Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just add a comment here detailing the assumption you're making? As I understand it, you're assuming that if there's any back stack at all here it's due to the trouble sending flow and you want to pop from the stack.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Done. 😃

// 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(
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
}
Expand All @@ -106,6 +114,7 @@ public void run() {
mTopLevelView.setVisibility(View.VISIBLE);
}
});
mEmailSent = true;
}

@Override
Expand Down Expand Up @@ -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 {
Expand Down