Skip to content
Development
Skill

/firebase-auth

Use when setting up auth, managing auth state, implementing email/password or social sign-in, handling auth errors, or managing users.

From plugin
flutter-ai-skills
67036 skills

Claude Code

$ npx -y skills add evanca/flutter-ai-rules --skill firebase-auth --agent claude-code

SKILL.md

firebase-auth.SKILL.md
name: firebase-auth
description: "Use when setting up auth, managing auth state, implementing email/password or social sign-in, handling auth errors, or managing users."
license: MIT

Firebase Authentication Skill

This skill defines how to correctly use Firebase Authentication in Flutter applications.

When to Use

Use this skill when:

  • Setting up Firebase Authentication in a Flutter project.
  • Listening to authentication state changes.
  • Implementing email/password, phone number, or social sign-in.
  • Managing user profiles, account linking, or MFA.
  • Handling authentication errors (including iOS `recaptcha-sdk-not-linked` for phone auth).
  • Applying security best practices for auth flows.

---

1. Setup and Configuration

flutter pub add firebase_auth
import 'package:firebase_auth/firebase_auth.dart';
  • Enable desired authentication providers in the **Firebase console** before using them.
  • Initialize Firebase before using any Firebase Authentication features.

**Local emulator for testing:**

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
  // ...
}

---

2. Authentication State Management

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!');
    }
  });
  • Listen to these streams **immediately** when the app starts to handle the initial auth state.
  • Custom claims are only available after sign-in, re-authentication, token expiration, or manual token refresh.

---

3. Email and Password Authentication

**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) {
  final String error = switch (e.code) {
    'invalid-email' => 'The email address is not valid.',
    // Email enumeration protection (default since Sep 2023) reports
    // 'invalid-credential' instead of 'user-not-found' / 'wrong-password';
    // older native SDKs report 'invalid-login-credentials'. Handle all four so
    // the app works with the setting on or off.
    'invalid-credential' ||
    'invalid-login-credentials' ||
    'user-not-found' ||
    'wrong-password' =>
      'The email address or password is incorrect.',
    'user-disabled' => 'This account has been disabled.',
    'too-many-requests' ||
    'network-request-failed' =>
      'Something went wrong. Try again later.',
    // Always keep a default branch — codes differ by platform and SDK version
    // (for example Windows reports 'unknown-error' for a wrong password).
    _ => 'Sign-in failed (${e.code}).',
  };
  print(error);
}
  • Verify the user's email address after account creation.
  • Firebase rate-limits new email/password sign-ups from the same IP to protect against abuse.
  • On iOS/macOS, authentication state persists between app re-installs via the system keychain.
  • Since September 2023, Firebase enables **email enumeration protection** by default on new projects, replacing `user-not-found` and `wrong-password` with `invalid-credential`. Manage this in the Firebase console under **Authentication > Settings**.
  • When email enumeration protection is enabled, `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.

---

4. Social Authentication

**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'});
  r
Read more
@evanca
Ships withflutter-ai-skills

36 Flutter and Dart skills your coding agent loads by itself, sourced only from official documentation. A skill is a folder with a SKILL.md file.

Stars on GitHub

Momentum

stars in total
670
Star history of evanca/flutter-ai-rules on GitHub, a chart by star-history.com

Other skills on flutter-ai-skills.

accessibility

accessibility

Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions,…

bloc

bloc

Use when creating a Cubit or Bloc, modeling state with sealed classes or status enums, wiring…

dart-3-updates

dart-3-updates

Use when writing switch statements, refactoring if-else chains, creating data classes, choosing records vs classes, destructuring…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about firebase-auth.

Which coding agents can use firebase-auth?
firebase-auth installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.