diff --git a/auth/README.md b/auth/README.md index 4fe4fc52f..5632b20b1 100644 --- a/auth/README.md +++ b/auth/README.md @@ -337,6 +337,61 @@ startActivityForResult( RC_SIGN_IN); ``` +##### Configuring Email Link Sign In + +To use email link sign in, you will first need to enable it in the Firebase Console. Additionally, you will +also have to enable Firebase Dynamic Links. + +You can enable email link sign in by calling the `enableEmailLinkSignIn` on an `EmailBuilder` instance. You will also need +to provide a valid `ActionCodeSettings` object with `setHandleCodeInApp` set to true. Additionally, you need to whitelist the +URL you pass to `setUrl`; you can do so in the Firebase Console (Authentication -> Sign in Methods -> Authorized domains). + +```java + +ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder() + .setAndroidPackageName(/*yourPackageName*/, /*installIfNotAvailable*/true, /*minimumVersion*/null) + .setHandleCodeInApp(true) + .setUrl("https://google.com") // This URL needs to be whitelisted + .build(); + +startActivityForResult( + AuthUI.getInstance() + .createSignInIntentBuilder() + .setAvailableProviders(Arrays.asList( + new AuthUI.IdpConfig.EmailBuilder().enableEmailLinkSignIn() + .setActionCodeSettings(actionCodeSettings).build()) + .build(), + RC_SIGN_IN); + +``` + +If you want to catch the link in a specific activity, please follow the steps outlined [here](https://firebase.google.com/docs/auth/android/email-link-auth). +Otherwise, the link will redirect to your launcher activity. + +Once you catch the deep link, you will need to call verify that we can handle it for you. If we can, you need to then +pass it to us via `setEmailLink`. + +```java +if (AuthUI.canHandleIntent(getIntent())) { + if (getIntent().getExtras() != null) { + return; + } + String link = getIntent().getExtras().getString(ExtraConstants.EMAIL_LINK_SIGN_IN); + if (link != null) { + startActivityForResult( + AuthUI.getInstance() + .createSignInIntentBuilder() + .setEmailLink(link) + .setAvailableProviders(getAvailableProviders()) + .build(), + RC_SIGN_IN); + } +} +``` + +Note that email link sign in is currently only supported for the same device. Finishing the flow on a different device will result +in the user being shown an error. + ##### Adding a ToS and privacy policy A terms of service URL and privacy policy URL are generally required: @@ -469,7 +524,6 @@ This change is purely UI based. We do not restrict users from signing in with th They will simply be unable to choose their country in the selector, but there may be another country sharing the same country code (e.g. US and CA are +1). - ##### ### Handling the sign-in response diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailActivity.java index 5d6a097b6..1fc2e9d3e 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailActivity.java @@ -173,11 +173,19 @@ public void onNewUser(User user) { public void onTroubleSigningIn(String email) { TroubleSigningInFragment troubleSigningInFragment = TroubleSigningInFragment.newInstance (email); - switchFragment(troubleSigningInFragment, TroubleSigningInFragment.TAG, true); + switchFragment(troubleSigningInFragment, TroubleSigningInFragment.TAG, true, true); } @Override public void onClickResendEmail(String email) { + if (getSupportFragmentManager().getBackStackEntryCount() > 0) { + // We're assuming that to get to the TroubleSigningInFragment, we went through + // the EmailLinkFragment, which was added to the fragment back stack. + // From here, we're going to register the EmailLinkFragment again, meaning we'd have to + // pop off the back stack twice to return to the nascar screen. To avoid this, + // we pre-emptively pop off the last EmailLinkFragment here. + getSupportFragmentManager().popBackStack(); + } AuthUI.IdpConfig emailConfig = ProviderUtils.getConfigFromIdpsOrThrow( getFlowParams().providers, EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD); showRegisterEmailLinkFragment( @@ -214,16 +222,24 @@ private void showRegisterEmailLinkFragment(AuthUI.IdpConfig emailConfig, } - private void switchFragment(Fragment fragment, String tag, boolean withTransition) { + private void switchFragment(Fragment fragment, + String tag, + boolean withTransition, + boolean addToBackStack) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); if (withTransition) { ft.setCustomAnimations(R.anim.fui_slide_in_right, R.anim.fui_slide_out_left); } - ft.replace(R.id.fragment_register_email, fragment, tag).disallowAddToBackStack().commit(); + ft.replace(R.id.fragment_register_email, fragment, tag); + if (addToBackStack) { + ft.addToBackStack(null).commit(); + } else { + ft.disallowAddToBackStack().commit(); + } } private void switchFragment(Fragment fragment, String tag) { - switchFragment(fragment, tag, false); + switchFragment(fragment, tag, false, false); } @Override diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailLinkFragment.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailLinkFragment.java index c4fd0cc93..9bdf52ac3 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailLinkFragment.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailLinkFragment.java @@ -34,6 +34,9 @@ public class EmailLinkFragment extends InvisibleFragmentBase { private TroubleSigningInListener mListener; private ScrollView mTopLevelView; + // Used to avoid sending a new email when popping off the fragment backstack + private boolean mEmailSent; + public static EmailLinkFragment newInstance(@NonNull final String email, @NonNull final ActionCodeSettings actionCodeSettings) { @@ -65,15 +68,20 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - // We need to hide the top level view until we know that the email link has been sent + if (savedInstanceState != null) { + mEmailSent = savedInstanceState.getBoolean(EMAIL_SENT); + } + mTopLevelView = view.findViewById(R.id.top_level_view); - mTopLevelView.setVisibility(View.GONE); + if (!mEmailSent) { + // We need to hide the top level view until we know that the email link has been sent + mTopLevelView.setVisibility(View.GONE); + } String email = getArguments().getString(ExtraConstants.EMAIL); setBodyText(view, email); setOnClickListeners(view, email); setPrivacyFooter(view); - } @Override @@ -85,7 +93,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { ActionCodeSettings actionCodeSettings = getArguments().getParcelable(ExtraConstants .ACTION_CODE_SETTINGS); - if (savedInstanceState == null || !savedInstanceState.getBoolean(EMAIL_SENT)) { + if (!mEmailSent) { mEmailLinkSendEmailHandler.sendSignInLinkToEmail(email, actionCodeSettings); } } @@ -106,6 +114,7 @@ public void run() { mTopLevelView.setVisibility(View.VISIBLE); } }); + mEmailSent = true; } @Override @@ -142,7 +151,7 @@ private void setPrivacyFooter(View view) { @Override public void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); - state.putBoolean(EMAIL_SENT, true); + state.putBoolean(EMAIL_SENT, mEmailSent); } interface TroubleSigningInListener {