linkEmailPassword method
Link anonymous account to email/password credentials
Converts an anonymous user to a permanent account while preserving the UID. After linking, the user can sign in with email/password on other devices.
Returns AuthServiceLinkFailure.emailAlreadyInUse if email is already registered. Returns AuthServiceLinkFailure.weakPassword if password is less than 6 characters.
Implementation
@override
Future<Either<AuthServiceLinkFailure, Unit>> linkEmailPassword(
String email,
String password,
) async {
try {
final user = _fbAuth.currentUser;
if (user == null) {
logw('linkEmailPassword: No user logged in');
return left(AuthServiceLinkFailure.userNotLoggedIn);
}
// Check if user already has email/password credential linked.
// We check for email provider instead of isAnonymous because users
// signed in with custom tokens (e.g., server-created anonymous users)
// have isAnonymous=false but should still be able to link email/password.
final hasEmailProvider = user.providerData.any(
(provider) => provider.providerId == 'password',
);
if (hasEmailProvider) {
logw('linkEmailPassword: User already has email/password linked');
return left(AuthServiceLinkFailure.credentialAlreadyInUse);
}
logd('linkEmailPassword: Linking account to email: $email');
// Create email/password credential
final credential = fb_auth.EmailAuthProvider.credential(
email: email,
password: password,
);
// Link the credential to the anonymous account
await user.linkWithCredential(credential);
logd('linkEmailPassword: Successfully linked account');
return right(unit);
} on fb_auth.FirebaseAuthException catch (e) {
loge(e, 'linkEmailPassword failed');
switch (e.code) {
case 'email-already-in-use':
return left(AuthServiceLinkFailure.emailAlreadyInUse);
case 'weak-password':
return left(AuthServiceLinkFailure.weakPassword);
case 'invalid-email':
return left(AuthServiceLinkFailure.invalidEmail);
case 'invalid-credential':
return left(AuthServiceLinkFailure.invalidCredential);
case 'credential-already-in-use':
return left(AuthServiceLinkFailure.credentialAlreadyInUse);
case 'requires-recent-login':
return left(AuthServiceLinkFailure.requiresRecentLogin);
default:
return left(AuthServiceLinkFailure.unexpected);
}
} catch (e) {
loge(e, 'linkEmailPassword failed');
return left(AuthServiceLinkFailure.unexpected);
}
}