Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
02b7468
Implement getIdTokenResult.
Jul 17, 2019
5de3c8f
Implement IdResultToken type.
Jul 17, 2019
b2c98d9
Fix typo.
Jul 17, 2019
af5302e
Fix claims type.
Jul 17, 2019
8e8a315
Fix claims type (2).
Jul 17, 2019
09f6efa
Fix claims type (3).
Jul 17, 2019
52620ba
Revert “Fix claims type (3)”.
Jul 17, 2019
d7812c0
Implement changes for renaming, add tests and changelog.
Jul 26, 2019
b33c424
Reformat.
Jul 26, 2019
a8ba0fb
Update CHANGELOG.md
collinjackson Jul 27, 2019
8928753
Update id_token_result.dart
collinjackson Jul 27, 2019
dd4fa48
Reformat
collinjackson Jul 27, 2019
423078e
Update *Date methods to Time instead
collinjackson Jul 27, 2019
5239ab2
Merge remote-tracking branch 'origin/master' into auth_idtokenresult
collinjackson Jul 27, 2019
883099e
Add integration testing
collinjackson Jul 27, 2019
beb1cb6
Update CHANGELOG.md
collinjackson Jul 27, 2019
6ddd601
Reformat
collinjackson Jul 27, 2019
f8f6352
Merge remote-tracking branch 'lukaspili/auth_idtokenresult' into auth…
collinjackson Jul 27, 2019
5c4cdc6
Fix integration test
collinjackson Jul 28, 2019
5df07ba
Merge remote-tracking branch 'origin/master' into auth_idtokenresult
collinjackson Jul 28, 2019
ea397c8
merge damage
collinjackson Jul 28, 2019
0b537cc
fix test failure
collinjackson Jul 28, 2019
3c4946a
Fix build
collinjackson Jul 28, 2019
5dcb187
Reformat
collinjackson Jul 28, 2019
b593de4
Merge remote-tracking branch 'origin/master' into auth_idtokenresult
collinjackson Jul 28, 2019
5386ee7
Remove unused import
collinjackson Jul 28, 2019
299f257
Update version to 0.13.0 to reflect breaking change
collinjackson Jul 28, 2019
a6de03f
Fix test
collinjackson Jul 28, 2019
bbc890d
revert project file
collinjackson Jul 28, 2019
e2400ed
Merge remote-tracking branch 'origin/master' into HEAD
collinjackson Jul 29, 2019
d5b84cc
Fix some merge damage
collinjackson Jul 29, 2019
233b378
Merge remote-tracking branch 'origin/master' into auth_idtokenresult
collinjackson Jul 29, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/firebase_auth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.14.0

* Added new `IdTokenResult` class.
* **Breaking Change**. `getIdToken()` method now returns `IdTokenResult` instead of a token `String`.
Use the `token` property of `IdTokenResult` to retrieve the token `String`.
* Added integration testing for `getIdToken()`.

## 0.13.1+1

* Update authentication example in README.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,16 +532,26 @@ private void handleGetToken(MethodCall call, final Result result, FirebaseAuth f
}

Map<String, Boolean> arguments = call.arguments();
boolean refresh = arguments.get("refresh");
final boolean refresh = arguments.get("refresh");

