Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions, reduced motion, or target sizes; not language/culture/device (see inclusive-design).
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when setting up auth, managing auth state, implementing email/password or social sign-in, handling auth errors, or managing users.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
This skill defines how to correctly use Firebase Authentication in Flutter applications.
Use this skill when:
recaptcha-sdk-not-linked for phone auth).flutter pub add firebase_auth
import 'package:firebase_auth/firebase_auth.dart';
Local emulator for testing:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
// ...
}
Use the appropriate stream based on what you need to observe:
| Stream | Fires when |
|---|---|
authStateChanges() | User signs in or out |
idTokenChanges() | ID token changes (including custom claims) |
userChanges() | User data changes (e.g., profile updates) |
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});
Create a new account:
try {
final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: emailAddress,
password: password,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
Sign in:
try {
final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailAddress,
password: password,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'invalid-credential') {
// Email enumeration protection enabled (default since Sep 2023):
// replaces 'user-not-found' and 'wrong-password'.
print('Invalid email or password.');
} else if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
user-not-found and wrong-password with invalid-credential. Manage this in the Firebase console under Authentication > Settings.sendPasswordResetEmail() may complete without an error even if the email is not registered. Treat this as expected behavior and do not use password-reset responses to infer whether an email exists.Share authentication state between Apple apps:
On Apple platforms, share auth state between apps in the same developer account by storing it in a shared Keychain access group. Enable the Keychain Sharing capability for each app with the same access group, then configure Firebase Auth with the fully qualified access group:
await FirebaseAuth.instance.setSettings(
userAccessGroup: 'TEAMID.com.example.group1',
);
Switching from the default Keychain to a shared access group signs out the existing user unless migrated. Pass migrateCurrentUser: true (requires a non-null userAccessGroup) to preserve the current session, including an anonymous one — safe to call at app startup before any other Auth call, since it reads the existing session straight from the Keychain before Auth restores it. Migration can overwrite a user already stored in the destination access group.
Google Sign-In (native platforms):
Future<UserCredential> signInWithGoogle() async {
final GoogleSignInAccount? googleUser = await GoogleSignIn.instance.authenticate();
final GoogleSignInAuthentication googleAuth = googleUser.authentication;
final credential = GoogleAuthProvider.credential(idToken: googleAuth.idToken);
return await FirebaseAuth.instance.signInWithCredential(credential);
}
Google Sign-In (web):
Future<UserCredential> signInWithGoogle() async {
GoogleAuthProvider googleProvider = GoogleAuthProvider();
googleProvider.addScope('https://www.googleapis.com/auth/contacts.readonly');
googleProvider.setCustomParameters({'login_hint': 'user@example.com'});
return await FirebaseAuth.instance.signInWithPopup(googleProvider);
}
signInWithProvider opens a Chrome Custom Tab. If AndroidManifest.xml contains android:taskAffinity="" (Flutter's default), the tab closes when the user switches apps (e.g., to use a password manager), causing a web-context-already-presented error. Remove android:taskAffinity="" to fix this.email and name scopes to present the full first-time sign-in UI (including "Share/Hide email"):
final appleProvider = AppleAuthProvider();
appleProvider.addScope('email');
appleProvider.addScope('name');
revokeTokenWithAuthorizationCode() with the authorization code from userCredential.additionalUserInfo?.authorizationCode.revokeAccessToken() with the access token from userCredential.credential?.accessToken.// Apple platforms (iOS/macOS/web)
final authCode = userCredential.additionalUserInfo?.authorizationCode;
if (authCode != null) {
await FirebaseAuth.instance.revokeTokenWithAuthorizationCode(authCode);
}
// Android
final accessToken = userCredential.credential?.accessToken;
if (accessToken != null) {
await FirebaseAuth.instance.revokeAccessToken(accessToken);
}
Before using phone authentication, ensure platform-specific prerequisites are met:
Phone number sign-in is only supported on real devices and the web. Testing on device emulators is not supported.
iOS: recaptcha-sdk-not-linked error
On iOS, verifyPhoneNumber can throw FirebaseAuthException with code recaptcha-sdk-not-linked when Identity Platform expects reCAPTCHA Enterprise but the native SDK is not linked. This cannot be resolved from Dart — fix it at the native iOS or GCP level:
projects.updateConfig REST API (set recaptchaConfig.phoneEnforcementState to OFF and recaptchaConfig.useSmsTollFraudProtection to false). See the official steps. This reduces fraud protection — prefer linking the SDK.uni_links/app_links or application:openURL: in the iOS runner.try-catch with FirebaseAuthException.e.code to identify specific error types.account-exists-with-different-credential by fetching sign-in methods for the email and guiding users through the correct flow.too-many-requests with retry logic or user feedback.operation-not-allowed by ensuring the provider is enabled in the Firebase console.recaptcha-sdk-not-linked during verifyPhoneNumber is raised by the native Firebase iOS Auth SDK and requires native setup or GCP configuration changes — it cannot be fixed from Dart code alone.// Update profile
await FirebaseAuth.instance.currentUser?.updateProfile(
displayName: "Jane Q. User",
photoURL: "https://example.com/jane-q-user/profile.jpg",
);
// Update email (sends verification to new address first)
await user?.verifyBeforeUpdateEmail("newemail@example.com");
verifyBeforeUpdateEmail() — not updateEmail() — to change a user's email. The email only updates after the user verifies it.linkWithCredential() to connect multiple auth providers to a single account.fetchSignInMethodsForEmail() when handling account linking.FirebaseAuth.instance.signOut() when users exit the app.reauthenticateWithCredential().auth variable to get the signed-in user's UID for access control.Security warning: Avoid SMS-based MFA. SMS is insecure and easy to compromise or spoof.
Platform limitation: Windows does not support MFA. MFA with multiple tenants is not supported on Flutter.
Important: Firebase Dynamic Links is deprecated for email link authentication. Firebase Hosting is now used to send sign-in links.
handleCodeInApp: true in ActionCodeSettings — sign-in must always be completed in the app.SharedPreferences) when sending the sign-in link.아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions, reduced motion, or target sizes; not language/culture/device (see inclusive-design).
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when creating a feature, designing folder structure, adding repositories/services/view models, wiring dependency injection, or deciding which layer owns logic.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when creating a Cubit or Bloc, modeling state with sealed classes or status enums, wiring BlocBuilder/BlocListener/BlocProvider, writing bloc tests, or choosing between Cubit and Bloc.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when asked to review a PR, MR, branch, or diff, audit changed files, or check code quality.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when writing switch statements, refactoring if-else chains, creating data classes, choosing records vs classes, destructuring values, or modernizing pre-Dart-3 code.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when building AI agents in Dart, implementing Genkit flows or tools, integrating LLMs into Dart or Flutter applications, or using Genkit Dart plugins.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.