Skip to content

feat(ui_auth)!: complete email link sign in after cold start and on other devices - #710

Draft
demolaf wants to merge 5 commits into
mainfrom
fix/email-link-android
Draft

demolaf wants to merge 5 commits into
mainfrom
fix/email-link-android

Conversation

@demolaf

@demolaf demolaf commented Sep 23, 2026

Copy link
Copy Markdown
Member

Fixes #283.

Email link sign in now completes for a second link in the same session, for a link that launches the app after it was killed, and for a link opened on another device. Anonymous users can optionally be upgraded instead of replaced.

⚠️ Breaking Changes

EmailLinkAuthListener gains onEmailRequired(String link) and EmailLinkAuthController gains confirmEmail(String email), so classes implementing either must add them. The custom widget example in docs/firebase-ui-auth/providers/email-link.md shows both.

Changes

  • EmailLinkAuthProvider keeps a single app_links subscription. app_links closes its shared stream when the last listener cancels, which dropped the second link.
  • The email and a session id are stored with shared_preferences, and the session id is added to the link (ui_sid, ui_auid, as in FirebaseUI-Android). The link that launched the app is read with getInitialLink().
  • A link without a matching session emits a new EmailRequired state, and EmailLinkSignInView asks the user to confirm their email. The view also shows a spinner while a link signs in instead of the "link sent" message.
  • New upgradeAnonymousUsers option (off by default, as in FirebaseUI-Android) links the email to the current anonymous user with linkWithCredential. That link must be opened on the same device.
  • Docs and the example handle UserCreated and CredentialLinked alongside SignedIn (🐛 Email signing-up (register) not responsive (a case uncovered by current documentation) #351). The example's flutter_deeplinking_enabled flag moves onto the <activity>, where Flutter reads it.

API Usage

EmailLinkAuthProvider(
  actionCodeSettings: actionCodeSettings,
  upgradeAnonymousUsers: true, // optional, defaults to false
);

// Show EmailLinkSignInScreen when an email link launched the app.
final launchedFromSignInLink =
    await emailLinkProvider.isLaunchedFromSignInLink();

// In a custom AuthFlowBuilder<EmailLinkAuthController>.
if (state is EmailRequired) {
  return TextField(onSubmitted: ctrl.confirmEmail);
}

Preview

Android emulators against the Auth emulator. Links are delivered with adb because the Auth emulator does not send email.

Link opens the app after it was killed

The app is swiped away after the link is sent. Opening the link launches it, shows a spinner while signing in, and lands on the profile.

email_link_cold_start.mp4

Link opened on another device

Left: the phone that requested the link. Right: a second phone with nothing stored, which asks the user to confirm their email.

email_link_other_device.mp4

…ther devices

Keeps a single app link subscription so a second link is no longer dropped, persists the email and a session id so a link that launches the app completes sign in, asks the user to confirm their email when the link is opened on another device, and upgrades anonymous users instead of replacing them.

BREAKING CHANGE: EmailLinkAuthListener gains onEmailRequired and EmailLinkAuthController gains confirmEmail, so classes implementing either must add them.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements support for email link sign-in, enabling users to complete the authentication process even if the link is opened on a different device. Key changes include the introduction of session persistence using shared_preferences, updates to the UI flows to handle cross-device sign-in, and the addition of necessary localization strings. The reviewer identified several critical issues that need to be addressed, including invalid Dart syntax in map literals, a bug in the authentication instance handling that breaks multi-app support, and a logic flaw in link deduplication that prevents users from retrying the sign-in process.

Comment thread packages/firebase_ui_auth/lib/src/providers/email_link_session.dart
Comment thread packages/firebase_ui_auth/test/flows/email_link_flow_test.dart
Comment thread packages/firebase_ui_auth/test/flows/email_link_flow_test.dart
Comment thread packages/firebase_ui_auth/lib/src/providers/email_link_auth_provider.dart Outdated
…elated links

Adds EmailLinkAuthProvider.upgradeAnonymousUsers (default false, as in FirebaseUI-Android) so anonymous users can still sign in to an existing account. Other deep links are only reported once a link was requested, a link that failed can be opened again, dispose no longer re-reads the launch link, and confirming a link from another device keeps this device's pending session.
EmailLinkSignInView showed the "link sent" message while signing in and the email form again after success, which was confusing when a link launched the app. It now shows a loading indicator while signing in and keeps the form hidden once sign in succeeded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🐛firebase_ui_auth] Signin link open app but dont't trigger login

1 participant