firebase_ui_auth 1.14.0 firebase_ui_auth: ^1.14.0 copied to clipboard
Pre-built widgets library that are integrated with the variety of the Firebase Auth providers.
// Copyright 2022, the Chromium project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:firebase_auth/firebase_auth.dart'
hide PhoneAuthProvider, EmailAuthProvider;
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_localizations/firebase_ui_localizations.dart';
import 'package:firebase_ui_oauth_apple/firebase_ui_oauth_apple.dart';
import 'package:firebase_ui_oauth_facebook/firebase_ui_oauth_facebook.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart';
import 'package:firebase_ui_oauth_twitter/firebase_ui_oauth_twitter.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'config.dart';
import 'decorations.dart';
import 'firebase_options.dart';
final actionCodeSettings = ActionCodeSettings(
url: 'https://flutterfire-e2e-tests.firebaseapp.com',
handleCodeInApp: true,
androidMinimumVersion: '1',
androidPackageName: 'io.flutter.plugins.firebase_ui.firebase_ui_example',
iOSBundleId: 'io.flutter.plugins.fireabaseUiExample',
);
final emailLinkProviderConfig = EmailLinkAuthProvider(
actionCodeSettings: actionCodeSettings,
);
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
FirebaseUIAuth.configureProviders([
EmailAuthProvider(),
emailLinkProviderConfig,
PhoneAuthProvider(),
GoogleProvider(clientId: GOOGLE_CLIENT_ID),
AppleProvider(),
FacebookProvider(clientId: FACEBOOK_CLIENT_ID),
TwitterProvider(
apiKey: TWITTER_API_KEY,
apiSecretKey: TWITTER_API_SECRET_KEY,
redirectUri: TWITTER_REDIRECT_URI,
),
]);
runApp(const FirebaseAuthUIExample());
}
// Overrides a label for en locale
// To add localization for a custom language follow the guide here:
// https://flutter.dev/docs/development/accessibility-and-localization/internationalization#an-alternative-class-for-the-apps-localized-resources
class LabelOverrides extends DefaultLocalizations {
const LabelOverrides();
@override
String get emailInputLabel => 'Enter your email';
}
class FirebaseAuthUIExample extends StatelessWidget {
const FirebaseAuthUIExample({super.key});
String get initialRoute {
final user = FirebaseAuth.instance.currentUser;
return switch (user) {
null => '/',
User(emailVerified: false, email: final String _) => '/verify-email',
_ => '/profile',
};
}
@override
Widget build(BuildContext context) {
final buttonStyle = ButtonStyle(
padding: MaterialStateProperty.all(const EdgeInsets.all(12)),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
);
final mfaAction = AuthStateChangeAction<MFARequired>(
(context, state) async {
final nav = Navigator.of(context);
await startMFAVerification(
resolver: state.resolver,
context: context,
);
nav.pushReplacementNamed('/profile');
},
);
return MaterialApp(
theme: ThemeData(
brightness: Brightness.light,
visualDensity: VisualDensity.standard,
useMaterial3: true,
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
),
elevatedButtonTheme: ElevatedButtonThemeData(style: buttonStyle),
textButtonTheme: TextButtonThemeData(style: buttonStyle),
outlinedButtonTheme: OutlinedButtonThemeData(style: buttonStyle),
),
initialRoute: initialRoute,
routes: {
'/': (context) {
return SignInScreen(
actions: [
ForgotPasswordAction((context, email) {
Navigator.pushNamed(
context,
'/forgot-password',
arguments: {'email': email},
);
}),
VerifyPhoneAction((context, _) {
Navigator.pushNamed(context, '/phone');
}),
AuthStateChangeAction((context, state) {
final user = switch (state) {
SignedIn(user: final user) => user,
CredentialLinked(user: final user) => user,
UserCreated(credential: final cred) => cred.user,
_ => null,
};
switch (user) {
case User(emailVerified: true):
Navigator.pushReplacementNamed(context, '/profile');
case User(emailVerified: false, email: final String _):
Navigator.pushNamed(context, '/verify-email');
}
}),
mfaAction,
EmailLinkSignInAction((context) {
Navigator.pushReplacementNamed(context, '/email-link-sign-in');
}),
],
styles: const {
EmailFormStyle(signInButtonVariant: ButtonVariant.filled),
},
headerBuilder: headerImage('assets/images/flutterfire_logo.png'),
sideBuilder: sideImage('assets/images/flutterfire_logo.png'),
subtitleBuilder: (context, action) {
final actionText = switch (action) {
AuthAction.signIn => 'Please sign in to continue.',
AuthAction.signUp => 'Please create an account to continue',
_ => throw Exception('Invalid action: $action'),
};
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text('Welcome to Firebase UI! $actionText.'),
);
},
footerBuilder: (context, action) {
final actionText = switch (action) {
AuthAction.signIn => 'signing in',
AuthAction.signUp => 'registering',
_ => throw Exception('Invalid action: $action'),
};
return Center(
child: Padding(
padding: const EdgeInsets.only(top: 16),
child: Text(
'By $actionText, you agree to our terms and conditions.',
style: const TextStyle(color: Colors.grey),
),
),
);
},
);
},
'/verify-email': (context) {
return EmailVerificationScreen(
headerBuilder: headerIcon(Icons.verified),
sideBuilder: sideIcon(Icons.verified),
actionCodeSettings: actionCodeSettings,
actions: [
EmailVerifiedAction(() {
Navigator.pushReplacementNamed(context, '/profile');
}),
AuthCancelledAction((context) {
FirebaseUIAuth.signOut(context: context);
Navigator.pushReplacementNamed(context, '/');
}),
],
);
},
'/phone': (context) {
return PhoneInputScreen(
actions: [
SMSCodeRequestedAction((context, action, flowKey, phone) {
Navigator.of(context).pushReplacementNamed(
'/sms',
arguments: {
'action': action,
'flowKey': flowKey,
'phone': phone,
},
);
}),
],
headerBuilder: headerIcon(Icons.phone),
sideBuilder: sideIcon(Icons.phone),
);
},
'/sms': (context) {
final arguments = ModalRoute.of(context)?.settings.arguments
as Map<String, dynamic>?;
return SMSCodeInputScreen(
actions: [
AuthStateChangeAction<SignedIn>((context, state) {
Navigator.of(context).pushReplacementNamed('/profile');
})
],
flowKey: arguments?['flowKey'],
action: arguments?['action'],
headerBuilder: headerIcon(Icons.sms_outlined),
sideBuilder: sideIcon(Icons.sms_outlined),
);
},
'/forgot-password': (context) {
final arguments = ModalRoute.of(context)?.settings.arguments
as Map<String, dynamic>?;
return ForgotPasswordScreen(
email: arguments?['email'],
headerMaxExtent: 200,
headerBuilder: headerIcon(Icons.lock),
sideBuilder: sideIcon(Icons.lock),
);
},
'/email-link-sign-in': (context) {
return EmailLinkSignInScreen(
actions: [
AuthStateChangeAction<SignedIn>((context, state) {
Navigator.pushReplacementNamed(context, '/');
}),
],
provider: emailLinkProviderConfig,
headerMaxExtent: 200,
headerBuilder: headerIcon(Icons.link),
sideBuilder: sideIcon(Icons.link),
);
},
'/profile': (context) {
final platform = Theme.of(context).platform;
return ProfileScreen(
actions: [
SignedOutAction((context) {
Navigator.pushReplacementNamed(context, '/');
}),
mfaAction,
],
actionCodeSettings: actionCodeSettings,
showMFATile: kIsWeb ||
platform == TargetPlatform.iOS ||
platform == TargetPlatform.android,
showUnlinkConfirmationDialog: true,
showDeleteConfirmationDialog: true,
);
},
},
title: 'Firebase UI demo',
debugShowCheckedModeBanner: false,
supportedLocales: const [Locale('en')],
localizationsDelegates: [
FirebaseUILocalizations.withDefaultOverrides(const LabelOverrides()),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
FirebaseUILocalizations.delegate,
],
);
}
}