currentUser
.getIdToken(refresh)
.addOnCompleteListener(
new OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful() && task.getResult() != null) {
String idToken = task.getResult().getToken();
result.success(idToken);
final Map<String, Object> map = new HashMap<>();
map.put("token", task.getResult().getToken());
map.put("expirationTimestamp", task.getResult().getExpirationTimestamp());
map.put("authTimestamp", task.getResult().getAuthTimestamp());
map.put("issuedAtTimestamp", task.getResult().getIssuedAtTimestamp());
map.put("claims", task.getResult().getClaims());

if (task.getResult().getSignInProvider() != null) {
map.put("signInProvider", task.getResult().getSignInProvider());
}

result.success(Collections.unmodifiableMap(map));
} else {
reportException(result, task.getException());
}
Expand Down
14 changes: 14 additions & 0 deletions packages/firebase_auth/example/test/firebase_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ void main() {
expect(user.isAnonymous, isTrue);
expect(user.metadata.creationTime.isAfter(DateTime(2018, 1, 1)), isTrue);
expect(user.metadata.creationTime.isBefore(DateTime.now()), isTrue);
final IdTokenResult tokenResult = await user.getIdToken();
expect(tokenResult.token, isNotNull);
expect(tokenResult.expirationTime.isAfter(DateTime.now()), isTrue);
expect(tokenResult.authTime, isNotNull);
expect(tokenResult.issuedAtTime, isNotNull);
// TODO(jackson): Fix behavior to be consistent across platforms
// https://github.com/firebase/firebase-ios-sdk/issues/3445
expect(
tokenResult.signInProvider == null ||
tokenResult.signInProvider == 'anonymous',
isTrue);
expect(tokenResult.claims['provider_id'], 'anonymous');
expect(tokenResult.claims['firebase']['sign_in_provider'], 'anonymous');
expect(tokenResult.claims['user_id'], user.uid);
await auth.signOut();
final FirebaseUser user2 = (await auth.signInAnonymously()).user;
expect(user2.uid, isNot(equals(user.uid)));
Expand Down
31 changes: 27 additions & 4 deletions packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,33 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
NSDictionary *args = call.arguments;
BOOL refresh = [args objectForKey:@"refresh"];
[[self getAuth:call.arguments].currentUser
getIDTokenForcingRefresh:refresh
completion:^(NSString *_Nullable token, NSError *_Nullable error) {
[self sendResult:result forObject:token error:error];
}];
getIDTokenResultForcingRefresh:refresh
completion:^(FIRAuthTokenResult *_Nullable tokenResult,
NSError *_Nullable error) {
NSMutableDictionary *tokenData = nil;
if (tokenResult != nil) {
long expirationTimestamp =
[tokenResult.expirationDate timeIntervalSince1970];
long authTimestamp = [tokenResult.authDate timeIntervalSince1970];
long issuedAtTimestamp =
[tokenResult.issuedAtDate timeIntervalSince1970];

tokenData = [[NSMutableDictionary alloc] initWithDictionary:@{
@"token" : tokenResult.token,
@"expirationTimestamp" :
[NSNumber numberWithInt:expirationTimestamp],
@"authTimestamp" : [NSNumber numberWithInt:authTimestamp],
@"issuedAtTimestamp" : [NSNumber numberWithInt:issuedAtTimestamp],
@"claims" : tokenResult.claims,
}];

if (tokenResult.signInProvider != nil) {
tokenData[@"signInProvider"] = tokenResult.signInProvider;
}
}

[self sendResult:result forObject:tokenData error:error];
}];
} else if ([@"reauthenticateWithCredential" isEqualToString:call.method]) {
[[self getAuth:call.arguments].currentUser
reauthenticateAndRetrieveDataWithCredential:[self getCredential:call.arguments]
Expand Down
1 change: 1 addition & 0 deletions packages/firebase_auth/lib/firebase_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ part 'src/auth_exception.dart';
part 'src/auth_result.dart';
part 'src/firebase_auth.dart';
part 'src/firebase_user.dart';
part 'src/id_token_result.dart';
part 'src/user_info.dart';
part 'src/user_metadata.dart';
part 'src/user_update_info.dart';
10 changes: 6 additions & 4 deletions packages/firebase_auth/lib/src/firebase_user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,21 @@ class FirebaseUser extends UserInfo {
/// Returns true if the user's email is verified.
bool get isEmailVerified => _data['isEmailVerified'];

/// Obtains the id token for the current user, forcing a [refresh] if desired.
/// Obtains the id token result for the current user, forcing a [refresh] if desired.
///
/// Useful when authenticating against your own backend. Use our server
/// SDKs or follow the official documentation to securely verify the
/// integrity and validity of this token.
///
/// Completes with an error if the user is signed out.
Future<String> getIdToken({bool refresh = false}) async {
return await FirebaseAuth.channel
.invokeMethod<String>('getIdToken', <String, dynamic>{
Future<IdTokenResult> getIdToken({bool refresh = false}) async {
final Map<String, dynamic> data = await FirebaseAuth.channel
.invokeMapMethod<String, dynamic>('getIdToken', <String, dynamic>{
'refresh': refresh,
'app': _app.name,
});

return IdTokenResult(data, _app);
}

/// Associates a user account from a third-party identity provider with this
Expand Down
51 changes: 51 additions & 0 deletions packages/firebase_auth/lib/src/id_token_result.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

part of firebase_auth;

/// Represents ID token result obtained from [FirebaseUser], containing the
/// ID token JWT string and other helper properties for getting different
/// data associated with the token as well as all the decoded payload claims.
///
/// Note that these claims are not to be trusted as they are parsed client side.
/// Only server side verification can guarantee the integrity of the token
/// claims.
class IdTokenResult {
@visibleForTesting
IdTokenResult(this._data, this._app);

final FirebaseApp _app;

final Map<dynamic, dynamic> _data;

/// The Firebase Auth ID token JWT string.
String get token => _data['token'];

/// The time when the ID token expires.
DateTime get expirationTime =>
DateTime.fromMillisecondsSinceEpoch(_data['expirationTimestamp'] * 1000);

/// The time the user authenticated (signed in).
///
/// Note that this is not the time the token was refreshed.
DateTime get authTime =>
DateTime.fromMillisecondsSinceEpoch(_data['authTimestamp'] * 1000);

/// The time when ID token was issued.
DateTime get issuedAtTime =>
DateTime.fromMillisecondsSinceEpoch(_data['issuedAtTimestamp'] * 1000);

/// The sign-in provider through which the ID token was obtained (anonymous,
/// custom, phone, password, etc). Note, this does not map to provider IDs.
String get signInProvider => _data['signInProvider'];

/// The entire payload claims of the ID token including the standard reserved
/// claims as well as the custom claims.
Map<dynamic, dynamic> get claims => _data['claims'];

@override
String toString() {
return '$runtimeType($_data)';
}
}
2 changes: 1 addition & 1 deletion packages/firebase_auth/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling Android and iOS
like Google, Facebook and Twitter.
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_auth
version: 0.13.1+1
version: 0.14.0

flutter:
plugin:
Expand Down
41 changes: 38 additions & 3 deletions packages/firebase_auth/test/firebase_auth_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ const String kMockPhoneNumber = '5555555555';
const String kMockVerificationId = '12345';
const String kMockSmsCode = '123456';
const String kMockLanguage = 'en';
const String kMockIdTokenResultSignInProvider = 'password';
const Map<dynamic, dynamic> kMockIdTokenResultClaims = <dynamic, dynamic>{
'claim1': 'value1',
};
const int kMockIdTokenResultExpirationTimestamp = 123456;
const int kMockIdTokenResultAuthTimestamp = 1234567;
const int kMockIdTokenResultIssuedAtTimestamp = 12345678;
const Map<String, dynamic> kMockIdTokenResult = <String, dynamic>{
'token': kMockIdToken,
'expirationTimestamp': kMockIdTokenResultExpirationTimestamp,
'authTimestamp': kMockIdTokenResultAuthTimestamp,
'issuedAtTimestamp': kMockIdTokenResultIssuedAtTimestamp,
'signInProvider': kMockIdTokenResultSignInProvider,
'claims': kMockIdTokenResultClaims,
};

final int kMockCreationTimestamp = DateTime(2019, 1, 1).millisecondsSinceEpoch;
final int kMockLastSignInTimestamp =
DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch;
Expand Down Expand Up @@ -65,7 +81,7 @@ void main() {
log.add(call);
switch (call.method) {
case "getIdToken":
return kMockIdToken;
return kMockIdTokenResult;
break;
case "isSignInWithEmailLink":
return true;
Expand Down Expand Up @@ -126,9 +142,28 @@ void main() {
}

test('getIdToken', () async {
void verifyIdTokenResult(IdTokenResult idTokenResult) {
expect(idTokenResult.token, equals(kMockIdToken));
expect(
idTokenResult.expirationTime,
equals(DateTime.fromMillisecondsSinceEpoch(
kMockIdTokenResultExpirationTimestamp * 1000)));
expect(
idTokenResult.authTime,
equals(DateTime.fromMillisecondsSinceEpoch(
kMockIdTokenResultAuthTimestamp * 1000)));
expect(
idTokenResult.issuedAtTime,
equals(DateTime.fromMillisecondsSinceEpoch(
kMockIdTokenResultIssuedAtTimestamp * 1000)));
expect(idTokenResult.signInProvider,
equals(kMockIdTokenResultSignInProvider));
expect(idTokenResult.claims, equals(kMockIdTokenResultClaims));
}

final FirebaseUser user = await auth.currentUser();
expect(await user.getIdToken(), equals(kMockIdToken));
expect(await user.getIdToken(refresh: true), equals(kMockIdToken));
verifyIdTokenResult(await user.getIdToken());
verifyIdTokenResult(await user.getIdToken(refresh: true));
expect(
log,
<Matcher>[
Expand Down