-
Notifications
You must be signed in to change notification settings - Fork 136
Expand file tree
/
Copy pathphone_auth_flow.dart
More file actions
223 lines (192 loc) · 6.89 KB
/
phone_auth_flow.dart
File metadata and controls
223 lines (192 loc) · 6.89 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// 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/widgets.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
/// An [AuthState] that indicates that [PhoneAuthFlow] is not yet initialized
/// wuth the phone number. UI should provide a way to submit a phone number.
class AwaitingPhoneNumber extends AuthState {}
/// An [AuthState] that indicates that the phone number was submitted and the SMS
/// code is being sent. UIs often reflect this state with a loading indicator.
class SMSCodeRequested extends AuthState {
/// The phone number that was submitted.
final String phoneNumber;
const SMSCodeRequested(this.phoneNumber);
}
/// An [AuthState] that indicates that the SMS code was sucessfully veriied and
/// a [fba.AuthCredential] was obtained.
class PhoneVerified extends AuthState {
/// An [fba.AuthCredential] that was obtained during authentication process.
final fba.AuthCredential credential;
PhoneVerified(this.credential);
}
/// Indicates that the phone verification failed.
/// [exception] contains the details describing what exactly went wrong.
class PhoneVerificationFailed extends AuthState {
/// A [fba.FirebaseAuthException] that contains the details about the error.
final fba.FirebaseAuthException exception;
PhoneVerificationFailed(this.exception);
}
/// {@template ui.auth.flows.phone_auth_flow}
/// A state that indicates that the SMS code was successfully sent and the user
/// should submit it. UI should provide a way to submit the SMS code.
/// {@endtemplate}
class SMSCodeSent extends AuthState {
/// Verification ID that should be used to verify the phone number.
String? verificationId;
/// A token that should be used to trigger another send attempt.
final int? resendToken;
/// Web-only object that is being used to verify the phone number.
fba.ConfirmationResult? confirmationResult;
/// {@macro ui.auth.flows.phone_auth_flow}
SMSCodeSent({this.verificationId, this.resendToken, this.confirmationResult});
}
/// {@template ui.auth.flows.autoresolution_failed_exception}
/// A state that indicates that autoresolution has failed.
/// This doesn't necessarily mean that the code was invalid, sometimes
/// a device doesn't support SMS code autoresolution.
/// {@endtemplate}
class AutoresolutionFailedException implements Exception {
final String message;
/// {@macro ui.auth.flows.autoresolution_failed_exception}
AutoresolutionFailedException([
this.message = 'SMS code autoresolution failed',
]);
}
/// A controller interface of the [PhoneAuthFlow].
abstract class PhoneAuthController extends AuthController {
/// Initializes the flow with a phone number. This method should be called
/// after user submits a phone number.
void acceptPhoneNumber(
String phoneNumber, [
fba.MultiFactorSession? multiFactorSession,
]);
/// Triggers an SMS code verification.
void verifySMSCode(
String code, {
String? verificationId,
fba.ConfirmationResult? confirmationResult,
});
}
/// {@template ui.auth.flows.phone_auth_flow}
/// An auth flow that allows authentication with a phone number.
/// {@endtemplate}
class PhoneAuthFlow extends AuthFlow<PhoneAuthProvider>
implements PhoneAuthController, PhoneAuthListener {
/// A verification ID that is being used to verify the phone number.
/// Not available on web, [confirmationResult] should be used instead.
String? verificationId;
/// Web-only object that should be used to verify the phone number.
fba.ConfirmationResult? confirmationResult;
/// {@macro ui.auth.flows.phone_auth_flow}
PhoneAuthFlow({
/// {@macro ui.auth.auth_flow.ctor.provider}
required super.provider,
/// {@macro ui.auth.auth_controller.auth}
super.auth,
/// {@macro ui.auth.auth_action}
super.action,
}) : super(initialState: AwaitingPhoneNumber());
@override
void acceptPhoneNumber(
String phoneNumber, [
fba.MultiFactorSession? multiFactorSession,
]) {
provider.sendVerificationCode(
phoneNumber: phoneNumber,
action: action,
multiFactorSession: multiFactorSession,
);
}
@override
void verifySMSCode(
String code, {
String? verificationId,
fba.ConfirmationResult? confirmationResult,
fba.MultiFactorSession? multiFactorSession,
}) {
provider.verifySMSCode(
action: action,
code: code,
verificationId: verificationId,
confirmationResult: confirmationResult,
);
}
@override
void onCodeSent(String verificationId, [int? forceResendToken]) {
value = SMSCodeSent(
verificationId: verificationId,
resendToken: forceResendToken,
);
}
@override
void onSMSCodeRequested(String phoneNumber) {
value = SMSCodeRequested(phoneNumber);
}
@override
void onVerificationCompleted(fba.PhoneAuthCredential credential) {
value = PhoneVerified(credential);
provider.onCredentialReceived(credential, action);
}
@override
void onConfirmationRequested(fba.ConfirmationResult result) {
value = SMSCodeSent(confirmationResult: result);
}
}
/// {@template ui.auth.flows.phone_auth_flow.verify_phone_number}
/// An action that is called when user requests a sign in with the phone number.
/// Could be used to show a [PhoneInputScreen] or trigger a custom
/// logic:
///
/// ```dart
/// SignInScreen(
/// actions: [
/// VerifyPhoneAction((context, action) {
/// Navigator.of(context).push(
/// MaterialPageRoute(
/// builder: (context) => PhoneInputScreen(),
/// ),
/// );
/// }),
/// ]
/// );
/// ```
/// {@endtemplate}
class VerifyPhoneAction extends FirebaseUIAction {
/// A callback that is being called when the user requests a sign in with the
/// phone number.
final void Function(BuildContext context, AuthAction? action) callback;
/// {@macro ui.auth.flows.phone_auth_flow.verify_phone_number}
VerifyPhoneAction(this.callback);
}
/// {@template ui.auth.flows.phone_auth_flow.sms_code_requested_action}
/// An action that is called when user requests a sign in with the phone number.
/// Could be used to show a [SMSCodeInputScreen] or trigger a custom
/// logic:
///
/// ```dart
/// SignInScreen(
/// actions: [
/// SMSCodeRequestedAction((context, action, flowKey, phoneNumber) {
/// Navigator.of(context).push(
/// MaterialPageRoute(
/// builder: (context) => SMSCodeInputScreen(),
/// ),
/// );
/// }),
/// ]
/// );
/// ```
/// {@endtemplate}
class SMSCodeRequestedAction extends FirebaseUIAction {
final void Function(
BuildContext context,
AuthAction? action,
Object flowKey,
String phoneNumber,
)
callback;
/// {@macro ui.auth.flows.phone_auth_flow.sms_code_requested_action}
SMSCodeRequestedAction(this.callback);
}