diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 6e66145a..e5f51521 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -39,7 +39,7 @@ @implementation GIDGoogleUser - (instancetype)initWithAuthState:(OIDAuthState *)authState - profileData:(GIDProfileData *)profileData { + profileData:(nullable GIDProfileData *)profileData { self = [super init]; if (self) { _authentication = [[GIDAuthentication alloc] initWithAuthState:authState]; diff --git a/GoogleSignIn/Sources/GIDGoogleUser_Private.h b/GoogleSignIn/Sources/GIDGoogleUser_Private.h index 34d04cf5..7136bdab 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser_Private.h +++ b/GoogleSignIn/Sources/GIDGoogleUser_Private.h @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN // Create a object with an auth state, scopes, and profile data. - (instancetype)initWithAuthState:(OIDAuthState *)authState - profileData:(GIDProfileData *)profileData; + profileData:(nullable GIDProfileData *)profileData; @end diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 5ca3f3b6..d2af2e3a 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -186,6 +186,17 @@ - (BOOL)hasPreviousSignIn { return [authState isAuthorized]; } +- (nullable GIDGoogleUser *)restoredGoogleUserFromPreviousSignIn { + OIDAuthState *authState = [self loadAuthState]; + + if (!authState) { + return nil; + } + + return [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; +} + - (void)restorePreviousSignIn { [self signInWithOptions:[GIDSignInInternalOptions silentOptions]]; } diff --git a/GoogleSignIn/Sources/GIDSignIn_Private.h b/GoogleSignIn/Sources/GIDSignIn_Private.h index b06a034d..79f0748f 100644 --- a/GoogleSignIn/Sources/GIDSignIn_Private.h +++ b/GoogleSignIn/Sources/GIDSignIn_Private.h @@ -18,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN +@class GIDGoogleUser; @class GIDSignInInternalOptions; // Private |GIDSignIn| methods that are used internally in this SDK and other Google SDKs. @@ -29,6 +30,9 @@ NS_ASSUME_NONNULL_BEGIN // Authenticates with extra options. - (void)signInWithOptions:(GIDSignInInternalOptions *)options; +// Returns the previous sign-in user in the keychain without refreshing the access token. +- (nullable GIDGoogleUser *)restoredGoogleUserFromPreviousSignIn; + @end NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 8be2cc8d..239d608e 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -66,6 +66,8 @@ return YES;\ }] +static NSString * const kFakeGaiaID = @"123456789"; +static NSString * const kFakeIDToken = @"FakeIDToken"; static NSString * const kClientId = @"FakeClientID"; static NSString * const kDotReversedClientId = @"FakeClientID"; static NSString * const kClientId2 = @"FakeClientID2"; @@ -347,6 +349,35 @@ - (void)testDefaultScope { [_signIn startMocking]; } +- (void)testRestoredGoogleUserFromPreviousSignIn_hasPreviousUser { + [[[_authorization expect] andReturn:_authState] authState]; + OCMStub([_authState lastTokenResponse]).andReturn(_tokenResponse); + OCMStub([_tokenResponse scope]).andReturn(nil); + OCMStub([_tokenResponse additionalParameters]).andReturn(nil); + OCMStub([_tokenResponse idToken]).andReturn(kFakeIDToken); + + id idTokenDecoded = OCMClassMock([OIDIDToken class]); + OCMStub([idTokenDecoded alloc]).andReturn(idTokenDecoded); + OCMStub([idTokenDecoded initWithIDTokenString:OCMOCK_ANY]).andReturn(idTokenDecoded); + OCMStub([idTokenDecoded subject]).andReturn(kFakeGaiaID); + + GIDGoogleUser *previousUser = [_signIn restoredGoogleUserFromPreviousSignIn]; + + [_authorization verify]; + [_authState verify]; + [_tokenResponse verify]; + XCTAssertEqual(previousUser.userID, kFakeGaiaID); +} + +- (void)testRestoredGoogleUserFromPreviousSignIn_hasNoPreviousUser { + [[[_authorization expect] andReturn:nil] authState]; + + GIDGoogleUser *previousUser = [_signIn restoredGoogleUserFromPreviousSignIn]; + + [_authorization verify]; + XCTAssertNil(previousUser); +} + - (void)testHasPreviousSignIn_HasBeenAuthenticated { [[[_authorization expect] andReturn:_authState] authState]; [[[_authState expect] andReturnValue:[NSNumber numberWithBool:YES]] isAuthorized];