4

I've been wracking my brain for weeks on this. I'm having trouble getting a custom password reset that has the user reset their password inside the app.

So far I'm able to do the following:

  1. Send the password reset email.
  2. When the user clicks the link, open the app if it's installed and direct them to the proper Activity.
  3. Confirm that my Dynamic Link will redirect to my website when put in a browser.
  4. Confirm that my Dynamic Link will redirect user to proper Activity when tested inside Android Studio (and return the deep link data).

The following are the issues that I'm running into:

  1. Clicking on the link in the password reset email on a desktop computer does NOT redirect me, but rather returns a web page error (error code 400).
  2. Clicking on the link in the password reset email in a phone takes me to the proper screen in the App but does NOT return any data, just null.
  3. If I click the link on a Nexus 6 (emulator or real phone) the redirect works, but if I click the link on a Nexus 5x (emulator) the redirect takes me to my login screen but not the correct Activity (No intent-filter is set for the login screen). All of these devices are running the same API (API 25).

I must be missing something, but I'm not sure what it could be. Here's my setup:

My detail link page in the Firebase Console (sensitive info redacted): enter image description here

The following code is the actionCodeSettings and password reset email code (sensitive stuff redacted):

String url = "https://xxxxx.com";
ActionCodeSettings settings = ActionCodeSettings.newBuilder()
        .setAndroidPackageName(
                getPackageName(),
                true, /* install if not available? */
                null   /* minimum app version */)
        .setHandleCodeInApp(true)
        .setUrl(url)
        .build();

mAuth.sendPasswordResetEmail(email, settings)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "Email sent.");
                    hideProgressDialog();
                    Toast.makeText(ForgotPasswordActivity.this, getString(R.string.alert_passwordResetConfirm),
                            Toast.LENGTH_SHORT).show();
                }
                else {
                    Exception e = task.getException();
                    Log.w(TAG, "passwordResetRequest:failure " + e.getMessage(), task.getException());
                    hideProgressDialog();
                    Toast.makeText(ForgotPasswordActivity.this, e.getMessage(),
                            Toast.LENGTH_SHORT).show();

                    if (e instanceof FirebaseAuthInvalidCredentialsException) {
                        emailText.setError(getString(R.string.validate_email));
                    }
                }
            }
        });

Android manifest xml stuff:

<intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:host="xxxxx.app.goo.gl" android:scheme="http"/>
        <data android:host="xxxxx.app.goo.gl" android:scheme="https"/>
    </intent-filter>

Code that grabs the deep link data when user returns to app:

FirebaseDynamicLinks.getInstance()
        .getDynamicLink(getIntent())
        .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
            @Override
            public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
                // Get deep link from result (may be null if no link is found)
                Uri deepLink = null;
                if (pendingDynamicLinkData != null) {
                    deepLink = pendingDynamicLinkData.getLink();
                }


                if (deepLink != null) {
                    Log.d(TAG, "Received Deep Link Data: " + deepLink.toString());
                }
                else {
                    Log.d(TAG, "Received Deep Link Data: " + null);
                }
                // Handle the deep link. For example, open the linked
                // content, or apply promotional credit to the user's
                // account.
                // ...

                // ...
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.w(TAG, "getDynamicLink:onFailure", e);
            }
        });

Finally, an example URL that the user would receive in their email:

https://xxxxx.app.goo.gl?link=https://xxxxx-00000.firebaseapp.com/__/auth/action?apiKey%<api key redacted>%26mode%3DresetPassword%26oobCode%3D<reset code redacted>%26continueUrl%3Dhttps://xxxxx.app.goo.gl/pass%26lang%3Den&apn=com.xxxxx.android

Any help would be greatly appreciated.

P.S. There is some mention in the docs that to get the deep data in the app we have call: FirebaseDynamicLinks.getDynamicLink() in the launcher activity as well as the deep link activity. I tried that as well...still got null data.

Additional Note: if I put the following in the activity that is opened by the deep link:

Intent intent = getIntent();
    String action = intent.getAction();
    Uri data = intent.getData();

    Log.d(TAG, "Data Data?: " + data.toString());

I get the full path that the user clicked to bring them to the app.

Thanks in advance for any help!

2 Answers 2

1

I didn't deep dive in your answer but i noticed a red flag as you are setting an FDL link as your deep link "https://xxxxx.app.goo.gl/pass"

// I speculate this is the root cause. You are ending up with a double
// dynamic link. Change this to a webpage you own.
String url = "https://xxxxx.app.goo.gl/pass";
ActionCodeSettings settings = ActionCodeSettings.newBuilder()
    .setAndroidPackageName(
            getPackageName(),
            true, /* install if not available? */
            null   /* minimum app version */)
    .setHandleCodeInApp(true)
    .setUrl(url)
    .build();
Sign up to request clarification or add additional context in comments.

9 Comments

Hi @bojeil thanks for the response. Unfortunately, that didn't seem to help. I tried with just my domain in the continueURL and all the same issues pop up. I get null data when trying to retrieve data from the deepLink inside the app and I cannot redirect to my app when I do this on a nexus 5x emulator (API 25)..basically all the issues that I outlined in this post.
Please update your answer above with your latest changes.
Can you try to isolate the cause? It seems like you are having issues with your FDL configuration. Try to create an FDL link with that *.app.goo.gl domain, add logic to intercept it with an intent filter and then click that link from a browser. Check that you are able to get the deep link from your app. If you can get this working, then you rule out any issue on the FDL side of things.
Hi @bojeil thanks for the response. I did create an DDL link wth the .app.goo.gl domain (please see screen grab at top of the post).
I did try something which might be a bug. I have 2 domains in my console: one that is .app.goo.gl the other is .page.link. I had the .gl one when I first created the account and when I was setting up the dynamic link I created the other (not knowing that apparently Google only sees the oldest one).
|
0

you have to create a custom action link from your server or it can be from a firebase cloud function. when you generate your action link you can add the domani of your dynamic link , so firebase will send you the action link based in your domain of dynamic link then it will be easier to retrive the params from the URL in your code.

https://firebase.google.com/docs/auth/admin/email-action-links

1 Comment

Could you please explain, step by step, how to implement your suggestion of using a Firebase Cloud Function? I'd appreciate it greatly if you could please post an answer to this question with detailed steps. MTIA :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.