Ready-to-use Firebase authentication UI for Flutter. Drop-in login and signup screens with email/password, Google Sign-In, and phone OTP — fully customisable via a single config object.
- ✅ Email / Password sign-in and sign-up
- ✅ Google Sign-In
- ✅ Phone OTP verification
- ✅ Auto tab-bar layout when multiple methods are enabled
- ✅ Fully customisable background — solid colour, gradient, image, or any widget
- ✅ Transparent header — blends into your own background
- ✅ Custom logo / icon in the header
- ✅ Custom colours for every UI element via
AuthColorScheme
- ✅ Custom validators for every input field
- ✅ Replace any individual field or button with your own widget
- ✅ No named routes required — navigation is callback-based
Add to your pubspec.yaml:
dependencies:
firebase_auth_kit: ^0.1.0
Then run:
flutter pub get
- Create a Firebase project at console.firebase.google.com
- Enable Authentication and the sign-in methods you need
- Add your app using the FlutterFire CLI:
dart pub global activate flutterfire_cli
flutterfire configure
- Initialise Firebase in
main():
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const MyApp());
}
import 'package:firebase_auth_kit/firebase_auth_kit.dart';
AuthLoginScreen(
config: const AuthUIConfig(
enableEmailPassword: true,
enableGoogle: true,
enableOtp: true,
),
onSuccess: () => Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const HomeScreen()),
),
onSignupTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (ctx) => AuthSignupScreen(
config: const AuthUIConfig(enableEmailPassword: true),
onSuccess: () => Navigator.pushAndRemoveUntil(
ctx,
MaterialPageRoute(builder: (_) => const HomeScreen()),
(_) => false,
),
onLoginTap: () => Navigator.pop(ctx),
),
),
),
)
Both screens are rendered as a Stack internally so you can place any background widget behind them.
Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
// Layer 0 — your background
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF4F46E5), Color(0xFF7C3AED)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
),
// Layer 1 — auth screen (transparent so background shows through)
AuthLoginScreen(
config: const AuthUIConfig(
enableEmailPassword: true,
backgroundColor: Colors.transparent,
headerBackground: BoxDecoration(color: Colors.transparent),
),
onSuccess: () { /* navigate to home */ },
),
],
),
)
Pass AuthUIConfig to the config parameter of AuthLoginScreen or AuthSignupScreen.
| Field |
Type |
Default |
Description |
enableEmailPassword |
bool |
true |
Show email/password sign-in |
enableGoogle |
bool |
false |
Show Google sign-in |
enableOtp |
bool |
false |
Show phone OTP sign-in |
| Field |
Type |
Description |
backgroundColor |
Color? |
Solid background colour |
backgroundGradient |
Gradient? |
Gradient background |
backgroundImage |
DecorationImage? |
Asset or network image background |
backgroundWidget |
Widget? |
Any widget as background (highest priority) |
Priority order: backgroundWidget → backgroundImage → backgroundGradient → backgroundColor → white (default)
| Field |
Type |
Default |
Description |
headerBackground |
Decoration? |
Blue gradient |
Header container decoration. Use BoxDecoration(color: Colors.transparent) to blend into your background |
headerBackgroundWidget |
Widget? |
— |
Widget drawn behind the header content |
headerLogoWidget |
Widget? |
Lock icon |
Replaces the default lock icon. Use SizedBox.shrink() to hide it |
headerTitleStyle |
TextStyle? |
White bold |
Text style for the title |
headerSubtitleStyle |
TextStyle? |
White regular |
Text style for the subtitle |
showHeaderDecorations |
bool |
true |
Set false to hide the decorative circle overlays |
Replace any individual UI element with your own widget:
| Field |
Replaces |
emailField |
Email input |
passwordField |
Password input |
nameField |
Name input (signup only) |
loginButton |
Sign In button |
signupButton |
Create Account button |
googleButton |
Google sign-in button |
phoneField |
Phone number input |
otpField |
OTP input boxes |
sendOtpButton |
Send OTP button |
verifyOtpButton |
Verify OTP button |
| Field |
Validates |
emailValidator |
String? Function(String?) |
passwordValidator |
String? Function(String?) |
nameValidator |
String? Function(String?) |
Pass to AuthUIConfig(colorScheme: AuthColorScheme(...)). Every field is optional — unset fields fall back to the default indigo/violet palette.
Brand #
| Field |
Type |
Description |
primary |
Color? |
Primary accent — focus borders, icons, links |
primaryLight |
Color? |
Secondary accent — gradient end, highlights |
primaryGradient |
LinearGradient? |
Full custom gradient for the action button |
| Field |
Type |
Description |
buttonColor |
Color? |
Solid button colour (used when no gradient set) |
buttonTextColor |
Color? |
Button label and spinner colour |
buttonShadowColor |
Color? |
Glow shadow under the button |
| Field |
Type |
Description |
cardColor |
Color? |
Form card background colour |
cardShadowColor |
Color? |
Card shadow tint |
| Field |
Type |
Description |
inputFillColor |
Color? |
Input background fill |
inputBorderColor |
Color? |
Unfocused input border |
inputFocusBorderColor |
Color? |
Focused input border |
inputFocusIconColor |
Color? |
Focused prefix icon and label colour |
| Field |
Type |
Description |
textPrimaryColor |
Color? |
Input values, headings |
textSecondaryColor |
Color? |
Subtitles, captions |
textHintColor |
Color? |
Placeholder and hint text |
linkColor |
Color? |
Tappable links ("Forgot password?", "Sign Up") |
| Field |
Type |
Description |
errorColor |
Color? |
Error text and icon |
errorContainerColor |
Color? |
Error banner background |
| Field |
Type |
Description |
otpIconColor |
Color? |
Phone/OTP icon circle colour |
AuthLoginScreen(
config: const AuthUIConfig(
enableEmailPassword: true,
backgroundColor: Color(0xFF0F172A),
headerBackground: BoxDecoration(color: Colors.transparent),
headerTitleStyle: TextStyle(color: Colors.white, fontSize: 28,
fontWeight: FontWeight.w800),
headerSubtitleStyle: TextStyle(color: Colors.white60),
headerLogoWidget: SizedBox.shrink(),
),
onSuccess: () { /* navigate */ },
)
AuthLoginScreen(
config: const AuthUIConfig(
enableEmailPassword: true,
backgroundImage: DecorationImage(
image: AssetImage('assets/bg.jpg'),
fit: BoxFit.cover,
),
headerBackground: BoxDecoration(color: Colors.transparent),
headerLogoWidget: SizedBox.shrink(),
),
onSuccess: () { /* navigate */ },
)
AuthLoginScreen(
config: const AuthUIConfig(
enableEmailPassword: true,
colorScheme: AuthColorScheme(
primary: Color(0xFF0D9488),
buttonColor: Color(0xFF0D9488),
buttonShadowColor: Color(0xFF0D9488),
inputFillColor: Color(0xFFF0FDFA),
inputBorderColor: Color(0xFF99F6E4),
inputFocusBorderColor: Color(0xFF0D9488),
linkColor: Color(0xFF0D9488),
cardColor: Colors.white,
textPrimaryColor: Color(0xFF134E4A),
),
),
onSuccess: () { /* navigate */ },
)
AuthLoginScreen(
config: AuthUIConfig(
enableEmailPassword: true,
headerLogoWidget: Image.asset('assets/logo.png', width: 52, height: 52),
colorScheme: const AuthColorScheme(
primaryGradient: LinearGradient(
colors: [Color(0xFFEC4899), Color(0xFFF97316)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
),
onSuccess: () { /* navigate */ },
)
AuthLoginScreen(
config: AuthUIConfig(
enableEmailPassword: true,
emailField: MyCustomEmailInput(),
loginButton: MyStyledButton(label: 'Log In', onTap: () {}),
),
onSuccess: () { /* navigate */ },
)
| Callback |
Type |
Description |
onSuccess |
VoidCallback? |
Called after successful login |
onSignupTap |
VoidCallback? |
Called when "Don't have an account?" is tapped. If null, the footer link is hidden |
| Callback |
Type |
Description |
onSuccess |
VoidCallback? |
Called after successful signup |
onLoginTap |
VoidCallback? |
Called when "Already have an account?" is tapped. If null, the footer link is hidden |
Use AuthController directly if you need to build your own UI:
final auth = AuthController();
// Email/password
await auth.login(email: 'user@example.com', password: 'pass');
await auth.signUp(name: 'John', email: 'user@example.com', password: 'pass');
// Google
await auth.loginWithGoogle();
// OTP
await auth.sendOTP(phone: '+1234567890', onCodeSent: (id) { });
await auth.verifyOTP(verificationId: id, code: '123456');
// Sign out
await auth.logout();
// Auth state stream
auth.authState.listen((user) { });
MIT