Skip to content

Commit cc7353b

Browse files
[firebase_auth] Update auth methods to return AuthResult instead of FirebaseUser (#1911)
* Sign-in methods now return `AuthResult` instead of `FirebaseUser`. * Change `reauthenticateWithCredential` to return AuthResult as well * Update tests
1 parent 495a6da commit cc7353b

File tree

14 files changed

+288
-140
lines changed

14 files changed

+288
-140
lines changed

packages/firebase_auth/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.12.0
2+
3+
* Added new `AuthResult` and `AdditionalUserInfo` classes.
4+
* **Breaking Change**. Sign-in methods now return `AuthResult` instead of `FirebaseUser`.
5+
Retrieve the `FirebaseUser` using the `user` property of `AuthResult`.
6+
17
## 0.11.1+12
28

39
* Update google-services Android gradle plugin to 4.3.0 in documentation and examples.

packages/firebase_auth/android/src/main/java/io/flutter/plugins/firebaseauth/FirebaseAuthPlugin.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.google.firebase.FirebaseNetworkException;
1717
import com.google.firebase.FirebaseTooManyRequestsException;
1818
import com.google.firebase.auth.ActionCodeSettings;
19+
import com.google.firebase.auth.AdditionalUserInfo;
1920
import com.google.firebase.auth.AuthCredential;
2021
import com.google.firebase.auth.AuthResult;
2122
import com.google.firebase.auth.EmailAuthProvider;
@@ -669,9 +670,15 @@ public void onComplete(@NonNull Task<AuthResult> task) {
669670
if (!task.isSuccessful() || task.getResult() == null) {
670671
reportException(result, task.getException());
671672
} else {
672-
FirebaseUser user = task.getResult().getUser();
673-
Map<String, Object> userMap = Collections.unmodifiableMap(mapFromUser(user));
674-
result.success(userMap);
673+
AuthResult authResult = task.getResult();
674+
FirebaseUser user = authResult.getUser();
675+
AdditionalUserInfo additionalUserInfo = authResult.getAdditionalUserInfo();
676+
Map<String, Object> userMap = (mapFromUser(user));
677+
Map<String, Object> additionalUserInfoMap = mapFromAdditionalUserInfo(additionalUserInfo);
678+
Map<String, Object> map = new HashMap<>();
679+
map.put("user", userMap);
680+
map.put("additionalUserInfo", additionalUserInfoMap);
681+
result.success(Collections.unmodifiableMap(map));
675682
}
676683
}
677684
}
@@ -752,6 +759,19 @@ private Map<String, Object> mapFromUser(FirebaseUser user) {
752759
}
753760
}
754761

762+
private Map<String, Object> mapFromAdditionalUserInfo(AdditionalUserInfo info) {
763+
if (info != null) {
764+
Map<String, Object> additionalUserInfoMap = new HashMap<>();
765+
additionalUserInfoMap.put("profile", info.getProfile());
766+
additionalUserInfoMap.put("providerId", info.getProviderId());
767+
additionalUserInfoMap.put("username", info.getUsername());
768+
additionalUserInfoMap.put("isNewUser", info.isNewUser());
769+
return Collections.unmodifiableMap(additionalUserInfoMap);
770+
} else {
771+
return null;
772+
}
773+
}
774+
755775
private void markUserRequired(Result result) {
756776
result.error("USER_REQUIRED", "Please authenticate with Firebase first", null);
757777
}

