-
Notifications
You must be signed in to change notification settings - Fork 135
Expand file tree
/
Copy pathauth_provider.dart
More file actions
154 lines (129 loc) · 4.95 KB
/
auth_provider.dart
File metadata and controls
154 lines (129 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// 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' as fba;
import 'package:flutter/material.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
/// Default error handler that starts MFA flow
/// if [FirebaseAuthMultiFactorException] is thrown.
void defaultOnAuthError(AuthProvider provider, Object error) {
if (error is! fba.FirebaseAuthException) {
throw error;
}
if (error is fba.FirebaseAuthMultiFactorException) {
provider.authListener.onMFARequired(error.resolver);
return;
}
throw error;
}
/// An interface that describes authentication process lifecycle.
///
/// See implementers:
/// - [EmailAuthListener]
/// - [EmailLinkAuthListener]
/// - [PhoneAuthListener]
abstract class AuthListener {
/// Current [AuthProvider] that is being used to authenticate the user.
AuthProvider get provider;
/// {@macro ui.auth.auth_controller.auth}
fba.FirebaseAuth get auth;
/// Called if an error occured during the authentication process.
void onError(Object error);
/// Called right before the authentication process starts.
void onBeforeSignIn();
/// Called if the user has successfully signed in.
void onSignedIn(fba.UserCredential credential);
/// Called before an attempt to link the credential with currently signed in
/// user account.
void onCredentialReceived(fba.AuthCredential credential);
/// Called if the credential was successfully linked with the user account.
void onCredentialLinked(fba.AuthCredential credential);
/// Called when the user cancels the sign in process.
void onCanceled();
/// Called when the user has to complete MFA.
void onMFARequired(fba.MultiFactorResolver resolver);
}
/// {@template ui.auth.auth_provider}
/// An interface that all auth providers should implement.
/// Contains shared authentication logic.
/// {@endtemplate}
abstract class AuthProvider<T extends AuthListener,
K extends fba.AuthCredential> {
/// {@macro ui.auth.auth_controller.auth}
late fba.FirebaseAuth auth;
/// {@template ui.auth.auth_provider.auth_listener}
/// An instance of the [AuthListener] that is used to notify about the
/// current state of the authentication process.
/// {@endtemplate}
T get authListener;
/// {@macro ui.auth.auth_provider.auth_listener}
set authListener(T listener);
/// {@template ui.auth.auth_provider.provider_id}
/// String identifer of the auth provider, for example: `'password'`,
/// `'phone'` or `'google.com'`.
/// {@endtemplate}
String get providerId;
/// Verifies that an [AuthProvider] is supported on a [platform].
bool supportsPlatform(TargetPlatform platform);
/// {@macro ui.auth.auth_provider}
AuthProvider();
/// Indicates whether the user should be upgraded and new credential should be
/// linked.
bool get shouldUpgradeAnonymous => auth.currentUser?.isAnonymous ?? false;
/// Signs the user in with the provided [AuthCredential].
void signInWithCredential(K credential) {
authListener.onBeforeSignIn();
auth
.signInWithCredential(credential)
.then(authListener.onSignedIn)
.catchError(authListener.onError);
}
/// Links a provided [AuthCredential] with the currently signed in user
/// account.
void linkWithCredential(K credential) {
authListener.onCredentialReceived(credential);
try {
final user = auth.currentUser!;
user
.linkWithCredential(credential)
.then((_) => authListener.onCredentialLinked(credential))
.catchError(authListener.onError);
} catch (err) {
authListener.onError(err);
}
}
/// {@template ui.auth.auth_provider.on_credential_received}
/// A method that is called when the user has successfully completed the
/// authentication process and decides what to do with the obtained
/// [credential].
///
/// [linkWithCredential] and respectful lifecycle hooks are called if [action]
/// is [AuthAction.link].
///
/// [signInWithCredential] and respectful lifecycle hooks are called
/// if [action] is [AuthAction.signIn].
///
/// [FirebaseAuth.createUserWithEmailAndPassword] and respectful lifecycle
/// hooks are called if action is [AuthAction.signUp].
/// {@endtemplate}
void onCredentialReceived(K credential, AuthAction action) {
switch (action) {
case AuthAction.link:
linkWithCredential(credential);
break;
case AuthAction.signIn:
// Only email provider has a different action for sign in and sign up
// and implements it's own sign up logic.
case AuthAction.signUp:
if (shouldUpgradeAnonymous) {
linkWithCredential(credential);
break;
}
signInWithCredential(credential);
break;
case AuthAction.none:
authListener.onCredentialReceived(credential);
break;
}
}
}