packages/firebase_auth/example/lib/register_page.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,11 @@ class RegisterPageState extends State<RegisterPage> {
8282

8383
// Example code for registration.
8484
void _register() async {
85-
final FirebaseUser user = await _auth.createUserWithEmailAndPassword(
85+
final FirebaseUser user = (await _auth.createUserWithEmailAndPassword(
8686
email: _emailController.text,
8787
password: _passwordController.text,
88-
);
88+
))
89+
.user;
8990
if (user != null) {
9091
setState(() {
9192
_success = true;

packages/firebase_auth/example/lib/signin_page.dart

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,11 @@ class _EmailPasswordFormState extends State<_EmailPasswordForm> {
145145

146146
// Example code of how to sign in with email and password.
147147
void _signInWithEmailAndPassword() async {
148-
final FirebaseUser user = await _auth.signInWithEmailAndPassword(
148+
final FirebaseUser user = (await _auth.signInWithEmailAndPassword(
149149
email: _emailController.text,
150150
password: _passwordController.text,
151-
);
151+
))
152+
.user;
152153
if (user != null) {
153154
setState(() {
154155
_success = true;
@@ -193,10 +194,11 @@ class _EmailLinkSignInSectionState extends State<_EmailLinkSignInSection>
193194
final Uri link = await _retrieveDynamicLink();
194195

195196
if (link != null) {
196-
final FirebaseUser user = await _auth.signInWithEmailAndLink(
197+
final FirebaseUser user = (await _auth.signInWithEmailAndLink(
197198
email: _userEmail,
198199
link: link.toString(),
199-
);
200+
))
201+
.user;
200202

201203
if (user != null) {
202204
_userID = user.uid;
@@ -330,7 +332,7 @@ class _AnonymouslySignInSectionState extends State<_AnonymouslySignInSection> {
330332

331333
// Example code of how to sign in anonymously.
332334
void _signInAnonymously() async {
333-
final FirebaseUser user = await _auth.signInAnonymously();
335+
final FirebaseUser user = (await _auth.signInAnonymously()).user;
334336
assert(user != null);
335337
assert(user.isAnonymous);
336338
assert(!user.isEmailVerified);
@@ -413,7 +415,8 @@ class _GoogleSignInSectionState extends State<_GoogleSignInSection> {
413415
accessToken: googleAuth.accessToken,
414416
idToken: googleAuth.idToken,
415417
);
416-
final FirebaseUser user = await _auth.signInWithCredential(credential);
418+
final FirebaseUser user =
419+
(await _auth.signInWithCredential(credential)).user;
417420
assert(user.email != null);
418421
assert(user.displayName != null);
419422
assert(!user.isAnonymous);
@@ -554,7 +557,8 @@ class _PhoneSignInSectionState extends State<_PhoneSignInSection> {
554557
verificationId: _verificationId,
555558
smsCode: _smsController.text,
556559
);
557-
final FirebaseUser user = await _auth.signInWithCredential(credential);
560+
final FirebaseUser user =
561+
(await _auth.signInWithCredential(credential)).user;
558562
final FirebaseUser currentUser = await _auth.currentUser();
559563
assert(user.uid == currentUser.uid);
560564
setState(() {
@@ -698,7 +702,8 @@ class _OtherProvidersSignInSectionState
698702
final AuthCredential credential = GithubAuthProvider.getCredential(
699703
token: _tokenController.text,
700704
);
701-
final FirebaseUser user = await _auth.signInWithCredential(credential);
705+
final FirebaseUser user =
706+
(await _auth.signInWithCredential(credential)).user;
702707
assert(user.email != null);
703708
assert(user.displayName != null);
704709
assert(!user.isAnonymous);
@@ -720,7 +725,8 @@ class _OtherProvidersSignInSectionState
720725
final AuthCredential credential = FacebookAuthProvider.getCredential(
721726
accessToken: _tokenController.text,
722727
);
723-
final FirebaseUser user = await _auth.signInWithCredential(credential);
728+
final FirebaseUser user =
729+
(await _auth.signInWithCredential(credential)).user;
724730
assert(user.email != null);
725731
assert(user.displayName != null);
726732
assert(!user.isAnonymous);
@@ -742,7 +748,8 @@ class _OtherProvidersSignInSectionState
742748
final AuthCredential credential = TwitterAuthProvider.getCredential(
743749
authToken: _tokenController.text,
744750
authTokenSecret: _tokenSecretController.text);
745-
final FirebaseUser user = await _auth.signInWithCredential(credential);
751+
final FirebaseUser user =
752+
(await _auth.signInWithCredential(credential)).user;
746753
assert(user.email != null);
747754
assert(user.displayName != null);
748755
assert(!user.isAnonymous);

packages/firebase_auth/example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ dependencies:
88
firebase_auth:
99
path: ../
1010
google_sign_in: ^4.0.0
11-
firebase_core: ^0.4.0
11+
firebase_core: ^0.4.0+8
1212
firebase_dynamic_links: ^0.3.0
1313

1414
dev_dependencies:

packages/firebase_auth/example/test/firebase_auth.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@ void main() {
1616
final FirebaseAuth auth = FirebaseAuth.instance;
1717

1818
test('signInAnonymously', () async {
19-
final FirebaseUser user = await auth.signInAnonymously();
19+
final AuthResult result = await auth.signInAnonymously();
20+
final FirebaseUser user = result.user;
2021
expect(user.uid, isNotNull);
2122
expect(user.isAnonymous, isTrue);
23+
final AdditionalUserInfo additionalUserInfo = result.additionalUserInfo;
24+
expect(additionalUserInfo.username, isNull);
25+
expect(additionalUserInfo.isNewUser, isNotNull);
26+
expect(additionalUserInfo.profile, isNull);
27+
expect(additionalUserInfo.providerId, isNull);
2228
});
2329

2430
test('isSignInWithEmailLink', () async {

packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,15 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
107107
} else if ([@"signInAnonymously" isEqualToString:call.method]) {
108108
[[self getAuth:call.arguments]
109109
signInAnonymouslyWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) {
110-
[self sendResult:result forUser:authResult.user error:error];
110+
[self sendResult:result forAuthDataResult:authResult error:error];
111111
}];
112112
} else if ([@"signInWithCredential" isEqualToString:call.method]) {
113113
[[self getAuth:call.arguments]
114114
signInAndRetrieveDataWithCredential:[self getCredential:call.arguments]
115115
completion:^(FIRAuthDataResult *authResult, NSError *error) {
116-
[self sendResult:result forUser:authResult.user error:error];
116+
[self sendResult:result
117+
forAuthDataResult:authResult
118+
error:error];
117119
}];
118120
} else if ([@"createUserWithEmailAndPassword" isEqualToString:call.method]) {
119121
NSString *email = call.arguments[@"email"];
@@ -122,7 +124,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
122124
createUserWithEmail:email
123125
password:password
124126
completion:^(FIRAuthDataResult *authResult, NSError *error) {
125-
[self sendResult:result forUser:authResult.user error:error];
127+
[self sendResult:result forAuthDataResult:authResult error:error];
126128
}];
127129
} else if ([@"fetchSignInMethodsForEmail" isEqualToString:call.method]) {
128130
NSString *email = call.arguments[@"email"];
@@ -177,7 +179,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
177179
signInWithEmail:email
178180
link:link
179181
completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
180-
[self sendResult:result forUser:authResult.user error:error];
182+
[self sendResult:result forAuthDataResult:authResult error:error];
181183
}];
182184
} else if ([@"signInWithEmailAndPassword" isEqualToString:call.method]) {
183185
NSString *email = call.arguments[@"email"];
@@ -186,7 +188,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
186188
signInWithEmail:email
187189
password:password
188190
completion:^(FIRAuthDataResult *authResult, NSError *error) {
189-
[self sendResult:result forUser:authResult.user error:error];
191+
[self sendResult:result forAuthDataResult:authResult error:error];
190192
}];
191193
} else if ([@"signOut" isEqualToString:call.method]) {
192194
NSError *signOutError;
@@ -215,8 +217,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
215217
} else if ([@"linkWithCredential" isEqualToString:call.method]) {
216218
[[self getAuth:call.arguments].currentUser
217219
linkAndRetrieveDataWithCredential:[self getCredential:call.arguments]
218-
completion:^(FIRAuthDataResult *r, NSError *error) {
219-
[self sendResult:result forUser:r.user error:error];
220+
completion:^(FIRAuthDataResult *authResult, NSError *error) {
221+
[self sendResult:result forAuthDataResult:authResult error:error];
220222
}];
221223
} else if ([@"unlinkFromProvider" isEqualToString:call.method]) {
222224
NSString *provider = call.arguments[@"provider"];
@@ -266,7 +268,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
266268
[[self getAuth:call.arguments]
267269
signInWithCustomToken:token
268270
completion:^(FIRAuthDataResult *authResult, NSError *error) {
269-
[self sendResult:result forUser:authResult.user error:error];
271+
[self sendResult:result forAuthDataResult:authResult error:error];
270272
}];
271273

272274
} else if ([@"startListeningAuthState" isEqualToString:call.method]) {
@@ -329,8 +331,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
329331
verificationCode:smsCode];
330332
[[self getAuth:call.arguments]
331333
signInAndRetrieveDataWithCredential:credential
332-
completion:^(FIRAuthDataResult *r, NSError *_Nullable error) {
333-
[self sendResult:result forUser:r.user error:error];
334+
completion:^(FIRAuthDataResult *authResult,
335+
NSError *_Nullable error) {
336+
[self sendResult:result
337+
forAuthDataResult:authResult
338+
error:error];
334339
}];
335340
} else if ([@"setLanguageCode" isEqualToString:call.method]) {
336341
NSString *language = call.arguments[@"language"];
@@ -353,14 +358,32 @@ - (NSMutableDictionary *)dictionaryFromUser:(FIRUser *)user {
353358

354359
NSMutableDictionary *userData = [toDictionary(user) mutableCopy];
355360
userData[@"creationTimestamp"] = [NSNumber numberWithLong:creationDate];
356-
userData[@"lastSignInTimestamp"] = [NSNumber numberWithInt:lastSignInDate];
361+
userData[@"lastSignInTimestamp"] = [NSNumber numberWithLong:lastSignInDate];
357362
userData[@"isAnonymous"] = [NSNumber numberWithBool:user.isAnonymous];
358363
userData[@"isEmailVerified"] = [NSNumber numberWithBool:user.isEmailVerified];
359364
userData[@"providerData"] = providerData;
360365
return userData;
361366
}
362367
#pragma clang diagnostic pop
363368

369+
- (void)sendResult:(FlutterResult)result
370+
forAuthDataResult:(FIRAuthDataResult *)authResult
371+
error:(NSError *)error {
372+
FIRUser *user = authResult.user;
373+
FIRAdditionalUserInfo *additionalUserInfo = authResult.additionalUserInfo;
374+
[self sendResult:result
375+
forObject:@{
376+
@"user" : (user != nil ? [self dictionaryFromUser:user] : nil),
377+
@"additionalUserInfo" : @{
378+
@"isNewUser" : [NSNumber numberWithBool:additionalUserInfo.isNewUser],
379+
@"username" : additionalUserInfo.username,
380+
@"providerId" : additionalUserInfo.providerID,
381+
@"profile" : additionalUserInfo.profile,
382+
}
383+
}
384+
error:error];
385+
}
386+
364387
- (void)sendResult:(FlutterResult)result forUser:(FIRUser *)user error:(NSError *)error {
365388
[self sendResult:result
366389
forObject:(user != nil ? [self dictionaryFromUser:user] : nil)

packages/firebase_auth/lib/firebase_auth.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ part 'src/auth_provider/github_auth_provider.dart';
1616
part 'src/auth_provider/google_auth_provider.dart';
1717
part 'src/auth_provider/phone_auth_provider.dart';
1818
part 'src/auth_provider/twitter_auth_provider.dart';
19+
part 'src/additional_user_info.dart';
1920
part 'src/auth_credential.dart';
2021
part 'src/auth_exception.dart';
22+
part 'src/auth_result.dart';
2123
part 'src/firebase_auth.dart';
2224
part 'src/firebase_user.dart';
2325
part 'src/user_info.dart';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2017 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
part of firebase_auth;
6+
7+
/// Interface representing a user's additional information
8+
class AdditionalUserInfo {
9+
AdditionalUserInfo._(this._data);
10+
11+
final Map<dynamic, dynamic> _data;
12+
13+
/// Returns whether the user is new or existing
14+
bool get isNewUser => _data['isNewUser'];
15+
16+
/// Returns the username if the provider is GitHub or Twitter
17+
String get username => _data['username'];
18+
19+
/// Returns the provider ID for specifying which provider the
20+
/// information in [profile] is for.
21+
String get providerId => _data['providerId'];
22+
23+
/// Returns a Map containing IDP-specific user data if the provider
24+
/// is one of Facebook, GitHub, Google, Twitter, Microsoft, or Yahoo.
25+
Map<String, dynamic> get profile => _data['profile']?.cast<String, dynamic>();
26+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2017 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
part of firebase_auth;
6+
7+
/// Result object obtained from operations that can affect the authentication
8+
/// state. Contains a method that returns the currently signed-in user after
9+
/// the operation has completed.
10+
class AuthResult {
11+
AuthResult._(this._data, FirebaseApp app)
12+
: user = FirebaseUser._(_data['user'].cast<String, dynamic>(), app);
13+
14+
final Map<String, dynamic> _data;
15+
16+
/// Returns the currently signed-in [FirebaseUser], or `null` if there isn't
17+
/// any (i.e. the user is signed out).
18+
final FirebaseUser user;
19+
20+
/// Returns IDP-specific information for the user if the provider is one of
21+
/// Facebook, Github, Google, or Twitter.
22+
AdditionalUserInfo get additionalUserInfo =>
23+
_data['additionalUserInfo'] == null
24+
? null
25+
: AdditionalUserInfo._(_data['additionalUserInfo']);
26+
27+
@override
28+
String toString() {
29+
return '$runtimeType($_data)';
30+
}
31+
}

0 commit comments

Comments
 (0)