From 528e534dc77b914deb8f3de0b38afb550e54bdbc Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Tue, 28 Feb 2023 19:33:07 -0800 Subject: [PATCH 01/38] Initial setup for GTMAA error handling --- ...ppAuthFetcherAuthorizationWithEMMSupport.h | 2 +- ...ppAuthFetcherAuthorizationWithEMMSupport.m | 37 +++----------- GoogleSignIn/Sources/GIDAuthStateMigration.m | 29 ++++++----- GoogleSignIn/Sources/GIDEMMSupport.h | 2 + GoogleSignIn/Sources/GIDEMMSupport.m | 6 +++ GoogleSignIn/Sources/GIDGoogleUser.m | 44 +++++++++++----- GoogleSignIn/Sources/GIDGoogleUser_Private.h | 5 +- GoogleSignIn/Sources/GIDSignIn.m | 21 ++++---- .../Public/GoogleSignIn/GIDGoogleUser.h | 7 ++- .../Tests/Unit/GIDAuthStateMigrationTest.m | 36 ++++++------- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 2 +- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 50 +++++++++---------- Package.swift | 2 +- 13 files changed, 125 insertions(+), 118 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h b/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h index baffe3c1..b0f04816 100644 --- a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h +++ b/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN // A specialized GTMAppAuthFetcherAuthorization subclass with EMM support. -@interface GIDAppAuthFetcherAuthorizationWithEMMSupport : GTMAppAuthFetcherAuthorization +@interface GIDAppAuthFetcherAuthorizationWithEMMSupport : NSObject @end diff --git a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m b/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m index 814a73fc..4fb2133e 100644 --- a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m +++ b/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m @@ -39,8 +39,8 @@ @interface GIDAppAuthFetcherAuthorizationEMMChainedDelegate : NSObject // Initializes with chained delegate and selector. - (instancetype)initWithDelegate:(id)delegate selector:(SEL)selector; -// The callback method for GTMAppAuthFetcherAuthorization to invoke. -- (void)authentication:(GTMAppAuthFetcherAuthorization *)auth +// The callback method for GTMAuthSession to invoke. +- (void)authentication:(GTMAuthSession *)auth request:(NSMutableURLRequest *)request finishedWithError:(nullable NSError *)error; @@ -50,8 +50,8 @@ @implementation GIDAppAuthFetcherAuthorizationEMMChainedDelegate { // We use a weak reference here to match GTMAppAuthFetcherAuthorization. __weak id _delegate; SEL _selector; - // We need to maintain a reference to the chained delegate because GTMAppAuthFetcherAuthorization - // only keeps a weak reference. + // We need to maintain a reference to the chained delegate because GTMAuthSession only keeps a + // weak reference. GIDAppAuthFetcherAuthorizationEMMChainedDelegate *_retained_self; } @@ -65,7 +65,7 @@ - (instancetype)initWithDelegate:(id)delegate selector:(SEL)selector { return self; } -- (void)authentication:(GTMAppAuthFetcherAuthorization *)auth +- (void)authentication:(GTMAuthSession *)auth request:(NSMutableURLRequest *)request finishedWithError:(nullable NSError *)error { [GIDEMMSupport handleTokenFetchEMMError:error completion:^(NSError *_Nullable error) { @@ -96,30 +96,9 @@ - (void)authentication:(GTMAppAuthFetcherAuthorization *)auth @implementation GIDAppAuthFetcherAuthorizationWithEMMSupport -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" -- (void)authorizeRequest:(nullable NSMutableURLRequest *)request - delegate:(id)delegate - didFinishSelector:(SEL)sel { -#pragma clang diagnostic pop - GIDAppAuthFetcherAuthorizationEMMChainedDelegate *chainedDelegate = - [[GIDAppAuthFetcherAuthorizationEMMChainedDelegate alloc] initWithDelegate:delegate - selector:sel]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [super authorizeRequest:request - delegate:chainedDelegate - didFinishSelector:@selector(authentication:request:finishedWithError:)]; -#pragma clang diagnostic pop -} - -- (void)authorizeRequest:(nullable NSMutableURLRequest *)request - completionHandler:(GTMAppAuthFetcherAuthorizationCompletion)handler { - [super authorizeRequest:request completionHandler:^(NSError *_Nullable error) { - [GIDEMMSupport handleTokenFetchEMMError:error completion:^(NSError *_Nullable error) { - handler(error); - }]; - }]; +- (nullable NSError *)updatedErrorForAuthSession:(GTMAuthSession *)authSession + originalError:(NSError *)originalError { + return [GIDEMMSupport handleTokenFetchEMMError:originalError]; } @end diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index f6ae73e4..27681bcc 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -55,14 +55,16 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL // action and go on to mark the migration check as having been performed. if (!isFreshInstall) { // Attempt migration - GTMAppAuthFetcherAuthorization *authorization = + GTMAuthSession *authorization = [self extractAuthorizationWithTokenURL:tokenURL callbackPath:callbackPath]; // If migration was successful, save our migrated state to the keychain. if (authorization) { // If we're unable to save to the keychain, return without marking migration performed. - if (![GTMAppAuthFetcherAuthorization saveAuthorization:authorization - toKeychainForName:keychainName]) { + NSError *err; + GTMKeychainStore *keychainStore = [[GTMKeychainStore alloc] initWithItemName:@"auth"]; + [keychainStore saveAuthSession:authorization error:&err]; + if (!err) { return; }; } @@ -72,9 +74,9 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL [defaults setBool:YES forKey:kMigrationCheckPerformedKey]; } -// Returns a |GTMAppAuthFetcherAuthorization| object containing any old auth state or |nil| if none +// Returns a |GTMAuthSession| object containing any old auth state or |nil| if none // was found or the migration failed. -+ (nullable GTMAppAuthFetcherAuthorization *) ++ (nullable GTMAuthSession *) extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath { // Retrieve the last used fingerprint. NSString *fingerprint = [GIDAuthStateMigration passwordForService:kFingerprintService]; @@ -83,7 +85,8 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL } // Retrieve the GTMOAuth2 persistence string. - NSString *GTMOAuth2PersistenceString = [GTMKeychain passwordFromKeychainForName:fingerprint]; + GTMKeychainStore *ks = [[GTMKeychainStore alloc] initWithItemName:@"auth"]; + NSString *GTMOAuth2PersistenceString = nil; // [GTMKeychain passwordFromKeychainForName:fingerprint]; if (!GTMOAuth2PersistenceString) { return nil; } @@ -126,14 +129,14 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL additionalTokenRequestParameters]; } - // Use |GTMOAuth2KeychainCompatibility| to generate a |GTMAppAuthFetcherAuthorization| from the + // Use |GTMOAuth2KeychainCompatibility| to generate a |GTMAuthSession| from the // persistence string, redirect URI, client ID, and token endpoint URL. - GTMAppAuthFetcherAuthorization *authorization = [GTMOAuth2KeychainCompatibility - authorizeFromPersistenceString:persistenceString - tokenURL:tokenURL - redirectURI:redirectURI - clientID:clientID - clientSecret:nil]; + GTMAuthSession *authorization = [GTMOAuth2Compatibility authSessionForPersistenceString:persistenceString + tokenURL:tokenURL + redirectURI:redirectURI + clientID:clientID + clientSecret:nil + error:nil]; return authorization; } diff --git a/GoogleSignIn/Sources/GIDEMMSupport.h b/GoogleSignIn/Sources/GIDEMMSupport.h index d6f4e92e..45cf0577 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.h +++ b/GoogleSignIn/Sources/GIDEMMSupport.h @@ -25,6 +25,8 @@ NS_ASSUME_NONNULL_BEGIN // A class to support EMM (Enterprise Mobility Management). @interface GIDEMMSupport : NSObject ++ (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error; + // Handles potential EMM error from token fetch response. + (void)handleTokenFetchEMMError:(nullable NSError *)error completion:(void (^)(NSError *_Nullable))completion; diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index a796f5fb..254db4d2 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -46,6 +46,12 @@ @implementation GIDEMMSupport ++ (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error { + return [NSError errorWithDomain:kGIDSignInErrorDomain + code:kGIDSignInErrorCodeEMM + userInfo:error.userInfo]; +} + + (void)handleTokenFetchEMMError:(nullable NSError *)error completion:(void (^)(NSError *_Nullable))completion { NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey]; diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 828ac5b6..58636e8b 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -52,6 +52,10 @@ // Minimal time interval before expiration for the access token or it needs to be refreshed. static NSTimeInterval const kMinimalTimeToExpire = 60.0; +@interface GIDGoogleUser () + +@end + @implementation GIDGoogleUser { GIDConfiguration *_cachedConfiguration; @@ -179,8 +183,8 @@ - (void)refreshTokensIfNeededWithCompletion:(GIDGoogleUserCompletion)completion }]; } -- (OIDAuthState *) authState{ - return ((GTMAppAuthFetcherAuthorization *)self.fetcherAuthorizer).authState; +- (OIDAuthState *) authState { + return ((GTMAuthSession *)self.fetcherAuthorizer).authState; } - (void)addScopes:(NSArray *)scopes @@ -228,15 +232,15 @@ - (instancetype)initWithAuthState:(OIDAuthState *)authState _tokenRefreshHandlerQueue = [[NSMutableArray alloc] init]; _profile = profileData; -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - GTMAppAuthFetcherAuthorization *authorization = self.emmSupport ? - [[GIDAppAuthFetcherAuthorizationWithEMMSupport alloc] initWithAuthState:authState] : - [[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState]; -#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST - GTMAppAuthFetcherAuthorization *authorization = - [[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState]; -#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST - authorization.tokenRefreshDelegate = self; +//#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST +// GTMAppAuthFetcherAuthorization *authorization = self.emmSupport ? +// [[GIDAppAuthFetcherAuthorizationWithEMMSupport alloc] initWithAuthState:authState] : +// [[GTMAuthSession alloc] initWithAuthState:authState]; +//#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST + GTMAuthSession *authorization = + [[GTMAuthSession alloc] initWithAuthState:authState]; +//#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST + authorization.delegate = self; authorization.authState.stateChangeDelegate = self; self.fetcherAuthorizer = authorization; @@ -304,10 +308,10 @@ - (nullable NSString *)hostedDomain { return nil; } -#pragma mark - GTMAppAuthFetcherAuthorizationTokenRefreshDelegate +#pragma mark - GTMAuthSessionDelegate - (nullable NSDictionary *)additionalRefreshParameters: - (GTMAppAuthFetcherAuthorization *)authorization { + (GTMAuthSession *)authorization { #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST return [GIDEMMSupport updatedEMMParametersWithParameters: authorization.authState.lastTokenResponse.request.additionalParameters]; @@ -316,6 +320,20 @@ - (nullable NSDictionary *)additionalRefreshParameters: #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST } +- (nullable NSDictionary *)additionalTokenRefreshParametersForAuthSession:(GTMAuthSession *)authSession { +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST + return [GIDEMMSupport updatedEMMParametersWithParameters: + authSession.authState.lastTokenResponse.request.additionalParameters]; +#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST + return authorization.authState.lastTokenResponse.request.additionalParameters; +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST +} + +- (nullable NSError *)updatedErrorForAuthSession:(GTMAuthSession *)authSession + originalError:(NSError *)originalError { + return [GIDEMMSupport handleTokenFetchEMMError:originalError]; +} + #pragma mark - OIDAuthStateChangeDelegate - (void)didChangeState:(OIDAuthState *)state { diff --git a/GoogleSignIn/Sources/GIDGoogleUser_Private.h b/GoogleSignIn/Sources/GIDGoogleUser_Private.h index 94a019ae..c3b8d8dd 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser_Private.h +++ b/GoogleSignIn/Sources/GIDGoogleUser_Private.h @@ -20,7 +20,7 @@ @import AppAuth; @import GTMAppAuth; #else -#import +//#import #import #endif @@ -32,8 +32,7 @@ NS_ASSUME_NONNULL_BEGIN typedef void (^GIDGoogleUserCompletion)(GIDGoogleUser *_Nullable user, NSError *_Nullable error); // Internal methods for the class that are not part of the public API. -@interface GIDGoogleUser () +@interface GIDGoogleUser () @property(nonatomic, readwrite) GIDToken *accessToken; diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index f4cdf1af..8b90953f 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -166,6 +166,8 @@ @implementation GIDSignIn { id _currentAuthorizationFlow; // Flag to indicate that the auth flow is restarting. BOOL _restarting; + // Keychain manager for GTMAppAuth + GTMKeychainStore *_keychainStore; } #pragma mark - Public methods @@ -475,6 +477,7 @@ - (id)initPrivate { _appAuthConfiguration = [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:[NSURL URLWithString:authorizationEnpointURL] tokenEndpoint:[NSURL URLWithString:tokenEndpointURL]]; + _keychainStore = [[GTMKeychainStore alloc] initWithItemName:kGTMAppAuthKeychainName]; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST // Perform migration of auth state from old (before 5.0) versions of the SDK if needed. @@ -872,8 +875,7 @@ - (void)startFetchURL:(NSURL *)URL withCompletionHandler:(void (^)(NSData *, NSError *))handler { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; GTMSessionFetcher *fetcher; - GTMAppAuthFetcherAuthorization *authorization = - [[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState]; + GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; id fetcherService = authorization.fetcherService; if (fetcherService) { fetcher = [fetcherService fetcherWithRequest:request]; @@ -977,22 +979,17 @@ - (BOOL)isFreshInstall { } - (void)removeAllKeychainEntries { - [GTMAppAuthFetcherAuthorization removeAuthorizationFromKeychainForName:kGTMAppAuthKeychainName - useDataProtectionKeychain:YES]; + [_keychainStore removeAuthSessionWithError:nil]; } - (BOOL)saveAuthState:(OIDAuthState *)authState { - GTMAppAuthFetcherAuthorization *authorization = - [[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState]; - return [GTMAppAuthFetcherAuthorization saveAuthorization:authorization - toKeychainForName:kGTMAppAuthKeychainName - useDataProtectionKeychain:YES]; + GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; + [_keychainStore saveAuthSession:authorization error:nil]; + return YES; } - (OIDAuthState *)loadAuthState { - GTMAppAuthFetcherAuthorization *authorization = - [GTMAppAuthFetcherAuthorization authorizationFromKeychainForName:kGTMAppAuthKeychainName - useDataProtectionKeychain:YES]; + GTMAuthSession *authorization = [_keychainStore retrieveAuthSessionWithError:nil]; return authorization.authState; } diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h index 434f0e56..26c78a95 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h @@ -26,9 +26,12 @@ // We have to import GTMAppAuth because forward declaring the protocol does // not generate the `fetcherAuthorizer` property below for Swift. #ifdef SWIFT_PACKAGE -@import GTMAppAuth; +//@import GTMAppAuth; +//@import AppAuthCore; +@import GTMSessionFetcherCore; #else -#import +#import +//#import #endif @class GIDConfiguration; diff --git a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m index 0ec70759..dac44c1f 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m @@ -58,7 +58,7 @@ @interface GIDAuthStateMigration () -+ (nullable GTMAppAuthFetcherAuthorization *) ++ (nullable GTMAuthSession *) extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath; + (nullable NSString *)passwordForService:(NSString *)service; @@ -82,12 +82,12 @@ - (void)setUp { [super setUp]; _mockUserDefaults = OCMStrictClassMock([NSUserDefaults class]); - _mockGTMAppAuthFetcherAuthorization = OCMStrictClassMock([GTMAppAuthFetcherAuthorization class]); + _mockGTMAppAuthFetcherAuthorization = OCMStrictClassMock([GTMAuthSession class]); _mockGIDAuthStateMigration = OCMStrictClassMock([GIDAuthStateMigration class]); - _mockGTMKeychain = OCMStrictClassMock([GTMKeychain class]); + _mockGTMKeychain = OCMStrictClassMock([GTMKeychainStore class]); _mockNSBundle = OCMStrictClassMock([NSBundle class]); _mockGIDSignInCallbackSchemes = OCMStrictClassMock([GIDSignInCallbackSchemes class]); - _mockGTMOAuth2KeychainCompatibility = OCMStrictClassMock([GTMOAuth2KeychainCompatibility class]); + _mockGTMOAuth2KeychainCompatibility = OCMStrictClassMock([GTMOAuth2Compatibility class]); } - (void)tearDown { @@ -117,8 +117,8 @@ - (void)testMigrateIfNeeded_NoPreviousMigration { boolForKey:kMigrationCheckPerformedKey]; [[[_mockGIDAuthStateMigration expect] andReturn:_mockGTMAppAuthFetcherAuthorization] extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath]; - [[[_mockGTMAppAuthFetcherAuthorization expect] andReturnValue:@YES] - saveAuthorization:_mockGTMAppAuthFetcherAuthorization toKeychainForName:kKeychainName]; + [[[_mockGTMKeychain expect] andReturnValue:@YES] + saveAuthSession:_mockGTMAppAuthFetcherAuthorization error:nil]; [[_mockUserDefaults expect] setBool:YES forKey:kMigrationCheckPerformedKey]; [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] @@ -144,8 +144,8 @@ - (void)testMigrateIfNeeded_KeychainFailure { boolForKey:kMigrationCheckPerformedKey]; [[[_mockGIDAuthStateMigration expect] andReturn:_mockGTMAppAuthFetcherAuthorization] extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath]; - [[[_mockGTMAppAuthFetcherAuthorization expect] andReturnValue:[NSNumber numberWithBool:NO]] - saveAuthorization:_mockGTMAppAuthFetcherAuthorization toKeychainForName:kKeychainName]; + [[[_mockGTMKeychain expect] andReturnValue:[NSNumber numberWithBool:NO]] + saveAuthSession:_mockGTMAppAuthFetcherAuthorization error:nil]; [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath @@ -184,8 +184,8 @@ - (NSString *)additionalTokenRequestParametersKeyFromFingerprint:(NSString *)fin - (void)extractAuthorizationWithFingerprint:(NSString *)fingerprint { [[[_mockGIDAuthStateMigration expect] andReturn:fingerprint] passwordForService:kFingerprintService]; - [[[_mockGTMKeychain expect] andReturn:kGTMOAuth2PersistenceString] - passwordFromKeychainForName:fingerprint]; +// [[[_mockGTMKeychain expect] andReturn:kGTMOAuth2PersistenceString] +// passwordFromKeychainForName:fingerprint];j [[[_mockNSBundle expect] andReturn:_mockNSBundle] mainBundle]; [[[_mockNSBundle expect] andReturn:kBundleID] bundleIdentifier]; [[[_mockGIDSignInCallbackSchemes expect] andReturn:_mockGIDSignInCallbackSchemes] alloc]; @@ -194,14 +194,14 @@ - (void)extractAuthorizationWithFingerprint:(NSString *)fingerprint { [[[_mockGIDSignInCallbackSchemes expect] andReturn:kDotReversedClientID] clientIdentifierScheme]; [[[_mockGIDAuthStateMigration expect] andReturn:kAdditionalTokenRequestParameters] passwordForService:[self additionalTokenRequestParametersKeyFromFingerprint:fingerprint]]; - [[[_mockGTMOAuth2KeychainCompatibility expect] andReturn:_mockGTMAppAuthFetcherAuthorization] - authorizeFromPersistenceString:kFinalPersistenceString - tokenURL:[NSURL URLWithString:kTokenURL] - redirectURI:kRedirectURI - clientID:kClientID - clientSecret:nil]; - - GTMAppAuthFetcherAuthorization *authorization = + // [[[_mockGTMOAuth2KeychainCompatibility expect] andReturn:_mockGTMAppAuthFetcherAuthorization] +// authorizeFromPersistenceString:kFinalPersistenceString +// tokenURL:[NSURL URLWithString:kTokenURL] +// redirectURI:kRedirectURI +// clientID:kClientID +// clientSecret:nil]; + + GTMAuthSession *authorization = [GIDAuthStateMigration extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath]; diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 3f42afd6..0c316735 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -216,7 +216,7 @@ - (void)testFetcherAuthorizer { #pragma clang diagnostic ignored "-Wdeprecated-declarations" id fetcherAuthorizer = user.fetcherAuthorizer; #pragma clang diagnostic pop - XCTAssertTrue([fetcherAuthorizer isKindOfClass:[GTMAppAuthFetcherAuthorization class]]); + XCTAssertTrue([fetcherAuthorizer isKindOfClass:[GTMAuthSession class]]); XCTAssertTrue([fetcherAuthorizer canAuthorize]); } diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index b778501c..8e1f1730 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -289,23 +289,23 @@ - (void)setUp { OCMStub([_authState initWithAuthorizationResponse:OCMOCK_ANY]).andReturn(_authState); _tokenResponse = OCMStrictClassMock([OIDTokenResponse class]); _tokenRequest = OCMStrictClassMock([OIDTokenRequest class]); - _authorization = OCMStrictClassMock([GTMAppAuthFetcherAuthorization class]); - OCMStub([_authorization authorizationFromKeychainForName:OCMOCK_ANY - useDataProtectionKeychain:YES]).andReturn(_authorization); + _authorization = OCMStrictClassMock([GTMAuthSession class]); +// OCMStub([_authorization authorizationFromKeychainForName:OCMOCK_ANY +// useDataProtectionKeychain:YES]).andReturn(_authorization); OCMStub([_authorization alloc]).andReturn(_authorization); OCMStub([_authorization initWithAuthState:OCMOCK_ANY]).andReturn(_authorization); - OCMStub([_authorization saveAuthorization:OCMOCK_ANY - toKeychainForName:OCMOCK_ANY - useDataProtectionKeychain:YES]) - .andDo(^(NSInvocation *invocation) { - self->_keychainSaved = self->_saveAuthorizationReturnValue; - [invocation setReturnValue:&self->_saveAuthorizationReturnValue]; - }); - OCMStub([_authorization removeAuthorizationFromKeychainForName:OCMOCK_ANY - useDataProtectionKeychain:YES]) - .andDo(^(NSInvocation *invocation) { - self->_keychainRemoved = YES; - }); +// OCMStub([_authorization saveAuthorization:OCMOCK_ANY +// toKeychainForName:OCMOCK_ANY +// useDataProtectionKeychain:YES]) +// .andDo(^(NSInvocation *invocation) { +// self->_keychainSaved = self->_saveAuthorizationReturnValue; +// [invocation setReturnValue:&self->_saveAuthorizationReturnValue]; +// }); +// OCMStub([_authorization removeAuthorizationFromKeychainForName:OCMOCK_ANY +// useDataProtectionKeychain:YES]) +// .andDo(^(NSInvocation *invocation) { +// self->_keychainRemoved = YES; +// }); _user = OCMStrictClassMock([GIDGoogleUser class]); _oidAuthorizationService = OCMStrictClassMock([OIDAuthorizationService class]); OCMStub([_oidAuthorizationService @@ -414,7 +414,7 @@ - (void)testInitPrivate_invalidConfig { - (void)testRestorePreviousSignInNoRefresh_hasPreviousUser { [[[_authorization stub] andReturn:_authState] authState]; - [[_authorization expect] setTokenRefreshDelegate:OCMOCK_ANY]; +// [[_authorization expect] setTokenRefreshDelegate:OCMOCK_ANY]; OCMStub([_authState lastTokenResponse]).andReturn(_tokenResponse); OCMStub([_authState refreshToken]).andReturn(kRefreshToken); [[_authState expect] setStateChangeDelegate:OCMOCK_ANY]; @@ -786,8 +786,8 @@ - (void)testSignOut { XCTAssertNil(_signIn.currentUser, @"should not have a current user"); XCTAssertTrue(_keychainRemoved, @"should remove keychain"); - OCMVerify([_authorization removeAuthorizationFromKeychainForName:kKeychainName - useDataProtectionKeychain:YES]); +// OCMVerify([_authorization removeAuthorizationFromKeychainForName:kKeychainName +// useDataProtectionKeychain:YES]); } - (void)testNotHandleWrongScheme { @@ -1477,13 +1477,13 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow XCTAssertFalse(_keychainRemoved, @"should not remove keychain"); XCTAssertFalse(_keychainSaved, @"should not save to keychain again"); - if (restoredSignIn) { - OCMVerify([_authorization authorizationFromKeychainForName:kKeychainName - useDataProtectionKeychain:YES]); - OCMVerify([_authorization saveAuthorization:OCMOCK_ANY - toKeychainForName:kKeychainName - useDataProtectionKeychain:YES]); - } +// if (restoredSignIn) { +// OCMVerify([_authorization authorizationFromKeychainForName:kKeychainName +// useDataProtectionKeychain:YES]); +// OCMVerify([_authorization saveAuthorization:OCMOCK_ANY +// toKeychainForName:kKeychainName +// useDataProtectionKeychain:YES]); +// } } @end diff --git a/Package.swift b/Package.swift index a8b794f9..047336bf 100644 --- a/Package.swift +++ b/Package.swift @@ -48,7 +48,7 @@ let package = Package( .package( name: "GTMAppAuth", url: "https://github.com/google/GTMAppAuth.git", - "1.3.0" ..< "3.0.0"), + .branch("mdmathias/no-longer-open")), .package( name: "GTMSessionFetcher", url: "https://github.com/google/gtm-session-fetcher.git", From 0600090e719a884471351607970d5581653e2bba Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Tue, 28 Feb 2023 20:00:29 -0800 Subject: [PATCH 02/38] Set the authorizer on the fetcher --- GoogleSignIn/Sources/GIDSignIn.m | 1 + 1 file changed, 1 insertion(+) diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 8b90953f..7601362f 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -885,6 +885,7 @@ - (void)startFetchURL:(NSURL *)URL fetcher.retryEnabled = YES; fetcher.maxRetryInterval = kFetcherMaxRetryInterval; fetcher.comment = comment; + fetcher.authorizer = authorization; [fetcher beginFetchWithCompletionHandler:handler]; } From e25d0440297868b73114b0389aba3a49ae7c8165 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Tue, 28 Feb 2023 20:47:14 -0800 Subject: [PATCH 03/38] Add the error handling delegate on the authorization --- GoogleSignIn/Sources/GIDSignIn.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 7601362f..1325ffa7 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -27,6 +27,7 @@ #import "GoogleSignIn/Sources/GIDCallbackQueue.h" #import "GoogleSignIn/Sources/GIDScopes.h" #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" +#import "GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h" #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST #import "GoogleSignIn/Sources/GIDAuthStateMigration.h" #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" @@ -168,6 +169,8 @@ @implementation GIDSignIn { BOOL _restarting; // Keychain manager for GTMAppAuth GTMKeychainStore *_keychainStore; + + GIDAppAuthFetcherAuthorizationWithEMMSupport *_authorizationDelegate; } #pragma mark - Public methods @@ -469,6 +472,7 @@ - (id)initPrivate { if (isFreshInstall) { [self removeAllKeychainEntries]; } + _authorizationDelegate = [[GIDAppAuthFetcherAuthorizationWithEMMSupport alloc] init]; NSString *authorizationEnpointURL = [NSString stringWithFormat:kAuthorizationURLTemplate, [GIDSignInPreferences googleAuthorizationServer]]; @@ -876,6 +880,7 @@ - (void)startFetchURL:(NSURL *)URL NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; GTMSessionFetcher *fetcher; GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; + authorization.delegate = _authorizationDelegate; id fetcherService = authorization.fetcherService; if (fetcherService) { fetcher = [fetcherService fetcherWithRequest:request]; From aea7ec0e407849faf3f07f34a26fd1790878fa39 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Fri, 3 Mar 2023 19:33:18 -0800 Subject: [PATCH 04/38] Add some support for testing emm support --- GoogleSignIn/Sources/GIDEMMSupport.h | 8 ++- GoogleSignIn/Sources/GIDEMMSupport.m | 13 +++++ GoogleSignIn/Sources/GIDGoogleUser.m | 35 +++---------- GoogleSignIn/Sources/GIDSignIn.m | 6 --- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 38 ++++++++++++++ .../Tests/Unit/GIDFailingOIDAuthState.h | 29 +++++++++++ .../Tests/Unit/GIDFailingOIDAuthState.m | 35 +++++++++++++ GoogleSignIn/Tests/Unit/GIDFakeFetcher.h | 11 ++++- GoogleSignIn/Tests/Unit/GIDFakeFetcher.m | 33 +++++++++++++ .../Tests/Unit/GIDFakeFetcherService.h | 16 +++++- .../Tests/Unit/GIDFakeFetcherService.m | 24 ++++++++- .../Tests/Unit/GIDGoogleUser+Testing.h | 6 +++ GoogleSignIn/Tests/Unit/GIDTestWorker.h | 39 +++++++++++++++ GoogleSignIn/Tests/Unit/GIDTestWorker.m | 49 +++++++++++++++++++ .../Tests/Unit/OIDAuthState+Testing.m | 1 + 15 files changed, 303 insertions(+), 40 deletions(-) create mode 100644 GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.h create mode 100644 GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m create mode 100644 GoogleSignIn/Tests/Unit/GIDTestWorker.h create mode 100644 GoogleSignIn/Tests/Unit/GIDTestWorker.m diff --git a/GoogleSignIn/Sources/GIDEMMSupport.h b/GoogleSignIn/Sources/GIDEMMSupport.h index 45cf0577..15d98559 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.h +++ b/GoogleSignIn/Sources/GIDEMMSupport.h @@ -20,10 +20,16 @@ #import +#ifdef SWIFT_PACKAGE +@import GTMAppAuth; +#else +#import +#endif + NS_ASSUME_NONNULL_BEGIN // A class to support EMM (Enterprise Mobility Management). -@interface GIDEMMSupport : NSObject +@interface GIDEMMSupport : NSObject + (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error; diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index 254db4d2..ba04d825 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -100,6 +100,19 @@ + (NSDictionary *)parametersWithParameters:(NSDictionary *)parameters return allParameters; } +#pragma mark - GTMAuthSessionDelegate + +- (nullable NSDictionary *) +additionalTokenRefreshParametersForAuthSession:(GTMAuthSession *)authSession { + return [GIDEMMSupport updatedEMMParametersWithParameters: + authSession.authState.lastTokenResponse.additionalParameters]; +} + +- (nullable NSError *)updatedErrorForAuthSession:(GTMAuthSession *)authSession + originalError:(NSError *)originalError { + return [GIDEMMSupport handleTokenFetchEMMError:originalError]; +} + @end NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 58636e8b..8eea843a 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -29,8 +29,10 @@ #ifdef SWIFT_PACKAGE @import AppAuth; +@import GTMAppAuth; #else #import +#import #endif NS_ASSUME_NONNULL_BEGIN @@ -52,7 +54,9 @@ // Minimal time interval before expiration for the access token or it needs to be refreshed. static NSTimeInterval const kMinimalTimeToExpire = 60.0; -@interface GIDGoogleUser () +@interface GIDGoogleUser () + +@property (nonatomic, strong) id authSessionDelegate; @end @@ -240,7 +244,8 @@ - (instancetype)initWithAuthState:(OIDAuthState *)authState GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; //#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST - authorization.delegate = self; + self.authSessionDelegate = [[GIDEMMSupport alloc] init]; + authorization.delegate = self.authSessionDelegate; authorization.authState.stateChangeDelegate = self; self.fetcherAuthorizer = authorization; @@ -308,32 +313,6 @@ - (nullable NSString *)hostedDomain { return nil; } -#pragma mark - GTMAuthSessionDelegate - -- (nullable NSDictionary *)additionalRefreshParameters: - (GTMAuthSession *)authorization { -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - return [GIDEMMSupport updatedEMMParametersWithParameters: - authorization.authState.lastTokenResponse.request.additionalParameters]; -#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST - return authorization.authState.lastTokenResponse.request.additionalParameters; -#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST -} - -- (nullable NSDictionary *)additionalTokenRefreshParametersForAuthSession:(GTMAuthSession *)authSession { -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - return [GIDEMMSupport updatedEMMParametersWithParameters: - authSession.authState.lastTokenResponse.request.additionalParameters]; -#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST - return authorization.authState.lastTokenResponse.request.additionalParameters; -#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST -} - -- (nullable NSError *)updatedErrorForAuthSession:(GTMAuthSession *)authSession - originalError:(NSError *)originalError { - return [GIDEMMSupport handleTokenFetchEMMError:originalError]; -} - #pragma mark - OIDAuthStateChangeDelegate - (void)didChangeState:(OIDAuthState *)state { diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 1325ffa7..8b90953f 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -27,7 +27,6 @@ #import "GoogleSignIn/Sources/GIDCallbackQueue.h" #import "GoogleSignIn/Sources/GIDScopes.h" #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" -#import "GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h" #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST #import "GoogleSignIn/Sources/GIDAuthStateMigration.h" #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" @@ -169,8 +168,6 @@ @implementation GIDSignIn { BOOL _restarting; // Keychain manager for GTMAppAuth GTMKeychainStore *_keychainStore; - - GIDAppAuthFetcherAuthorizationWithEMMSupport *_authorizationDelegate; } #pragma mark - Public methods @@ -472,7 +469,6 @@ - (id)initPrivate { if (isFreshInstall) { [self removeAllKeychainEntries]; } - _authorizationDelegate = [[GIDAppAuthFetcherAuthorizationWithEMMSupport alloc] init]; NSString *authorizationEnpointURL = [NSString stringWithFormat:kAuthorizationURLTemplate, [GIDSignInPreferences googleAuthorizationServer]]; @@ -880,7 +876,6 @@ - (void)startFetchURL:(NSURL *)URL NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; GTMSessionFetcher *fetcher; GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; - authorization.delegate = _authorizationDelegate; id fetcherService = authorization.fetcherService; if (fetcherService) { fetcher = [fetcherService fetcherWithRequest:request]; @@ -890,7 +885,6 @@ - (void)startFetchURL:(NSURL *)URL fetcher.retryEnabled = YES; fetcher.maxRetryInterval = kFetcherMaxRetryInterval; fetcher.comment = comment; - fetcher.authorizer = authorization; [fetcher beginFetchWithCompletionHandler:handler]; } diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index aaf5c71e..c87f03fa 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -26,6 +26,11 @@ #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" #import "GoogleSignIn/Sources/GIDMDMPasscodeState.h" +#import "GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h" +#import "GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.h" +#import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" +#import "GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h" +#import "GoogleSignIn/Tests/Unit/GIDTestWorker.h" #ifdef SWIFT_PACKAGE @import AppAuth; @@ -57,6 +62,39 @@ @interface GIDEMMSupportTest : XCTestCase @implementation GIDEMMSupportTest +- (void)testEMMSupportDelegate { + GIDEMMSupport *emmSupport = [[GIDEMMSupport alloc] init]; + OIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; + GTMAuthSession *authSession = [[GTMAuthSession alloc] initWithAuthState:authState]; + authSession.delegate = emmSupport; + GIDFakeFetcherService *fakeFetcherService = [[GIDFakeFetcherService alloc] + initWithAuthorizer:authSession]; + NSDictionary *userInfo = @{ + @"OIDOAuthErrorResponseErrorKey": @[@"foo", @"bar"], + NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] + }; + NSError *expectedError = [NSError errorWithDomain:@"org.openid.appauth.resourceserver" + code:0 + userInfo:userInfo]; + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@""]]; + GTMSessionFetcher *fakeFetcher = [fakeFetcherService fetcherWithRequest:request + error:expectedError]; + fakeFetcher.authorizer = authSession; + + id mockGoogleUser = OCMStrictClassMock([GIDGoogleUser class]); + [[[mockGoogleUser expect] andReturn:authState] authorizer]; + + GIDTestWorker *testWorker = [[GIDTestWorker alloc] initWithGoogleUser:mockGoogleUser + fetcher:fakeFetcher]; + XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; + [testWorker failWorkWithCompletion:^(NSError * _Nullable error) { + XCTAssertNotNil(error); + XCTAssertEqualObjects(expectedError, error); + [emmErrorExpectation fulfill]; + }]; + [self waitForExpectations:@[emmErrorExpectation] timeout:1]; +} + - (void)testUpdatedEMMParametersWithParameters_NoEMMKey { NSDictionary *originalParameters = @{ @"not_emm_support_key" : @"xyz", diff --git a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.h b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.h new file mode 100644 index 00000000..b2f3c4f0 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.h @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef SWIFT_PACKAGE +@import AppAuth; +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface GIDFailingOIDAuthState : OIDAuthState + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m new file mode 100644 index 00000000..71d482af --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m @@ -0,0 +1,35 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GIDFailingOIDAuthState.h" + +@implementation GIDFailingOIDAuthState + +// Forces the OIDAuthState to fail with the error below to simulate an error handled by EMM support +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action + additionalRefreshParameters:(NSDictionary *)additionalParameters + dispatchQueue:(dispatch_queue_t)dispatchQueue { + NSDictionary *userInfo = @{ + @"OIDOAuthErrorResponseErrorKey": @[@"foo", @"bar"], + NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] + }; + NSError *error = [NSError errorWithDomain:@"org.openid.appauth.resourceserver" + code:0 + userInfo:userInfo]; + action(nil, nil, error); +} + +@end diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h index 10cd91ef..2d0e2a65 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h @@ -20,14 +20,21 @@ #import #endif -// A fake |GTMHTTPFetcher| for testing. +/// A fake |GTMHTTPFetcher| for testing. @interface GIDFakeFetcher : GTMSessionFetcher -// The URL of the fetching request. +/// The URL of the fetching request. - (NSURL *)requestURL; // Emulates server returning with data and/or error. - (void)didFinishWithData:(NSData *)data error:(NSError *)error; - (instancetype)initWithRequest:(NSURLRequest *)request; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +- (instancetype)initWithRequest:(NSURLRequest *)request + authorizer:(id)authorizer + error:(nullable NSError *)error; +#pragma clang diagnostic pop @end diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m index 79221f99..7106c3a0 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m @@ -13,9 +13,20 @@ // limitations under the License. #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" +#ifdef SWIFT_PACKAGE +@import GTMAppAuth; +#else +#import +#endif typedef void (^FetchCompletionHandler)(NSData *, NSError *); +@interface GIDFakeFetcher () + +@property(nonatomic, strong) NSError *fetcherError; + +@end + @implementation GIDFakeFetcher { FetchCompletionHandler _handler; NSURL *_requestURL; @@ -29,6 +40,19 @@ - (instancetype)initWithRequest:(NSURLRequest *)request { return self; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +- (instancetype)initWithRequest:(NSURLRequest *)request + authorizer:(id)authorizer + error:(nullable NSError *)error { +#pragma clang diagnostic pop + self = [self initWithRequest:request]; + if (self) { + self.authorizer = authorizer; + self.fetcherError = error; + } + return self; +} - (void)beginFetchWithDelegate:(id)delegate didFinishSelector:(SEL)finishedSEL { [NSException raise:@"NotImplementedException" format:@"Implement this method if it is used"]; @@ -39,6 +63,15 @@ - (void)beginFetchWithCompletionHandler:(FetchCompletionHandler)handler { [NSException raise:NSInvalidArgumentException format:@"Attempted start fetch again"]; } _handler = [handler copy]; + [self authorizeRequest]; + handler(nil, self.fetcherError); +} + +- (void)authorizeRequest { + NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:self.request.URL]; + [self.authorizer authorizeRequest:mutableRequest completionHandler:^(NSError * _Nullable error) { + self.fetcherError = error; + }]; } - (NSURL *)requestURL { diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h index e54aa149..6e5aeacd 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h @@ -23,7 +23,21 @@ // A fake |GTMHTTPFetcherService| for testing. @interface GIDFakeFetcherService : NSObject -// Returns the list of |GPPFakeFetcher| objects that have been created. +/// Creates an instance of this fake with an authorizer. +- initWithAuthorizer:(id)authorizer; + +/// Returns the list of |GPPFakeFetcher| objects that have been created. - (NSArray *)fetchers; +/// Creates a `GTMSessionFetcher` with the provided request and error. +/// +/// The error is passed to the returned `GIDFakeFetcher` to simulate failing fetches. +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request error:(NSError *)error; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +/// The instance to use for authorizing requeests. +@property (nonatomic, strong) id authorizer; +#pragma clang diagnostic pop + @end diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m index 002a9172..45e73fd2 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m @@ -13,7 +13,6 @@ // limitations under the License. #import "GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h" - #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" @implementation GIDFakeFetcherService { @@ -32,6 +31,17 @@ - (instancetype)init { return self; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +- (instancetype)initWithAuthorizer:(id)authorizer { +#pragma clang diagnostic pop + self = [self init]; + if (self) { + self.authorizer = authorizer; + } + return self; +} + - (BOOL)fetcherShouldBeginFetching:(GTMSessionFetcher *)fetcher { return YES; } @@ -49,8 +59,18 @@ - (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher { return NO; } +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request error:(NSError *)error { + GIDFakeFetcher *fetcher = [[GIDFakeFetcher alloc] initWithRequest:request + authorizer:self.authorizer + error:error]; + [_fetchers addObject:fetcher]; + return fetcher; +} + - (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request { - GIDFakeFetcher *fetcher = [[GIDFakeFetcher alloc] initWithRequest:request]; + GIDFakeFetcher *fetcher = [[GIDFakeFetcher alloc] initWithRequest:request + authorizer:self.authorizer + error:nil]; [_fetchers addObject:fetcher]; return fetcher; } diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUser+Testing.h b/GoogleSignIn/Tests/Unit/GIDGoogleUser+Testing.h index 3f833030..5b36f2f5 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUser+Testing.h +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUser+Testing.h @@ -16,6 +16,12 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h" +#ifdef SWIFT_PACKAGE +@import AppAuthCore; +#else +#import +#endif + @interface GIDGoogleUser (Testing) - (BOOL)isEqual:(id)object; diff --git a/GoogleSignIn/Tests/Unit/GIDTestWorker.h b/GoogleSignIn/Tests/Unit/GIDTestWorker.h new file mode 100644 index 00000000..5713947e --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDTestWorker.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GIDGoogleUser; +@class GTMSessionFetcher; + +NS_ASSUME_NONNULL_BEGIN + +/// Class used in testing EMM error handling in `GIDEMMSupportTest`. +@interface GIDTestWorker : NSObject + +/// Creates an instance with a Google user. +/// +/// Ensure that the `GIDGoogleUser` has some way to return an `authorizer` of time `GTMAuthSession` +/// with its delegate set to `GIDEMMSupport`. +- (instancetype)initWithGoogleUser:(nonnull GIDGoogleUser *)googleUser + fetcher:(nonnull GTMSessionFetcher *)fetcher; + +/// Fails the work encapsulated by this type with the given error. +- (void)failWorkWithCompletion:(void (^)(NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/GIDTestWorker.m b/GoogleSignIn/Tests/Unit/GIDTestWorker.m new file mode 100644 index 00000000..d9094ee5 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDTestWorker.m @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GIDTestWorker.h" +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h" +#import +#import "GoogleSignIn/Sources/GIDEMMSupport.h" + +@interface GIDTestWorker () + +@property(nonatomic, strong) GIDGoogleUser *googleUser; +@property(nonatomic, strong) GTMSessionFetcher *fetcher; + +@end + +@implementation GIDTestWorker + +- (instancetype)initWithGoogleUser:(nonnull GIDGoogleUser *)googleUser + fetcher:(nonnull GTMSessionFetcher *)fetcher { + self = [super init]; + if (self) { + self.googleUser = googleUser; + self.fetcher = fetcher; + self.fetcher.authorizer = self.googleUser.fetcherAuthorizer; + } + return self; +} + +- (void)failWorkWithCompletion:(void (^)(NSError *_Nullable))completion { + [self.fetcher beginFetchWithCompletionHandler:^(NSData * _Nullable data, + NSError * _Nullable error) { + completion(error); + }]; +} + +@end diff --git a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m index c6c694a4..c49b2abd 100644 --- a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m +++ b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m @@ -46,4 +46,5 @@ + (instancetype)testInstanceWithIDToken:(NSString *)idToken return [self testInstanceWithTokenResponse:newResponse]; } + @end From 99b73d22c8372c12ad8831a1238697370a8c5ac8 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Fri, 3 Mar 2023 19:38:57 -0800 Subject: [PATCH 05/38] Do not expose method creating fetcher with an error as unneeded --- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 21 +++++++++++-------- GoogleSignIn/Tests/Unit/GIDFakeFetcher.h | 3 +-- GoogleSignIn/Tests/Unit/GIDFakeFetcher.m | 6 ++---- .../Tests/Unit/GIDFakeFetcherService.h | 5 ----- .../Tests/Unit/GIDFakeFetcherService.m | 11 +--------- 5 files changed, 16 insertions(+), 30 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index c87f03fa..8858411f 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -63,12 +63,7 @@ @interface GIDEMMSupportTest : XCTestCase @implementation GIDEMMSupportTest - (void)testEMMSupportDelegate { - GIDEMMSupport *emmSupport = [[GIDEMMSupport alloc] init]; - OIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; - GTMAuthSession *authSession = [[GTMAuthSession alloc] initWithAuthState:authState]; - authSession.delegate = emmSupport; - GIDFakeFetcherService *fakeFetcherService = [[GIDFakeFetcherService alloc] - initWithAuthorizer:authSession]; + XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; NSDictionary *userInfo = @{ @"OIDOAuthErrorResponseErrorKey": @[@"foo", @"bar"], NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] @@ -76,9 +71,16 @@ - (void)testEMMSupportDelegate { NSError *expectedError = [NSError errorWithDomain:@"org.openid.appauth.resourceserver" code:0 userInfo:userInfo]; + + GIDEMMSupport *emmSupport = [[GIDEMMSupport alloc] init]; + OIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; + GTMAuthSession *authSession = [[GTMAuthSession alloc] initWithAuthState:authState]; + authSession.delegate = emmSupport; + GIDFakeFetcherService *fakeFetcherService = [[GIDFakeFetcherService alloc] + initWithAuthorizer:authSession]; + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@""]]; - GTMSessionFetcher *fakeFetcher = [fakeFetcherService fetcherWithRequest:request - error:expectedError]; + GTMSessionFetcher *fakeFetcher = [fakeFetcherService fetcherWithRequest:request]; fakeFetcher.authorizer = authSession; id mockGoogleUser = OCMStrictClassMock([GIDGoogleUser class]); @@ -86,12 +88,13 @@ - (void)testEMMSupportDelegate { GIDTestWorker *testWorker = [[GIDTestWorker alloc] initWithGoogleUser:mockGoogleUser fetcher:fakeFetcher]; - XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; + [testWorker failWorkWithCompletion:^(NSError * _Nullable error) { XCTAssertNotNil(error); XCTAssertEqualObjects(expectedError, error); [emmErrorExpectation fulfill]; }]; + [self waitForExpectations:@[emmErrorExpectation] timeout:1]; } diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h index 2d0e2a65..c31c05eb 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.h @@ -34,7 +34,6 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated" - (instancetype)initWithRequest:(NSURLRequest *)request - authorizer:(id)authorizer - error:(nullable NSError *)error; + authorizer:(id)authorizer; #pragma clang diagnostic pop @end diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m index 7106c3a0..f2ea7ac0 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m @@ -23,7 +23,7 @@ @interface GIDFakeFetcher () -@property(nonatomic, strong) NSError *fetcherError; +@property(nonatomic, strong, nullable) NSError *fetcherError; @end @@ -43,13 +43,11 @@ - (instancetype)initWithRequest:(NSURLRequest *)request { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated" - (instancetype)initWithRequest:(NSURLRequest *)request - authorizer:(id)authorizer - error:(nullable NSError *)error { + authorizer:(id)authorizer { #pragma clang diagnostic pop self = [self initWithRequest:request]; if (self) { self.authorizer = authorizer; - self.fetcherError = error; } return self; } diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h index 6e5aeacd..f09d1894 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h @@ -29,11 +29,6 @@ /// Returns the list of |GPPFakeFetcher| objects that have been created. - (NSArray *)fetchers; -/// Creates a `GTMSessionFetcher` with the provided request and error. -/// -/// The error is passed to the returned `GIDFakeFetcher` to simulate failing fetches. -- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request error:(NSError *)error; - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated" /// The instance to use for authorizing requeests. diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m index 45e73fd2..bab7c34b 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.m @@ -59,18 +59,9 @@ - (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher { return NO; } -- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request error:(NSError *)error { - GIDFakeFetcher *fetcher = [[GIDFakeFetcher alloc] initWithRequest:request - authorizer:self.authorizer - error:error]; - [_fetchers addObject:fetcher]; - return fetcher; -} - - (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request { GIDFakeFetcher *fetcher = [[GIDFakeFetcher alloc] initWithRequest:request - authorizer:self.authorizer - error:nil]; + authorizer:self.authorizer]; [_fetchers addObject:fetcher]; return fetcher; } From 193ea42d977bc82f5383ba0e2c63e53b1b6dd12e Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Tue, 7 Mar 2023 17:41:54 -0800 Subject: [PATCH 06/38] Add test for testing EMM error handling flow with GTMAppAuth --- GoogleSignIn/Sources/GIDEMMSupport.m | 43 +++++++++++++++++-- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 25 ++++++----- .../Tests/Unit/GIDFailingOIDAuthState.m | 20 ++++++++- GoogleSignIn/Tests/Unit/GIDFakeFetcher.m | 6 +-- GoogleSignIn/Tests/Unit/GIDTestWorker.m | 1 - 5 files changed, 74 insertions(+), 21 deletions(-) diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index ba04d825..ef82d258 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -44,12 +44,49 @@ // New UIDevice system name for iOS. static NSString *const kNewIOSSystemName = @"iOS"; +// The error key in the server response. +static NSString *const kErrorKey = @"error"; + +// Error strings in the server response. +static NSString *const kGeneralErrorPrefix = @"emm_"; +static NSString *const kScreenlockRequiredError = @"emm_passcode_required"; +static NSString *const kAppVerificationRequiredErrorPrefix = @"emm_app_verification_required"; + +// Optional separator between error prefix and the payload. +static NSString *const kErrorPayloadSeparator = @":"; + +// A list for recognized error codes. +typedef enum { + ErrorCodeNone = 0, + ErrorCodeDeviceNotCompliant, + ErrorCodeScreenlockRequired, + ErrorCodeAppVerificationRequired, +} ErrorCode; + @implementation GIDEMMSupport + (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error { - return [NSError errorWithDomain:kGIDSignInErrorDomain - code:kGIDSignInErrorCodeEMM - userInfo:error.userInfo]; + NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey]; + ErrorCode errorCode = ErrorCodeNone; + + if (errorJSON) { + id errorValue = errorJSON[kErrorKey]; + if ([errorValue isEqual:kScreenlockRequiredError]) { + errorCode = ErrorCodeScreenlockRequired; + } else if ([errorValue hasPrefix:kAppVerificationRequiredErrorPrefix]) { + errorCode = ErrorCodeAppVerificationRequired; + } else if ([errorValue hasPrefix:kGeneralErrorPrefix]) { + errorCode = ErrorCodeDeviceNotCompliant; + } + } + + if (errorCode) { + return [NSError errorWithDomain:kGIDSignInErrorDomain + code:kGIDSignInErrorCodeEMM + userInfo:error.userInfo]; + } else { + return error; + } } + (void)handleTokenFetchEMMError:(nullable NSError *)error diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index 8858411f..c58a58ae 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -64,16 +64,10 @@ @implementation GIDEMMSupportTest - (void)testEMMSupportDelegate { XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; - NSDictionary *userInfo = @{ - @"OIDOAuthErrorResponseErrorKey": @[@"foo", @"bar"], - NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] - }; - NSError *expectedError = [NSError errorWithDomain:@"org.openid.appauth.resourceserver" - code:0 - userInfo:userInfo]; + GIDEMMSupport *emmSupport = [[GIDEMMSupport alloc] init]; - OIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; + GIDFailingOIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; GTMAuthSession *authSession = [[GTMAuthSession alloc] initWithAuthState:authState]; authSession.delegate = emmSupport; GIDFakeFetcherService *fakeFetcherService = [[GIDFakeFetcherService alloc] @@ -81,16 +75,21 @@ - (void)testEMMSupportDelegate { NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@""]]; GTMSessionFetcher *fakeFetcher = [fakeFetcherService fetcherWithRequest:request]; - fakeFetcher.authorizer = authSession; - - id mockGoogleUser = OCMStrictClassMock([GIDGoogleUser class]); - [[[mockGoogleUser expect] andReturn:authState] authorizer]; - GIDTestWorker *testWorker = [[GIDTestWorker alloc] initWithGoogleUser:mockGoogleUser + GIDGoogleUser *user = [[GIDGoogleUser alloc] init]; + GIDTestWorker *testWorker = [[GIDTestWorker alloc] initWithGoogleUser:user fetcher:fakeFetcher]; [testWorker failWorkWithCompletion:^(NSError * _Nullable error) { XCTAssertNotNil(error); + NSDictionary *userInfo = @{ + // FIXME: (mdmathias) Reuse values listed in `GIDEMMSupport.m` + @"OIDOAuthErrorResponseErrorKey": @{@"error": @"emm_passcode_required"}, + NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] + }; + NSError *expectedError = [NSError errorWithDomain:kGIDSignInErrorDomain + code:kGIDSignInErrorCodeEMM + userInfo:userInfo]; XCTAssertEqualObjects(expectedError, error); [emmErrorExpectation fulfill]; }]; diff --git a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m index 71d482af..8703e59d 100644 --- a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m +++ b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m @@ -15,15 +15,33 @@ */ #import "GIDFailingOIDAuthState.h" +#import "GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h" +#import "GoogleSignIn/Tests/Unit/OIDAuthorizationResponse+Testing.h" +#import "GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.h" @implementation GIDFailingOIDAuthState ++ (instancetype)testInstance { + return [[GIDFailingOIDAuthState alloc] + initWithAuthorizationResponse:[OIDAuthorizationResponse testInstance] + tokenResponse:[OIDTokenResponse testInstance]]; +} + +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action + additionalRefreshParameters: + (nullable NSDictionary *)additionalParameters { + [self performActionWithFreshTokens:action + additionalRefreshParameters:additionalParameters + dispatchQueue:dispatch_get_main_queue()]; +} + // Forces the OIDAuthState to fail with the error below to simulate an error handled by EMM support - (void)performActionWithFreshTokens:(OIDAuthStateAction)action additionalRefreshParameters:(NSDictionary *)additionalParameters dispatchQueue:(dispatch_queue_t)dispatchQueue { NSDictionary *userInfo = @{ - @"OIDOAuthErrorResponseErrorKey": @[@"foo", @"bar"], + // FIXME: (mdmathias) Reuse values listed in `GIDEMMSupport.m` + @"OIDOAuthErrorResponseErrorKey": @{@"error": @"emm_passcode_required"}, NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] }; NSError *error = [NSError errorWithDomain:@"org.openid.appauth.resourceserver" diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m index f2ea7ac0..c1488f53 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m @@ -61,14 +61,14 @@ - (void)beginFetchWithCompletionHandler:(FetchCompletionHandler)handler { [NSException raise:NSInvalidArgumentException format:@"Attempted start fetch again"]; } _handler = [handler copy]; - [self authorizeRequest]; - handler(nil, self.fetcherError); + [self authorizeRequestWithCompletion:handler]; } -- (void)authorizeRequest { +- (void)authorizeRequestWithCompletion:(FetchCompletionHandler)completion { NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:self.request.URL]; [self.authorizer authorizeRequest:mutableRequest completionHandler:^(NSError * _Nullable error) { self.fetcherError = error; + completion(nil, error); }]; } diff --git a/GoogleSignIn/Tests/Unit/GIDTestWorker.m b/GoogleSignIn/Tests/Unit/GIDTestWorker.m index d9094ee5..1d33fd05 100644 --- a/GoogleSignIn/Tests/Unit/GIDTestWorker.m +++ b/GoogleSignIn/Tests/Unit/GIDTestWorker.m @@ -34,7 +34,6 @@ - (instancetype)initWithGoogleUser:(nonnull GIDGoogleUser *)googleUser if (self) { self.googleUser = googleUser; self.fetcher = fetcher; - self.fetcher.authorizer = self.googleUser.fetcherAuthorizer; } return self; } From 0eb2f1f5f08e65d5bda255eea75e570a5132903a Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 8 Mar 2023 12:59:48 -0800 Subject: [PATCH 07/38] Add doc comments to GIDEMMSupport --- GoogleSignIn/Sources/GIDEMMSupport.h | 8 ++++---- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 1 - GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/GoogleSignIn/Sources/GIDEMMSupport.h b/GoogleSignIn/Sources/GIDEMMSupport.h index 15d98559..27a1d950 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.h +++ b/GoogleSignIn/Sources/GIDEMMSupport.h @@ -28,19 +28,19 @@ NS_ASSUME_NONNULL_BEGIN -// A class to support EMM (Enterprise Mobility Management). +/// A class to support EMM (Enterprise Mobility Management). @interface GIDEMMSupport : NSObject + (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error; -// Handles potential EMM error from token fetch response. +/// Handles potential EMM error from token fetch response. + (void)handleTokenFetchEMMError:(nullable NSError *)error completion:(void (^)(NSError *_Nullable))completion; -// Gets a new set of URL parameters that contains updated EMM-related URL parameters if needed. +/// Gets a new set of URL parameters that contains updated EMM-related URL parameters if needed. + (NSDictionary *)updatedEMMParametersWithParameters:(NSDictionary *)parameters; -// Gets a new set of URL parameters that also contains EMM-related URL parameters if needed. +/// Gets a new set of URL parameters that also contains EMM-related URL parameters if needed. + (NSDictionary *)parametersWithParameters:(NSDictionary *)parameters emmSupport:(nullable NSString *)emmSupport isPasscodeInfoRequired:(BOOL)isPasscodeInfoRequired; diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index c58a58ae..54e5791f 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -83,7 +83,6 @@ - (void)testEMMSupportDelegate { [testWorker failWorkWithCompletion:^(NSError * _Nullable error) { XCTAssertNotNil(error); NSDictionary *userInfo = @{ - // FIXME: (mdmathias) Reuse values listed in `GIDEMMSupport.m` @"OIDOAuthErrorResponseErrorKey": @{@"error": @"emm_passcode_required"}, NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] }; diff --git a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m index 8703e59d..ae2e7847 100644 --- a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m +++ b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m @@ -40,7 +40,6 @@ - (void)performActionWithFreshTokens:(OIDAuthStateAction)action additionalRefreshParameters:(NSDictionary *)additionalParameters dispatchQueue:(dispatch_queue_t)dispatchQueue { NSDictionary *userInfo = @{ - // FIXME: (mdmathias) Reuse values listed in `GIDEMMSupport.m` @"OIDOAuthErrorResponseErrorKey": @{@"error": @"emm_passcode_required"}, NSUnderlyingErrorKey: [NSError errorWithDomain:@"SomeUnderlyingError" code:0 userInfo:nil] }; From bd8325ee0b837f8deb3aa598f7888d0c7b757656 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 22 Mar 2023 14:38:40 -0700 Subject: [PATCH 08/38] Fix GIDAuthStateMigrationTest --- ...ppAuthFetcherAuthorizationWithEMMSupport.h | 36 ----- ...ppAuthFetcherAuthorizationWithEMMSupport.m | 108 -------------- GoogleSignIn/Sources/GIDAuthStateMigration.h | 24 ++- GoogleSignIn/Sources/GIDAuthStateMigration.m | 56 ++++--- GoogleSignIn/Sources/GIDGoogleUser.m | 10 +- GoogleSignIn/Sources/GIDGoogleUser_Private.h | 2 +- GoogleSignIn/Sources/GIDSignIn.m | 10 +- .../Public/GoogleSignIn/GIDGoogleUser.h | 5 - .../Tests/Unit/GIDAuthStateMigrationTest.m | 139 ++++++++++-------- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 54 +++---- 10 files changed, 171 insertions(+), 273 deletions(-) delete mode 100644 GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h delete mode 100644 GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m diff --git a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h b/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h deleted file mode 100644 index b0f04816..00000000 --- a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - -#ifdef SWIFT_PACKAGE -@import GTMAppAuth; -#else -#import -#endif - -NS_ASSUME_NONNULL_BEGIN - -// A specialized GTMAppAuthFetcherAuthorization subclass with EMM support. -@interface GIDAppAuthFetcherAuthorizationWithEMMSupport : NSObject - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST diff --git a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m b/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m deleted file mode 100644 index 4fb2133e..00000000 --- a/GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.m +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - -#import "GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h" - -#import "GoogleSignIn/Sources/GIDEMMSupport.h" - -#ifdef SWIFT_PACKAGE -@import AppAuth; -@import GTMAppAuth; -#else -#import -#import -#endif - -NS_ASSUME_NONNULL_BEGIN - -// The specialized GTMAppAuthFetcherAuthorization delegate that handles potential EMM error -// responses. -@interface GIDAppAuthFetcherAuthorizationEMMChainedDelegate : NSObject - -// Initializes with chained delegate and selector. -- (instancetype)initWithDelegate:(id)delegate selector:(SEL)selector; - -// The callback method for GTMAuthSession to invoke. -- (void)authentication:(GTMAuthSession *)auth - request:(NSMutableURLRequest *)request - finishedWithError:(nullable NSError *)error; - -@end - -@implementation GIDAppAuthFetcherAuthorizationEMMChainedDelegate { - // We use a weak reference here to match GTMAppAuthFetcherAuthorization. - __weak id _delegate; - SEL _selector; - // We need to maintain a reference to the chained delegate because GTMAuthSession only keeps a - // weak reference. - GIDAppAuthFetcherAuthorizationEMMChainedDelegate *_retained_self; -} - -- (instancetype)initWithDelegate:(id)delegate selector:(SEL)selector { - self = [super init]; - if (self) { - _delegate = delegate; - _selector = selector; - _retained_self = self; - } - return self; -} - -- (void)authentication:(GTMAuthSession *)auth - request:(NSMutableURLRequest *)request - finishedWithError:(nullable NSError *)error { - [GIDEMMSupport handleTokenFetchEMMError:error completion:^(NSError *_Nullable error) { - if (!self->_delegate || !self->_selector) { - return; - } - NSMethodSignature *signature = [self->_delegate methodSignatureForSelector:self->_selector]; - if (!signature) { - return; - } - id argument1 = auth; - id argument2 = request; - id argument3 = error; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; - [invocation setTarget:self->_delegate]; // index 0 - [invocation setSelector:self->_selector]; // index 1 - [invocation setArgument:&argument1 atIndex:2]; - [invocation setArgument:&argument2 atIndex:3]; - [invocation setArgument:&argument3 atIndex:4]; - [invocation invoke]; - }]; - // Prepare to deallocate the chained delegate instance because the above block will retain the - // iVar references it uses. - _retained_self = nil; -} - -@end - -@implementation GIDAppAuthFetcherAuthorizationWithEMMSupport - -- (nullable NSError *)updatedErrorForAuthSession:(GTMAuthSession *)authSession - originalError:(NSError *)originalError { - return [GIDEMMSupport handleTokenFetchEMMError:originalError]; -} - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration.h index 1da012d7..f5a1fe1d 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.h +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.h @@ -16,18 +16,34 @@ #import +@class GTMKeychainStore; +@class GTMAuthSession; + NS_ASSUME_NONNULL_BEGIN -// A class providing migration support for auth state saved by older versions of the SDK. +/// A class providing migration support for auth state saved by older versions of the SDK. @interface GIDAuthStateMigration : NSObject -// Perform a one-time migration for auth state saved by GPPSignIn 1.x or GIDSignIn 1.0 - 4.x to the -// GTMAppAuth storage introduced in GIDSignIn 5.0. -+ (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL +/// Creates an instance of this migration type. +/// +/// - Note: Uses `"auth"` as the keychain item name for the `GTMKeychainStore`, which is created +/// within the initializer. +- (instancetype)init; + +/// Creates an instance of this migration type with the keychain storage wrapper it will use. +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore NS_DESIGNATED_INITIALIZER; + +/// Perform a one-time migration for auth state saved by GPPSignIn 1.x or GIDSignIn 1.0 - 4.x to the +/// GTMAppAuth storage introduced in GIDSignIn 5.0. +- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath keychainName:(NSString *)keychainName isFreshInstall:(BOOL)isFreshInstall; +/// Returns a `GTMAuthSession` given the provided token URL. +- (nullable GTMAuthSession *) + extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath; + @end NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index 27681bcc..cea30b34 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -21,8 +21,8 @@ @import GTMAppAuth; #else #import -#import -#import +#import +#import #endif NS_ASSUME_NONNULL_BEGIN @@ -39,9 +39,28 @@ // Keychain service name used to store the last used fingerprint value. static NSString *const kFingerprintService = @"fingerprint"; +@interface GIDAuthStateMigration () + +@property (nonatomic, strong) GTMKeychainStore *keychainStore; + +@end + @implementation GIDAuthStateMigration -+ (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { + self = [super init]; + if (self) { + self.keychainStore = keychainStore; + } + return self; +} + +- (instancetype)init { + GTMKeychainStore *keychainStore = [[GTMKeychainStore alloc] initWithItemName:@"auth"]; + return [self initWithKeychainStore:keychainStore]; +} + +- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath keychainName:(NSString *)keychainName isFreshInstall:(BOOL)isFreshInstall { @@ -60,11 +79,10 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL // If migration was successful, save our migrated state to the keychain. if (authorization) { - // If we're unable to save to the keychain, return without marking migration performed. NSError *err; - GTMKeychainStore *keychainStore = [[GTMKeychainStore alloc] initWithItemName:@"auth"]; - [keychainStore saveAuthSession:authorization error:&err]; - if (!err) { + [self.keychainStore saveAuthSession:authorization error:&err]; + // If we're unable to save to the keychain, return without marking migration performed. + if (err) { return; }; } @@ -76,7 +94,7 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL // Returns a |GTMAuthSession| object containing any old auth state or |nil| if none // was found or the migration failed. -+ (nullable GTMAuthSession *) +- (nullable GTMAuthSession *) extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath { // Retrieve the last used fingerprint. NSString *fingerprint = [GIDAuthStateMigration passwordForService:kFingerprintService]; @@ -85,9 +103,10 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL } // Retrieve the GTMOAuth2 persistence string. - GTMKeychainStore *ks = [[GTMKeychainStore alloc] initWithItemName:@"auth"]; - NSString *GTMOAuth2PersistenceString = nil; // [GTMKeychain passwordFromKeychainForName:fingerprint]; - if (!GTMOAuth2PersistenceString) { + NSError *passwordError; + NSString *GTMOAuth2PersistenceString = + [self.keychainStore.keychainHelper passwordForService:fingerprint error:&passwordError]; + if (passwordError) { return nil; } @@ -129,14 +148,15 @@ + (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL additionalTokenRequestParameters]; } - // Use |GTMOAuth2KeychainCompatibility| to generate a |GTMAuthSession| from the + // Use |GTMOAuth2Compatibility| to generate a |GTMAuthSession| from the // persistence string, redirect URI, client ID, and token endpoint URL. - GTMAuthSession *authorization = [GTMOAuth2Compatibility authSessionForPersistenceString:persistenceString - tokenURL:tokenURL - redirectURI:redirectURI - clientID:clientID - clientSecret:nil - error:nil]; + GTMAuthSession *authorization = + [GTMOAuth2Compatibility authSessionForPersistenceString:persistenceString + tokenURL:tokenURL + redirectURI:redirectURI + clientID:clientID + clientSecret:nil + error:nil]; return authorization; } diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 8eea843a..dd9ce01f 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -19,7 +19,6 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h" -#import "GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h" #import "GoogleSignIn/Sources/GIDAuthentication.h" #import "GoogleSignIn/Sources/GIDEMMSupport.h" #import "GoogleSignIn/Sources/GIDProfileData_Private.h" @@ -236,14 +235,7 @@ - (instancetype)initWithAuthState:(OIDAuthState *)authState _tokenRefreshHandlerQueue = [[NSMutableArray alloc] init]; _profile = profileData; -//#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST -// GTMAppAuthFetcherAuthorization *authorization = self.emmSupport ? -// [[GIDAppAuthFetcherAuthorizationWithEMMSupport alloc] initWithAuthState:authState] : -// [[GTMAuthSession alloc] initWithAuthState:authState]; -//#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST - GTMAuthSession *authorization = - [[GTMAuthSession alloc] initWithAuthState:authState]; -//#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST + GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; self.authSessionDelegate = [[GIDEMMSupport alloc] init]; authorization.delegate = self.authSessionDelegate; authorization.authState.stateChangeDelegate = self; diff --git a/GoogleSignIn/Sources/GIDGoogleUser_Private.h b/GoogleSignIn/Sources/GIDGoogleUser_Private.h index c3b8d8dd..a46ab9b6 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser_Private.h +++ b/GoogleSignIn/Sources/GIDGoogleUser_Private.h @@ -20,7 +20,7 @@ @import AppAuth; @import GTMAppAuth; #else -//#import +#import #import #endif diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 8b90953f..e8016895 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -481,10 +481,12 @@ - (id)initPrivate { #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST // Perform migration of auth state from old (before 5.0) versions of the SDK if needed. - [GIDAuthStateMigration migrateIfNeededWithTokenURL:_appAuthConfiguration.tokenEndpoint - callbackPath:kBrowserCallbackPath - keychainName:kGTMAppAuthKeychainName - isFreshInstall:isFreshInstall]; + GIDAuthStateMigration *migration = + [[GIDAuthStateMigration alloc] initWithKeychainStore:_keychainStore]; + [migration migrateIfNeededWithTokenURL:_appAuthConfiguration.tokenEndpoint + callbackPath:kBrowserCallbackPath + keychainName:kGTMAppAuthKeychainName + isFreshInstall:isFreshInstall]; #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST } return self; diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h index 26c78a95..94590e00 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h @@ -23,15 +23,10 @@ #import #endif -// We have to import GTMAppAuth because forward declaring the protocol does -// not generate the `fetcherAuthorizer` property below for Swift. #ifdef SWIFT_PACKAGE -//@import GTMAppAuth; -//@import AppAuthCore; @import GTMSessionFetcherCore; #else #import -//#import #endif @class GIDConfiguration; diff --git a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m index dac44c1f..a9d382b7 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m @@ -23,9 +23,9 @@ @import OCMock; #else #import -#import -#import -#import +#import +#import +#import #import #endif @@ -72,22 +72,24 @@ @implementation GIDAuthStateMigrationTest { id _mockUserDefaults; id _mockGTMAppAuthFetcherAuthorization; id _mockGIDAuthStateMigration; - id _mockGTMKeychain; + id _mockGTMKeychainStore; + id _mockKeychainHelper; id _mockNSBundle; id _mockGIDSignInCallbackSchemes; - id _mockGTMOAuth2KeychainCompatibility; + id _mockGTMOAuth2Compatibility; } - (void)setUp { [super setUp]; - _mockUserDefaults = OCMStrictClassMock([NSUserDefaults class]); + _mockUserDefaults = OCMClassMock([NSUserDefaults class]); _mockGTMAppAuthFetcherAuthorization = OCMStrictClassMock([GTMAuthSession class]); _mockGIDAuthStateMigration = OCMStrictClassMock([GIDAuthStateMigration class]); - _mockGTMKeychain = OCMStrictClassMock([GTMKeychainStore class]); + _mockGTMKeychainStore = OCMStrictClassMock([GTMKeychainStore class]); + _mockKeychainHelper = OCMProtocolMock(@protocol(GTMKeychainHelper)); _mockNSBundle = OCMStrictClassMock([NSBundle class]); _mockGIDSignInCallbackSchemes = OCMStrictClassMock([GIDSignInCallbackSchemes class]); - _mockGTMOAuth2KeychainCompatibility = OCMStrictClassMock([GTMOAuth2Compatibility class]); + _mockGTMOAuth2Compatibility = OCMStrictClassMock([GTMOAuth2Compatibility class]); } - (void)tearDown { @@ -97,14 +99,16 @@ - (void)tearDown { [_mockGTMAppAuthFetcherAuthorization stopMocking]; [_mockGIDAuthStateMigration verify]; [_mockGIDAuthStateMigration stopMocking]; - [_mockGTMKeychain verify]; - [_mockGTMKeychain stopMocking]; + [_mockGTMKeychainStore verify]; + [_mockGTMKeychainStore stopMocking]; + [_mockKeychainHelper verify]; + [_mockKeychainHelper stopMocking]; [_mockNSBundle verify]; [_mockNSBundle stopMocking]; [_mockGIDSignInCallbackSchemes verify]; [_mockGIDSignInCallbackSchemes stopMocking]; - [_mockGTMOAuth2KeychainCompatibility verify]; - [_mockGTMOAuth2KeychainCompatibility stopMocking]; + [_mockGTMOAuth2Compatibility verify]; + [_mockGTMOAuth2Compatibility stopMocking]; [super tearDown]; } @@ -113,44 +117,49 @@ - (void)tearDown { - (void)testMigrateIfNeeded_NoPreviousMigration { [[[_mockUserDefaults stub] andReturn:_mockUserDefaults] standardUserDefaults]; - [[[_mockUserDefaults expect] andReturnValue:@NO] - boolForKey:kMigrationCheckPerformedKey]; - [[[_mockGIDAuthStateMigration expect] andReturn:_mockGTMAppAuthFetcherAuthorization] - extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath]; - [[[_mockGTMKeychain expect] andReturnValue:@YES] - saveAuthSession:_mockGTMAppAuthFetcherAuthorization error:nil]; + [[[_mockUserDefaults expect] andReturnValue:@NO] boolForKey:kMigrationCheckPerformedKey]; [[_mockUserDefaults expect] setBool:YES forKey:kMigrationCheckPerformedKey]; - [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] - callbackPath:kCallbackPath - keychainName:kKeychainName - isFreshInstall:NO]; + [[_mockGTMKeychainStore expect] saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef]; + + [self setUpCommonExtractAuthorizationMocksWithFingerPrint:kSavedFingerprint]; + + GIDAuthStateMigration *migration = + [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; + [migration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath + keychainName:kKeychainName + isFreshInstall:NO]; } - (void)testMigrateIfNeeded_HasPreviousMigration { [[[_mockUserDefaults stub] andReturn:_mockUserDefaults] standardUserDefaults]; - [[[_mockUserDefaults expect] andReturnValue:@YES] - boolForKey:kMigrationCheckPerformedKey]; - - [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] - callbackPath:kCallbackPath - keychainName:kKeychainName - isFreshInstall:NO]; + [[[_mockUserDefaults expect] andReturnValue:@YES] boolForKey:kMigrationCheckPerformedKey]; + [[_mockUserDefaults reject] setBool:YES forKey:kMigrationCheckPerformedKey]; + + GIDAuthStateMigration *migration = + [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; + [migration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath + keychainName:kKeychainName + isFreshInstall:NO]; } - (void)testMigrateIfNeeded_KeychainFailure { [[[_mockUserDefaults stub] andReturn:_mockUserDefaults] standardUserDefaults]; - [[[_mockUserDefaults expect] andReturnValue:@NO] - boolForKey:kMigrationCheckPerformedKey]; - [[[_mockGIDAuthStateMigration expect] andReturn:_mockGTMAppAuthFetcherAuthorization] - extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath]; - [[[_mockGTMKeychain expect] andReturnValue:[NSNumber numberWithBool:NO]] - saveAuthSession:_mockGTMAppAuthFetcherAuthorization error:nil]; - - [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] - callbackPath:kCallbackPath - keychainName:kKeychainName - isFreshInstall:NO]; + [[[_mockUserDefaults expect] andReturnValue:@NO] boolForKey:kMigrationCheckPerformedKey]; + + NSError *keychainSaveError = [NSError new]; + OCMStub([_mockGTMKeychainStore saveAuthSession:OCMOCK_ANY error:[OCMArg setTo:keychainSaveError]]); + + [self setUpCommonExtractAuthorizationMocksWithFingerPrint:kSavedFingerprint]; + + GIDAuthStateMigration *migration = + [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; + [migration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath + keychainName:kKeychainName + isFreshInstall:NO]; } - (void)testMigrateIfNeeded_isFreshInstall { @@ -159,18 +168,36 @@ - (void)testMigrateIfNeeded_isFreshInstall { boolForKey:kMigrationCheckPerformedKey]; [[_mockUserDefaults expect] setBool:YES forKey:kMigrationCheckPerformedKey]; - [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] - callbackPath:kCallbackPath - keychainName:kKeychainName - isFreshInstall:YES]; + GIDAuthStateMigration *migration = + [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; + [migration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath + keychainName:kKeychainName + isFreshInstall:YES]; } - (void)testExtractAuthorization { - [self extractAuthorizationWithFingerprint:kSavedFingerprint]; + [self setUpCommonExtractAuthorizationMocksWithFingerPrint:kSavedFingerprint]; + + GIDAuthStateMigration *migration = + [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; + GTMAuthSession *authorization = + [migration extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath]; + + XCTAssertNotNil(authorization); } - (void)testExtractAuthorization_HostedDomain { - [self extractAuthorizationWithFingerprint:kSavedFingerprint_HostedDomain]; + [self setUpCommonExtractAuthorizationMocksWithFingerPrint:kSavedFingerprint_HostedDomain]; + + GIDAuthStateMigration *migration = + [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; + GTMAuthSession *authorization = + [migration extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath]; + + XCTAssertNotNil(authorization); } #pragma mark - Helpers @@ -180,12 +207,12 @@ - (NSString *)additionalTokenRequestParametersKeyFromFingerprint:(NSString *)fin return [NSString stringWithFormat:@"%@%@", fingerprint, kAdditionalTokenRequestParametersPostfix]; } -// The parameterized extractAuthorization test. -- (void)extractAuthorizationWithFingerprint:(NSString *)fingerprint { +- (void)setUpCommonExtractAuthorizationMocksWithFingerPrint:(NSString *)fingerprint { [[[_mockGIDAuthStateMigration expect] andReturn:fingerprint] passwordForService:kFingerprintService]; -// [[[_mockGTMKeychain expect] andReturn:kGTMOAuth2PersistenceString] -// passwordFromKeychainForName:fingerprint];j + (void)[[[_mockKeychainHelper expect] andReturn:kGTMOAuth2PersistenceString] + passwordForService:fingerprint error:OCMArg.anyObjectRef]; + [[[_mockGTMKeychainStore expect] andReturn:_mockKeychainHelper] keychainHelper]; [[[_mockNSBundle expect] andReturn:_mockNSBundle] mainBundle]; [[[_mockNSBundle expect] andReturn:kBundleID] bundleIdentifier]; [[[_mockGIDSignInCallbackSchemes expect] andReturn:_mockGIDSignInCallbackSchemes] alloc]; @@ -194,18 +221,6 @@ - (void)extractAuthorizationWithFingerprint:(NSString *)fingerprint { [[[_mockGIDSignInCallbackSchemes expect] andReturn:kDotReversedClientID] clientIdentifierScheme]; [[[_mockGIDAuthStateMigration expect] andReturn:kAdditionalTokenRequestParameters] passwordForService:[self additionalTokenRequestParametersKeyFromFingerprint:fingerprint]]; - // [[[_mockGTMOAuth2KeychainCompatibility expect] andReturn:_mockGTMAppAuthFetcherAuthorization] -// authorizeFromPersistenceString:kFinalPersistenceString -// tokenURL:[NSURL URLWithString:kTokenURL] -// redirectURI:kRedirectURI -// clientID:kClientID -// clientSecret:nil]; - - GTMAuthSession *authorization = - [GIDAuthStateMigration extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] - callbackPath:kCallbackPath]; - - XCTAssertNotNil(authorization); } @end diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 8e1f1730..01cb4a6f 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -63,8 +63,8 @@ #import #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST -#import -#import +#import +#import #import #import #endif @@ -190,9 +190,12 @@ @interface GIDSignInTest : XCTestCase { // Mock |OIDTokenRequest|. id _tokenRequest; - // Mock |GTMAppAuthFetcherAuthorization|. + // Mock |GTMAuthSession|. id _authorization; + // Mock |GTMKeychainStore|. + id _keychainStore; + #if TARGET_OS_IOS || TARGET_OS_MACCATALYST // Mock |UIViewController|. id _presentingViewController; @@ -290,22 +293,21 @@ - (void)setUp { _tokenResponse = OCMStrictClassMock([OIDTokenResponse class]); _tokenRequest = OCMStrictClassMock([OIDTokenRequest class]); _authorization = OCMStrictClassMock([GTMAuthSession class]); -// OCMStub([_authorization authorizationFromKeychainForName:OCMOCK_ANY -// useDataProtectionKeychain:YES]).andReturn(_authorization); + _keychainStore = OCMStrictClassMock([GTMKeychainStore class]); + OCMStub([_keychainStore retrieveAuthSessionWithItemName:OCMOCK_ANY + error:nil]).andReturn(_authorization); OCMStub([_authorization alloc]).andReturn(_authorization); OCMStub([_authorization initWithAuthState:OCMOCK_ANY]).andReturn(_authorization); -// OCMStub([_authorization saveAuthorization:OCMOCK_ANY -// toKeychainForName:OCMOCK_ANY -// useDataProtectionKeychain:YES]) -// .andDo(^(NSInvocation *invocation) { -// self->_keychainSaved = self->_saveAuthorizationReturnValue; -// [invocation setReturnValue:&self->_saveAuthorizationReturnValue]; -// }); -// OCMStub([_authorization removeAuthorizationFromKeychainForName:OCMOCK_ANY -// useDataProtectionKeychain:YES]) -// .andDo(^(NSInvocation *invocation) { -// self->_keychainRemoved = YES; -// }); + OCMStub([_authorization saveAuthSession:OCMOCK_ANY + withItemName:OCMOCK_ANY + error:nil]).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + [invocation setReturnValue:&self->_saveAuthorizationReturnValue]; + }); + OCMStub([_keychainStore removeAuthSessionWithItemName:OCMOCK_ANY + error:nil]).andDo(^(NSInvocation *invocation) { + self->_keychainRemoved = YES; + }); _user = OCMStrictClassMock([GIDGoogleUser class]); _oidAuthorizationService = OCMStrictClassMock([OIDAuthorizationService class]); OCMStub([_oidAuthorizationService @@ -786,8 +788,8 @@ - (void)testSignOut { XCTAssertNil(_signIn.currentUser, @"should not have a current user"); XCTAssertTrue(_keychainRemoved, @"should remove keychain"); -// OCMVerify([_authorization removeAuthorizationFromKeychainForName:kKeychainName -// useDataProtectionKeychain:YES]); + OCMVerify([_keychainStore removeAuthSessionWithItemName:kKeychainName + error:nil]); } - (void)testNotHandleWrongScheme { @@ -1477,13 +1479,13 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow XCTAssertFalse(_keychainRemoved, @"should not remove keychain"); XCTAssertFalse(_keychainSaved, @"should not save to keychain again"); -// if (restoredSignIn) { -// OCMVerify([_authorization authorizationFromKeychainForName:kKeychainName -// useDataProtectionKeychain:YES]); -// OCMVerify([_authorization saveAuthorization:OCMOCK_ANY -// toKeychainForName:kKeychainName -// useDataProtectionKeychain:YES]); -// } + if (restoredSignIn) { + // Ignore the return value + OCMVerify((void)[_keychainStore retrieveAuthSessionWithItemName:kKeychainName error:nil]); + OCMVerify([_keychainStore saveAuthSession:OCMOCK_ANY + withItemName:kKeychainName + error:nil]); + } } @end From 4e2ee95a329d3862176fd3c0c82d96afa2a76bff Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 22 Mar 2023 17:44:18 -0700 Subject: [PATCH 09/38] Fix most of GIDSignInTests --- GoogleSignIn/Sources/GIDSignIn.m | 12 +++- GoogleSignIn/Sources/GIDSignIn_Private.h | 4 ++ GoogleSignIn/Tests/Unit/GIDSignInTest.m | 87 +++++++++++++----------- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index e8016895..0e6f2de8 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -451,7 +451,7 @@ + (GIDSignIn *)sharedInstance { #pragma mark - Private methods -- (id)initPrivate { +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { self = [super init]; if (self) { // Get the bundle of the current executable. @@ -461,7 +461,7 @@ - (id)initPrivate { if (bundle) { _configuration = [GIDSignIn configurationFromBundle:bundle]; } - + // Check to see if the 3P app is being run for the first time after a fresh install. BOOL isFreshInstall = [self isFreshInstall]; @@ -477,7 +477,7 @@ - (id)initPrivate { _appAuthConfiguration = [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:[NSURL URLWithString:authorizationEnpointURL] tokenEndpoint:[NSURL URLWithString:tokenEndpointURL]]; - _keychainStore = [[GTMKeychainStore alloc] initWithItemName:kGTMAppAuthKeychainName]; + _keychainStore = keychainStore; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST // Perform migration of auth state from old (before 5.0) versions of the SDK if needed. @@ -492,6 +492,12 @@ - (id)initPrivate { return self; } +- (instancetype)initPrivate { + GTMKeychainStore *keychainStore = + [[GTMKeychainStore alloc] initWithItemName:kGTMAppAuthKeychainName]; + return [self initWithKeychainStore:keychainStore]; +} + // Does sanity check for parameters and then authenticates if necessary. - (void)signInWithOptions:(GIDSignInInternalOptions *)options { // Options for continuation are not the options we want to cache. The purpose of caching the diff --git a/GoogleSignIn/Sources/GIDSignIn_Private.h b/GoogleSignIn/Sources/GIDSignIn_Private.h index 98dd0aae..2fb71ae4 100644 --- a/GoogleSignIn/Sources/GIDSignIn_Private.h +++ b/GoogleSignIn/Sources/GIDSignIn_Private.h @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @class GIDGoogleUser; @class GIDSignInInternalOptions; +@class GTMKeychainStore; /// Represents a completion block that takes a `GIDSignInResult` on success or an error if the /// operation was unsuccessful. @@ -46,6 +47,9 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error); /// Private initializer for |GIDSignIn|. - (instancetype)initPrivate; +/// Private initializer taking a `GTMKeychainStore` to use during tests. +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore; + /// Authenticates with extra options. - (void)signInWithOptions:(GIDSignInInternalOptions *)options; diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 01cb4a6f..9207d661 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -294,18 +294,21 @@ - (void)setUp { _tokenRequest = OCMStrictClassMock([OIDTokenRequest class]); _authorization = OCMStrictClassMock([GTMAuthSession class]); _keychainStore = OCMStrictClassMock([GTMKeychainStore class]); - OCMStub([_keychainStore retrieveAuthSessionWithItemName:OCMOCK_ANY - error:nil]).andReturn(_authorization); + OCMStub( + [_keychainStore retrieveAuthSessionWithItemName:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andReturn(_authorization); + OCMStub([_keychainStore retrieveAuthSessionWithError:nil]).andReturn(_authorization); OCMStub([_authorization alloc]).andReturn(_authorization); OCMStub([_authorization initWithAuthState:OCMOCK_ANY]).andReturn(_authorization); - OCMStub([_authorization saveAuthSession:OCMOCK_ANY - withItemName:OCMOCK_ANY - error:nil]).andDo(^(NSInvocation *invocation) { + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { self->_keychainSaved = self->_saveAuthorizationReturnValue; [invocation setReturnValue:&self->_saveAuthorizationReturnValue]; }); - OCMStub([_keychainStore removeAuthSessionWithItemName:OCMOCK_ANY - error:nil]).andDo(^(NSInvocation *invocation) { + OCMStub( + [_keychainStore removeAuthSessionWithError:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { self->_keychainRemoved = YES; }); _user = OCMStrictClassMock([GIDGoogleUser class]); @@ -332,7 +335,7 @@ - (void)setUp { [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAppHasRunBeforeKey]; - _signIn = [[GIDSignIn alloc] initPrivate]; + _signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore]; _hint = nil; __weak GIDSignInTest *weakSelf = self; @@ -416,7 +419,7 @@ - (void)testInitPrivate_invalidConfig { - (void)testRestorePreviousSignInNoRefresh_hasPreviousUser { [[[_authorization stub] andReturn:_authState] authState]; -// [[_authorization expect] setTokenRefreshDelegate:OCMOCK_ANY]; + [[_authorization expect] setDelegate:OCMOCK_ANY]; OCMStub([_authState lastTokenResponse]).andReturn(_tokenResponse); OCMStub([_authState refreshToken]).andReturn(kRefreshToken); [[_authState expect] setStateChangeDelegate:OCMOCK_ANY]; @@ -788,8 +791,7 @@ - (void)testSignOut { XCTAssertNil(_signIn.currentUser, @"should not have a current user"); XCTAssertTrue(_keychainRemoved, @"should remove keychain"); - OCMVerify([_keychainStore removeAuthSessionWithItemName:kKeychainName - error:nil]); + OCMVerify([_keychainStore removeAuthSessionWithError:OCMArg.anyObjectRef]); } - (void)testNotHandleWrongScheme { @@ -813,14 +815,16 @@ - (void)testDisconnect_accessToken { [[[_authState expect] andReturn:_tokenResponse] lastTokenResponse]; [[[_tokenResponse expect] andReturn:kAccessToken] accessToken]; [[[_authorization expect] andReturn:_fetcherService] fetcherService]; - XCTestExpectation *expectation = + XCTestExpectation *accessTokenExpectation = [self expectationWithDescription:@"Callback called with nil error"]; [_signIn disconnectWithCompletion:^(NSError * _Nullable error) { if (error == nil) { - [expectation fulfill]; + [accessTokenExpectation fulfill]; } }]; - [self verifyAndRevokeToken:kAccessToken hasCallback:YES]; + [self verifyAndRevokeToken:kAccessToken + hasCallback:YES + waitingForExpectations:@[accessTokenExpectation]]; [_authorization verify]; [_authState verify]; [_tokenResponse verify]; @@ -833,7 +837,7 @@ - (void)testDisconnectNoCallback_accessToken { [[[_tokenResponse expect] andReturn:kAccessToken] accessToken]; [[[_authorization expect] andReturn:_fetcherService] fetcherService]; [_signIn disconnectWithCompletion:nil]; - [self verifyAndRevokeToken:kAccessToken hasCallback:NO]; + [self verifyAndRevokeToken:kAccessToken hasCallback:NO waitingForExpectations:@[]]; [_authorization verify]; [_authState verify]; [_tokenResponse verify]; @@ -847,14 +851,16 @@ - (void)testDisconnect_refreshToken { [[[_authState expect] andReturn:_tokenResponse] lastTokenResponse]; [[[_tokenResponse expect] andReturn:kRefreshToken] refreshToken]; [[[_authorization expect] andReturn:_fetcherService] fetcherService]; - XCTestExpectation *expectation = + XCTestExpectation *refreshTokenExpectation = [self expectationWithDescription:@"Callback called with nil error"]; [_signIn disconnectWithCompletion:^(NSError * _Nullable error) { if (error == nil) { - [expectation fulfill]; + [refreshTokenExpectation fulfill]; } }]; - [self verifyAndRevokeToken:kRefreshToken hasCallback:YES]; + [self verifyAndRevokeToken:kRefreshToken + hasCallback:YES + waitingForExpectations:@[refreshTokenExpectation]]; [_authorization verify]; [_authState verify]; [_tokenResponse verify]; @@ -866,18 +872,18 @@ - (void)testDisconnect_errors { [[[_authState expect] andReturn:_tokenResponse] lastTokenResponse]; [[[_tokenResponse expect] andReturn:kAccessToken] accessToken]; [[[_authorization expect] andReturn:_fetcherService] fetcherService]; - XCTestExpectation *expectation = + XCTestExpectation *errorExpectation = [self expectationWithDescription:@"Callback called with an error"]; [_signIn disconnectWithCompletion:^(NSError * _Nullable error) { if (error != nil) { - [expectation fulfill]; + [errorExpectation fulfill]; } }]; XCTAssertTrue([self isFetcherStarted], @"should start fetching"); // Emulate result back from server. NSError *error = [self error]; [self didFetch:nil error:error]; - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self waitForExpectations:@[errorExpectation] timeout:1]; [_authorization verify]; [_authState verify]; [_tokenResponse verify]; @@ -907,14 +913,14 @@ - (void)testDisconnect_noTokens { [[[_tokenResponse expect] andReturn:nil] accessToken]; [[[_authState expect] andReturn:_tokenResponse] lastTokenResponse]; [[[_tokenResponse expect] andReturn:nil] refreshToken]; - XCTestExpectation *expectation = + XCTestExpectation *noTokensExpectation = [self expectationWithDescription:@"Callback called with nil error"]; [_signIn disconnectWithCompletion:^(NSError * _Nullable error) { if (error == nil) { - [expectation fulfill]; + [noTokensExpectation fulfill]; } }]; - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self waitForExpectations:@[noTokensExpectation] timeout:1]; XCTAssertFalse([self isFetcherStarted], @"should not fetch"); XCTAssertTrue(_keychainRemoved, @"keychain should be removed"); [_authorization verify]; @@ -1183,7 +1189,9 @@ - (NSError *)error { } // Verifies a fetcher has started for revoking token and emulates a server response. -- (void)verifyAndRevokeToken:(NSString *)token hasCallback:(BOOL)hasCallback { +- (void)verifyAndRevokeToken:(NSString *)token + hasCallback:(BOOL)hasCallback + waitingForExpectations:(NSArray *)expectations { XCTAssertTrue([self isFetcherStarted], @"should start fetching"); NSURL *url = [self fetchedURL]; XCTAssertEqualObjects([url scheme], @"https", @"scheme must match"); @@ -1199,10 +1207,10 @@ - (void)verifyAndRevokeToken:(NSString *)token hasCallback:(BOOL)hasCallback { @"Environment logging parameter should match"); // Emulate result back from server. [self didFetch:nil error:nil]; + XCTAssertTrue(_keychainRemoved, @"should clear saved keychain name"); if (hasCallback) { - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self waitForExpectations:expectations timeout:1]; } - XCTAssertTrue(_keychainRemoved, @"should clear saved keychain name"); } - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow @@ -1283,10 +1291,11 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow tokenRefreshRequestWithAdditionalParameters:[OCMArg any]]; } } else { - XCTestExpectation *expectation = [self expectationWithDescription:@"Callback called"]; + XCTestExpectation *newAccessTokenExpectation = + [self expectationWithDescription:@"Callback called"]; GIDSignInCompletion completion = ^(GIDSignInResult *_Nullable signInResult, NSError * _Nullable error) { - [expectation fulfill]; + [newAccessTokenExpectation fulfill]; if (signInResult) { XCTAssertEqualObjects(signInResult.serverAuthCode, kServerAuthCode); } else { @@ -1369,10 +1378,11 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow } if (restoredSignIn && oldAccessToken) { - XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called"]; + XCTestExpectation *callbackShouldBeCalledExpectation = + [self expectationWithDescription:@"Callback should be called"]; [_signIn restorePreviousSignInWithCompletion:^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) { - [expectation fulfill]; + [callbackShouldBeCalledExpectation fulfill]; XCTAssertNil(error, @"should have no error"); }]; } @@ -1425,10 +1435,10 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow } if (restoredSignIn && !oldAccessToken) { - XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called"]; + XCTestExpectation *restoredSignInExpectation = [self expectationWithDescription:@"Callback should be called"]; [_signIn restorePreviousSignInWithCompletion:^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) { - [expectation fulfill]; + [restoredSignInExpectation fulfill]; XCTAssertNil(error, @"should have no error"); }]; } else { @@ -1465,11 +1475,12 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow __block GIDGoogleUserCompletion completion; [[_user expect] refreshTokensIfNeededWithCompletion:SAVE_TO_ARG_BLOCK(completion)]; - XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called"]; + XCTestExpectation *restorePreviousSignInExpectation = + [self expectationWithDescription:@"Callback should be called"]; [_signIn restorePreviousSignInWithCompletion:^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) { - [expectation fulfill]; + [restorePreviousSignInExpectation fulfill]; XCTAssertNil(error, @"should have no error"); }]; @@ -1481,10 +1492,8 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow if (restoredSignIn) { // Ignore the return value - OCMVerify((void)[_keychainStore retrieveAuthSessionWithItemName:kKeychainName error:nil]); - OCMVerify([_keychainStore saveAuthSession:OCMOCK_ANY - withItemName:kKeychainName - error:nil]); + OCMVerify((void)[_keychainStore retrieveAuthSessionWithError:OCMArg.anyObjectRef]); + OCMVerify([_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef]); } } From b9d9b8f2d24534490b430485c5841566bdbbfdef Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Fri, 24 Mar 2023 15:52:31 -0700 Subject: [PATCH 10/38] Fix GIDSignInTest Stub GTMKeychainStore saveAuthSession method to sometimes succeed and sometimes fill in an error. --- GoogleSignIn/Sources/GIDSignIn.m | 5 +- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 83 ++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 0e6f2de8..afec5398 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -992,8 +992,9 @@ - (void)removeAllKeychainEntries { - (BOOL)saveAuthState:(OIDAuthState *)authState { GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; - [_keychainStore saveAuthSession:authorization error:nil]; - return YES; + NSError *error; + [_keychainStore saveAuthSession:authorization error:&error]; + return error == nil; } - (OIDAuthState *)loadAuthState { diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 9207d661..ac184f7a 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -300,12 +300,6 @@ - (void)setUp { OCMStub([_keychainStore retrieveAuthSessionWithError:nil]).andReturn(_authorization); OCMStub([_authorization alloc]).andReturn(_authorization); OCMStub([_authorization initWithAuthState:OCMOCK_ANY]).andReturn(_authorization); - OCMStub( - [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] - ).andDo(^(NSInvocation *invocation) { - self->_keychainSaved = self->_saveAuthorizationReturnValue; - [invocation setReturnValue:&self->_saveAuthorizationReturnValue]; - }); OCMStub( [_keychainStore removeAuthSessionWithError:OCMArg.anyObjectRef] ).andDo(^(NSInvocation *invocation) { @@ -542,6 +536,12 @@ - (void)testRestorePreviousSignInWhenCompletionIsNil { } - (void)testOAuthLogin { + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -553,6 +553,12 @@ - (void)testOAuthLogin { } - (void)testOAuthLogin_RestoredSignIn { + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -564,6 +570,12 @@ - (void)testOAuthLogin_RestoredSignIn { } - (void)testOAuthLogin_RestoredSignInOldAccessToken { + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -576,7 +588,13 @@ - (void)testOAuthLogin_RestoredSignInOldAccessToken { - (void)testOAuthLogin_AdditionalScopes { NSString *expectedScopeString; - + + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -622,6 +640,11 @@ - (void)testOAuthLogin_AdditionalScopes { - (void)testAddScopes { // Restore the previous sign-in account. This is the preparation for adding scopes. + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -682,6 +705,12 @@ - (void)testOpenIDRealm { hostedDomain:nil openIDRealm:kOpenIDRealm]; + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -698,6 +727,12 @@ - (void)testOpenIDRealm { - (void)testOAuthLogin_LoginHint { _hint = kUserEmail; + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -717,6 +752,12 @@ - (void)testOAuthLogin_HostedDomain { hostedDomain:kHostedDomain openIDRealm:nil]; + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -759,6 +800,16 @@ - (void)testOAuthLogin_ModalCanceled { } - (void)testOAuthLogin_KeychainError { + // This error is going be overidden by `-[GIDSignIn errorWithString:code:]` + // We just need to fill in the error so that happens. + NSError *keychainError = [NSError errorWithDomain:@"com.googleSignIn.throwAway" + code:1 + userInfo:nil]; + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:[OCMArg setTo:keychainError]] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -775,6 +826,12 @@ - (void)testOAuthLogin_KeychainError { } - (void)testSignOut { + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + // Sign in a user so that we can then sign them out. [self OAuthLoginWithAddScopesFlow:NO authError:nil @@ -1016,6 +1073,12 @@ - (void)testRequiringPendingSignIn { #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - (void)testEmmSupportRequestParameters { + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil @@ -1061,6 +1124,12 @@ - (void)testEmmSupportRequestParameters { } - (void)testEmmPasscodeInfo { + OCMStub( + [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] + ).andDo(^(NSInvocation *invocation) { + self->_keychainSaved = self->_saveAuthorizationReturnValue; + }); + [self OAuthLoginWithAddScopesFlow:NO authError:nil tokenError:nil From 96c8c3b0c88898f6281d97727c00022647cb86b4 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Mon, 27 Mar 2023 19:22:05 -0700 Subject: [PATCH 11/38] Some cocoapods import fixes --- GoogleSignIn/Sources/GIDGoogleUser.m | 3 ++- GoogleSignIn/Sources/GIDGoogleUser_Private.h | 2 +- GoogleSignIn/Sources/GIDSignIn.m | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index dd9ce01f..0969ac12 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -31,7 +31,8 @@ @import GTMAppAuth; #else #import -#import +#import +#import #endif NS_ASSUME_NONNULL_BEGIN diff --git a/GoogleSignIn/Sources/GIDGoogleUser_Private.h b/GoogleSignIn/Sources/GIDGoogleUser_Private.h index a46ab9b6..74aa4f2f 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser_Private.h +++ b/GoogleSignIn/Sources/GIDGoogleUser_Private.h @@ -21,10 +21,10 @@ @import GTMAppAuth; #else #import -#import #endif @class OIDAuthState; +@protocol GTMAuthSessionDelegate; NS_ASSUME_NONNULL_BEGIN diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index afec5398..4b99f774 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -53,8 +53,8 @@ #import #import #import -#import -#import +#import +#import #import #if TARGET_OS_IOS || TARGET_OS_MACCATALYST From 55aeb46db8ced02e64dffcb65c5e705ef5668ff4 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Mon, 27 Mar 2023 19:28:11 -0700 Subject: [PATCH 12/38] Do not forward declare protocol conformance --- GoogleSignIn/Sources/GIDGoogleUser.m | 1 - GoogleSignIn/Sources/GIDGoogleUser_Private.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 0969ac12..c75eacf5 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -32,7 +32,6 @@ #else #import #import -#import #endif NS_ASSUME_NONNULL_BEGIN diff --git a/GoogleSignIn/Sources/GIDGoogleUser_Private.h b/GoogleSignIn/Sources/GIDGoogleUser_Private.h index 74aa4f2f..29f2c1ff 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser_Private.h +++ b/GoogleSignIn/Sources/GIDGoogleUser_Private.h @@ -21,10 +21,10 @@ @import GTMAppAuth; #else #import +#import #endif @class OIDAuthState; -@protocol GTMAuthSessionDelegate; NS_ASSUME_NONNULL_BEGIN From 614111fc22019a9c2863f5b8c660ef208c31fe68 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Tue, 11 Apr 2023 09:44:42 -0700 Subject: [PATCH 13/38] Bump dependencies for AppAuth-iOS and GTMAppAuth --- GoogleSignIn.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GoogleSignIn.podspec b/GoogleSignIn.podspec index b82e5dcc..635d8346 100644 --- a/GoogleSignIn.podspec +++ b/GoogleSignIn.podspec @@ -32,8 +32,8 @@ The Google Sign-In SDK allows users to sign in with their Google account from th ] s.ios.framework = 'UIKit' s.osx.framework = 'AppKit' - s.dependency 'AppAuth', '~> 1.5' - s.dependency 'GTMAppAuth', '>= 1.3', '< 3.0' + s.dependency 'AppAuth', '~> 1.6' + s.dependency 'GTMAppAuth', '~> 3.0.0' s.dependency 'GTMSessionFetcher/Core', '>= 1.1', '< 4.0' s.resource_bundle = { 'GoogleSignIn' => ['GoogleSignIn/Sources/{Resources,Strings}/*'] From c024c5284b2d17917613422d5fa5d9c71f30a621 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Tue, 11 Apr 2023 17:28:50 -0700 Subject: [PATCH 14/38] Update sample apps --- GoogleSignIn/Sources/GIDAuthStateMigration.m | 5 ++--- GoogleSignIn/Sources/GIDEMMSupport.h | 6 ++---- GoogleSignIn/Sources/GIDEMMSupport.m | 4 ++++ GoogleSignIn/Sources/GIDGoogleUser.m | 8 ++++++-- GoogleSignIn/Sources/GIDGoogleUser_Private.h | 8 ++++---- GoogleSignIn/Sources/GIDSignIn.m | 5 ++--- .../Tests/Unit/GIDAuthStateMigrationTest.m | 7 ++++--- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 1 + GoogleSignIn/Tests/Unit/GIDFakeFetcher.m | 3 ++- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 3 ++- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 15 ++++++++------- Package.swift | 4 ++-- Samples/ObjC/SignInSample/Podfile | 1 + .../SignInSampleForPod.xcodeproj/project.pbxproj | 14 ++++++++------ Samples/Swift/DaysUntilBirthday/Podfile | 2 ++ 15 files changed, 50 insertions(+), 36 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index cea30b34..79652a38 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -16,13 +16,12 @@ #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" +@import GTMAppAuth; + #ifdef SWIFT_PACKAGE @import AppAuth; -@import GTMAppAuth; #else #import -#import -#import #endif NS_ASSUME_NONNULL_BEGIN diff --git a/GoogleSignIn/Sources/GIDEMMSupport.h b/GoogleSignIn/Sources/GIDEMMSupport.h index 27a1d950..0d704264 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.h +++ b/GoogleSignIn/Sources/GIDEMMSupport.h @@ -20,17 +20,15 @@ #import -#ifdef SWIFT_PACKAGE @import GTMAppAuth; -#else -#import -#endif NS_ASSUME_NONNULL_BEGIN /// A class to support EMM (Enterprise Mobility Management). @interface GIDEMMSupport : NSObject +- (instancetype)init NS_DESIGNATED_INITIALIZER; + + (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error; /// Handles potential EMM error from token fetch response. diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index ef82d258..8b71f112 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -65,6 +65,10 @@ @implementation GIDEMMSupport +- (instancetype)init { + return [super init]; +} + + (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error { NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey]; ErrorCode errorCode = ErrorCodeNone; diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index c75eacf5..ba307355 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -26,12 +26,12 @@ #import "GoogleSignIn/Sources/GIDSignInPreferences.h" #import "GoogleSignIn/Sources/GIDToken_Private.h" +@import GTMAppAuth; + #ifdef SWIFT_PACKAGE @import AppAuth; -@import GTMAppAuth; #else #import -#import #endif NS_ASSUME_NONNULL_BEGIN @@ -53,11 +53,13 @@ // Minimal time interval before expiration for the access token or it needs to be refreshed. static NSTimeInterval const kMinimalTimeToExpire = 60.0; +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST @interface GIDGoogleUser () @property (nonatomic, strong) id authSessionDelegate; @end +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST @implementation GIDGoogleUser { GIDConfiguration *_cachedConfiguration; @@ -236,8 +238,10 @@ - (instancetype)initWithAuthState:(OIDAuthState *)authState _profile = profileData; GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST self.authSessionDelegate = [[GIDEMMSupport alloc] init]; authorization.delegate = self.authSessionDelegate; +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST authorization.authState.stateChangeDelegate = self; self.fetcherAuthorizer = authorization; diff --git a/GoogleSignIn/Sources/GIDGoogleUser_Private.h b/GoogleSignIn/Sources/GIDGoogleUser_Private.h index 29f2c1ff..d5c7f045 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser_Private.h +++ b/GoogleSignIn/Sources/GIDGoogleUser_Private.h @@ -16,12 +16,12 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h" +@import GTMAppAuth; + #ifdef SWIFT_PACKAGE @import AppAuth; -@import GTMAppAuth; #else #import -#import #endif @class OIDAuthState; @@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN /// A completion block that takes a `GIDGoogleUser` or an error if the attempt to refresh tokens was unsuccessful. typedef void (^GIDGoogleUserCompletion)(GIDGoogleUser *_Nullable user, NSError *_Nullable error); -// Internal methods for the class that are not part of the public API. +/// Internal methods for the class that are not part of the public API. @interface GIDGoogleUser () @property(nonatomic, readwrite) GIDToken *accessToken; @@ -40,7 +40,7 @@ typedef void (^GIDGoogleUserCompletion)(GIDGoogleUser *_Nullable user, NSError * @property(nonatomic, readwrite, nullable) GIDToken *idToken; -// A representation of the state of the OAuth session for this instance. +/// A representation of the state of the OAuth session for this instance. @property(nonatomic, readonly) OIDAuthState *authState; #pragma clang diagnostic push diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 4b99f774..4b942ed9 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -36,9 +36,10 @@ #import "GoogleSignIn/Sources/GIDProfileData_Private.h" #import "GoogleSignIn/Sources/GIDSignInResult_Private.h" +@import GTMAppAuth; + #ifdef SWIFT_PACKAGE @import AppAuth; -@import GTMAppAuth; @import GTMSessionFetcherCore; #else #import @@ -53,8 +54,6 @@ #import #import #import -#import -#import #import #if TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m index a9d382b7..0b9dd01f 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m @@ -17,15 +17,16 @@ #import "GoogleSignIn/Sources/GIDAuthStateMigration.h" #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" +@import GTMAppAuth; #ifdef SWIFT_PACKAGE @import AppAuth; @import GTMAppAuth; @import OCMock; #else #import -#import -#import -#import +//#import +//#import +//#import #import #endif diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index 54e5791f..207a41aa 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -22,6 +22,7 @@ #import "GoogleSignIn/Sources/GIDEMMSupport.h" +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h" #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m index c1488f53..d409c1ff 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +@import GTMAppAuth; #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" #ifdef SWIFT_PACKAGE @import GTMAppAuth; #else -#import +//#import #endif typedef void (^FetchCompletionHandler)(NSData *, NSError *); diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 0c316735..5ad8bd1e 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -30,6 +30,7 @@ #import "GoogleSignIn/Tests/Unit/OIDTokenRequest+Testing.h" #import "GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.h" +@import GTMAppAuth; #ifdef SWIFT_PACKAGE @import AppAuth; @import GoogleUtilities_MethodSwizzler; @@ -47,7 +48,7 @@ #import #import #import -#import +//#import #import #endif diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index ac184f7a..c252c532 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -26,6 +26,8 @@ // Test module imports @import GoogleSignIn; +@import GTMAppAuth; + #import "GoogleSignIn/Sources/GIDEMMSupport.h" #import "GoogleSignIn/Sources/GIDGoogleUser_Private.h" #import "GoogleSignIn/Sources/GIDSignIn_Private.h" @@ -43,7 +45,6 @@ #ifdef SWIFT_PACKAGE @import AppAuth; -@import GTMAppAuth; @import GTMSessionFetcherCore; @import OCMock; #else @@ -63,8 +64,6 @@ #import #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST -#import -#import #import #import #endif @@ -413,7 +412,9 @@ - (void)testInitPrivate_invalidConfig { - (void)testRestorePreviousSignInNoRefresh_hasPreviousUser { [[[_authorization stub] andReturn:_authState] authState]; +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST [[_authorization expect] setDelegate:OCMOCK_ANY]; +#endif // TARGET_OS_IOS || !TARGET_OS_MACCATALYST OCMStub([_authState lastTokenResponse]).andReturn(_tokenResponse); OCMStub([_authState refreshToken]).andReturn(kRefreshToken); [[_authState expect] setStateChangeDelegate:OCMOCK_ANY]; @@ -437,10 +438,6 @@ - (void)testRestorePreviousSignInNoRefresh_hasPreviousUser { [_signIn restorePreviousSignInNoRefresh]; - [_authorization verify]; - [_authState verify]; - [_tokenResponse verify]; - [_tokenRequest verify]; [idTokenDecoded verify]; XCTAssertEqual(_signIn.currentUser.userID, kFakeGaiaID); @@ -826,6 +823,10 @@ - (void)testOAuthLogin_KeychainError { } - (void)testSignOut { +#if TARGET_OS_IOS || !TARGET_OS_MACCATALYST +// OCMStub([_authorization authState]).andReturn(_authState); +#endif // TARGET_OS_IOS || !TARGET_OS_MACCATALYST + OCMStub([_authorization fetcherService]).andReturn(_fetcherService); OCMStub( [_keychainStore saveAuthSession:OCMOCK_ANY error:OCMArg.anyObjectRef] ).andDo(^(NSInvocation *invocation) { diff --git a/Package.swift b/Package.swift index 047336bf..21434a00 100644 --- a/Package.swift +++ b/Package.swift @@ -44,11 +44,11 @@ let package = Package( .package( name: "AppAuth", url: "https://github.com/openid/AppAuth-iOS.git", - "1.5.0" ..< "2.0.0"), + "1.6.0" ..< "2.0.0"), .package( name: "GTMAppAuth", url: "https://github.com/google/GTMAppAuth.git", - .branch("mdmathias/no-longer-open")), + from: "3.0.0"), .package( name: "GTMSessionFetcher", url: "https://github.com/google/gtm-session-fetcher.git", diff --git a/Samples/ObjC/SignInSample/Podfile b/Samples/ObjC/SignInSample/Podfile index c7df6fc7..003fefe1 100644 --- a/Samples/ObjC/SignInSample/Podfile +++ b/Samples/ObjC/SignInSample/Podfile @@ -1,4 +1,5 @@ platform :ios, '10.0' +use_frameworks! target 'SampleForPod' do pod 'GoogleSignIn', :path => '../../../', :testspecs => ['unit'] diff --git a/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj b/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj index 154116db..543d030f 100644 --- a/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj +++ b/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - CC887BA946C6A9FDA3DE81B5 /* Pods_SampleForPod.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 550F5407FA6F32CFDE2C3C75 /* Pods_SampleForPod.framework */; }; + 1D721EFBF29E4B5D3EA5BE4D /* Pods_SampleForPod.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2675052AF6D7076DCBF751BB /* Pods_SampleForPod.framework */; }; D926A5701BC3236100ADECE6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A5381BC3236100ADECE6 /* AppDelegate.m */; }; D926A5711BC3236100ADECE6 /* AuthInspectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A53A1BC3236100ADECE6 /* AuthInspectorViewController.m */; }; D926A5721BC3236100ADECE6 /* DataPickerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A53C1BC3236100ADECE6 /* DataPickerState.m */; }; @@ -24,7 +24,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 550F5407FA6F32CFDE2C3C75 /* Pods_SampleForPod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleForPod.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2675052AF6D7076DCBF751BB /* Pods_SampleForPod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleForPod.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1B5D38B282AFE460068D12B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; D926A51D1BC31FE000ADECE6 /* SignInSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SignInSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; D926A5371BC3236100ADECE6 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Source/AppDelegate.h; sourceTree = SOURCE_ROOT; }; @@ -90,7 +90,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CC887BA946C6A9FDA3DE81B5 /* Pods_SampleForPod.framework in Frameworks */, + 1D721EFBF29E4B5D3EA5BE4D /* Pods_SampleForPod.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -109,7 +109,7 @@ BB0E907DD016FB9CB6DC01B5 /* Frameworks */ = { isa = PBXGroup; children = ( - 550F5407FA6F32CFDE2C3C75 /* Pods_SampleForPod.framework */, + 2675052AF6D7076DCBF751BB /* Pods_SampleForPod.framework */, ); name = Frameworks; sourceTree = ""; @@ -178,7 +178,7 @@ D926A5191BC31FE000ADECE6 /* Sources */, D926A51A1BC31FE000ADECE6 /* Frameworks */, D926A51B1BC31FE000ADECE6 /* Resources */, - 819CCDEFD018D376E185A11E /* [CP] Embed Pods Frameworks */, + CA434359EF3A93E8F17342C4 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -296,7 +296,7 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 819CCDEFD018D376E185A11E /* [CP] Embed Pods Frameworks */ = { + CA434359EF3A93E8F17342C4 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -496,6 +496,7 @@ baseConfigurationReference = FE1798D23522F57E24875676 /* Pods-SampleForPod.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -509,6 +510,7 @@ baseConfigurationReference = DAD21F7A41C90200270A7376 /* Pods-SampleForPod.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; diff --git a/Samples/Swift/DaysUntilBirthday/Podfile b/Samples/Swift/DaysUntilBirthday/Podfile index 373455a8..a466e9bc 100644 --- a/Samples/Swift/DaysUntilBirthday/Podfile +++ b/Samples/Swift/DaysUntilBirthday/Podfile @@ -2,6 +2,8 @@ pod 'GoogleSignIn', :path => '../../../', :testspecs => ['unit'] pod 'GoogleSignInSwiftSupport', :path => '../../../', :testspecs => ['unit'] project 'DaysUntilBirthdayForPod.xcodeproj' +use_modular_headers! + target 'DaysUntilBirthdayForPod (iOS)' do platform :ios, '14.0' end From 4febcdb6c9c0d0625df473ac78f5fda46191e280 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 12 Apr 2023 09:19:25 -0700 Subject: [PATCH 15/38] Use frameworks with static linkage in Swift sample --- .../project.pbxproj | 16 ++++++++-------- Samples/Swift/DaysUntilBirthday/Podfile | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Samples/Swift/DaysUntilBirthday/DaysUntilBirthdayForPod.xcodeproj/project.pbxproj b/Samples/Swift/DaysUntilBirthday/DaysUntilBirthdayForPod.xcodeproj/project.pbxproj index 8f76c9ff..87f26e0c 100644 --- a/Samples/Swift/DaysUntilBirthday/DaysUntilBirthdayForPod.xcodeproj/project.pbxproj +++ b/Samples/Swift/DaysUntilBirthday/DaysUntilBirthdayForPod.xcodeproj/project.pbxproj @@ -7,8 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 5965643074F45661539BC2DF /* libPods-DaysUntilBirthdayForPod (iOS).a in Frameworks */ = {isa = PBXBuildFile; fileRef = F163BB5E1E81280A79B4E535 /* libPods-DaysUntilBirthdayForPod (iOS).a */; }; - 7023CA98EF5DD94278069A12 /* libPods-DaysUntilBirthdayForPod (macOS).a in Frameworks */ = {isa = PBXBuildFile; fileRef = AE0FE424C7B3C57CF8808F8A /* libPods-DaysUntilBirthdayForPod (macOS).a */; }; + 4C6A2BA2321434ACBD2AF201 /* Pods_DaysUntilBirthdayForPod__macOS_.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 926A15D393D684C68E09FB0F /* Pods_DaysUntilBirthdayForPod__macOS_.framework */; }; 7345AD032703D9470020AFB1 /* DaysUntilBirthday.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7345AD022703D9470020AFB1 /* DaysUntilBirthday.swift */; }; 7345AD052703D9470020AFB1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7345AD042703D9470020AFB1 /* ContentView.swift */; }; 7345AD072703D9480020AFB1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7345AD062703D9480020AFB1 /* Assets.xcassets */; }; @@ -37,6 +36,7 @@ 73DB41952805FC5F0028B8D3 /* Birthday.swift in Sources */ = {isa = PBXBuildFile; fileRef = 739FCC47270E659A00C92042 /* Birthday.swift */; }; 73DB419628060A9A0028B8D3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7345AD062703D9480020AFB1 /* Assets.xcassets */; }; C1B5D38D282AFE870068D12B /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = C1B5D38C282AFE870068D12B /* README.md */; }; + EEEEE201864437604E97D3B4 /* Pods_DaysUntilBirthdayForPod__iOS_.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F329EC9CE4A0A4AF2280834F /* Pods_DaysUntilBirthdayForPod__iOS_.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -62,10 +62,10 @@ 739FCC45270E467600C92042 /* BirthdayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BirthdayView.swift; sourceTree = ""; }; 739FCC47270E659A00C92042 /* Birthday.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Birthday.swift; sourceTree = ""; }; 7542DB53C46DFA9B71387188 /* Pods-DaysUntilBirthdayForPod (iOS).release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DaysUntilBirthdayForPod (iOS).release.xcconfig"; path = "Target Support Files/Pods-DaysUntilBirthdayForPod (iOS)/Pods-DaysUntilBirthdayForPod (iOS).release.xcconfig"; sourceTree = ""; }; - AE0FE424C7B3C57CF8808F8A /* libPods-DaysUntilBirthdayForPod (macOS).a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-DaysUntilBirthdayForPod (macOS).a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 926A15D393D684C68E09FB0F /* Pods_DaysUntilBirthdayForPod__macOS_.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DaysUntilBirthdayForPod__macOS_.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B7CC09BA1B68EB1881A08E87 /* Pods-DaysUntilBirthdayForPod(macOS).debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DaysUntilBirthdayForPod(macOS).debug.xcconfig"; path = "Target Support Files/Pods-DaysUntilBirthdayForPod(macOS)/Pods-DaysUntilBirthdayForPod(macOS).debug.xcconfig"; sourceTree = ""; }; C1B5D38C282AFE870068D12B /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - F163BB5E1E81280A79B4E535 /* libPods-DaysUntilBirthdayForPod (iOS).a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-DaysUntilBirthdayForPod (iOS).a"; sourceTree = BUILT_PRODUCTS_DIR; }; + F329EC9CE4A0A4AF2280834F /* Pods_DaysUntilBirthdayForPod__iOS_.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DaysUntilBirthdayForPod__iOS_.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F84E43064819F374C9789E49 /* Pods-DaysUntilBirthdayForPod (macOS).debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DaysUntilBirthdayForPod (macOS).debug.xcconfig"; path = "Target Support Files/Pods-DaysUntilBirthdayForPod (macOS)/Pods-DaysUntilBirthdayForPod (macOS).debug.xcconfig"; sourceTree = ""; }; FE2F2ABC2800D9C1005EA17F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; FE71738027ECFAF400910319 /* DaysUntilBirthdayForPod (macOS).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DaysUntilBirthdayForPod (macOS).app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -79,7 +79,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5965643074F45661539BC2DF /* libPods-DaysUntilBirthdayForPod (iOS).a in Frameworks */, + EEEEE201864437604E97D3B4 /* Pods_DaysUntilBirthdayForPod__iOS_.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -87,7 +87,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7023CA98EF5DD94278069A12 /* libPods-DaysUntilBirthdayForPod (macOS).a in Frameworks */, + 4C6A2BA2321434ACBD2AF201 /* Pods_DaysUntilBirthdayForPod__macOS_.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -174,8 +174,8 @@ FE71738F27ECFB3300910319 /* Frameworks */ = { isa = PBXGroup; children = ( - F163BB5E1E81280A79B4E535 /* libPods-DaysUntilBirthdayForPod (iOS).a */, - AE0FE424C7B3C57CF8808F8A /* libPods-DaysUntilBirthdayForPod (macOS).a */, + F329EC9CE4A0A4AF2280834F /* Pods_DaysUntilBirthdayForPod__iOS_.framework */, + 926A15D393D684C68E09FB0F /* Pods_DaysUntilBirthdayForPod__macOS_.framework */, ); name = Frameworks; sourceTree = ""; diff --git a/Samples/Swift/DaysUntilBirthday/Podfile b/Samples/Swift/DaysUntilBirthday/Podfile index a466e9bc..f746be79 100644 --- a/Samples/Swift/DaysUntilBirthday/Podfile +++ b/Samples/Swift/DaysUntilBirthday/Podfile @@ -2,7 +2,7 @@ pod 'GoogleSignIn', :path => '../../../', :testspecs => ['unit'] pod 'GoogleSignInSwiftSupport', :path => '../../../', :testspecs => ['unit'] project 'DaysUntilBirthdayForPod.xcodeproj' -use_modular_headers! +use_frameworks! :linkage => :static target 'DaysUntilBirthdayForPod (iOS)' do platform :ios, '14.0' From 52cef300ef005d8cb8eed8293dcf49b484764dfa Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 12 Apr 2023 09:55:52 -0700 Subject: [PATCH 16/38] Remove use_libraries and use_static_frameworks flags from pod lib lint --- .github/workflows/unit_tests.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 221650b3..882a726a 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -16,11 +16,6 @@ jobs: matrix: os: [macos-12] podspec: [GoogleSignIn.podspec, GoogleSignInSwiftSupport.podspec] - flag: [ - "", - "--use-libraries", - "--use-static-frameworks" - ] include: - podspec: GoogleSignInSwiftSupport.podspec includePodspecFlag: "--include-podspecs='GoogleSignIn.podspec'" @@ -33,7 +28,7 @@ jobs: - name: Lint podspec using local source run: | pod lib lint ${{ matrix.podspec }} --verbose \ - ${{ matrix.includePodspecFlag }} ${{ matrix.flag }} + ${{ matrix.includePodspecFlag }} spm-build-test: runs-on: ${{ matrix.os }} From e113cdb38f73b46996221ea25dbd61ffc78682d9 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 12 Apr 2023 10:59:17 -0700 Subject: [PATCH 17/38] Add swift version --- GoogleSignIn.podspec | 1 + GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/GoogleSignIn.podspec b/GoogleSignIn.podspec index 635d8346..d1e133b3 100644 --- a/GoogleSignIn.podspec +++ b/GoogleSignIn.podspec @@ -12,6 +12,7 @@ The Google Sign-In SDK allows users to sign in with their Google account from th :git => 'https://github.com/google/GoogleSignIn-iOS.git', :tag => s.version.to_s } + s.swift_version = '4.0' ios_deployment_target = '10.0' osx_deployment_target = '10.15' s.ios.deployment_target = ios_deployment_target diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h index f09d1894..382c310d 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h @@ -23,8 +23,11 @@ // A fake |GTMHTTPFetcherService| for testing. @interface GIDFakeFetcherService : NSObject +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" /// Creates an instance of this fake with an authorizer. - initWithAuthorizer:(id)authorizer; +#pragma clang diagnostic pop /// Returns the list of |GPPFakeFetcher| objects that have been created. - (NSArray *)fetchers; From a8aa402090672f70370f385ca94847345ab4dbff Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 12 Apr 2023 13:32:17 -0700 Subject: [PATCH 18/38] Clean up imports Also add an empty Swift file for CocoaPods in SignInSample --- GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m | 5 +---- GoogleSignIn/Tests/Unit/GIDFakeFetcher.m | 5 ----- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 1 + .../SignInSampleForPod.xcodeproj/project.pbxproj | 10 ++++++++++ Samples/ObjC/SignInSample/Source/Empty.swift | 9 +++++++++ 5 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 Samples/ObjC/SignInSample/Source/Empty.swift diff --git a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m index 0b9dd01f..5aa387a8 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m @@ -18,15 +18,12 @@ #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" @import GTMAppAuth; + #ifdef SWIFT_PACKAGE @import AppAuth; -@import GTMAppAuth; @import OCMock; #else #import -//#import -//#import -//#import #import #endif diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m index d409c1ff..e4328f35 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m @@ -14,11 +14,6 @@ @import GTMAppAuth; #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" -#ifdef SWIFT_PACKAGE -@import GTMAppAuth; -#else -//#import -#endif typedef void (^FetchCompletionHandler)(NSData *, NSError *); diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 5ad8bd1e..295f1071 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -31,6 +31,7 @@ #import "GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.h" @import GTMAppAuth; + #ifdef SWIFT_PACKAGE @import AppAuth; @import GoogleUtilities_MethodSwizzler; diff --git a/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj b/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj index 543d030f..417d1c30 100644 --- a/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj +++ b/Samples/ObjC/SignInSample/SignInSampleForPod.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 1D721EFBF29E4B5D3EA5BE4D /* Pods_SampleForPod.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2675052AF6D7076DCBF751BB /* Pods_SampleForPod.framework */; }; + 7314214E29E7348800D35433 /* Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7314214D29E7348800D35433 /* Empty.swift */; }; D926A5701BC3236100ADECE6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A5381BC3236100ADECE6 /* AppDelegate.m */; }; D926A5711BC3236100ADECE6 /* AuthInspectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A53A1BC3236100ADECE6 /* AuthInspectorViewController.m */; }; D926A5721BC3236100ADECE6 /* DataPickerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A53C1BC3236100ADECE6 /* DataPickerState.m */; }; @@ -25,6 +26,7 @@ /* Begin PBXFileReference section */ 2675052AF6D7076DCBF751BB /* Pods_SampleForPod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleForPod.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7314214D29E7348800D35433 /* Empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Empty.swift; sourceTree = ""; }; C1B5D38B282AFE460068D12B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; D926A51D1BC31FE000ADECE6 /* SignInSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SignInSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; D926A5371BC3236100ADECE6 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Source/AppDelegate.h; sourceTree = SOURCE_ROOT; }; @@ -130,6 +132,7 @@ D926A56D1BC3236100ADECE6 /* SignInViewController.h */, D926A56E1BC3236100ADECE6 /* SignInViewController.m */, D926A56F1BC3236100ADECE6 /* SignInViewController.xib */, + 7314214D29E7348800D35433 /* Empty.swift */, ); path = Source; sourceTree = ""; @@ -200,6 +203,7 @@ TargetAttributes = { D926A51C1BC31FE000ADECE6 = { CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 1420; }; }; }; @@ -332,6 +336,7 @@ D926A5721BC3236100ADECE6 /* DataPickerState.m in Sources */, D926A5711BC3236100ADECE6 /* AuthInspectorViewController.m in Sources */, D926A57D1BC3236100ADECE6 /* SignInViewController.m in Sources */, + 7314214E29E7348800D35433 /* Empty.swift in Sources */, D926A5701BC3236100ADECE6 /* AppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -496,12 +501,15 @@ baseConfigurationReference = FE1798D23522F57E24875676 /* Pods-SampleForPod.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.google.SignInSample; PRODUCT_NAME = SignInSample; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -510,12 +518,14 @@ baseConfigurationReference = DAD21F7A41C90200270A7376 /* Pods-SampleForPod.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.google.SignInSample; PRODUCT_NAME = SignInSample; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Samples/ObjC/SignInSample/Source/Empty.swift b/Samples/ObjC/SignInSample/Source/Empty.swift new file mode 100644 index 00000000..702b9ee7 --- /dev/null +++ b/Samples/ObjC/SignInSample/Source/Empty.swift @@ -0,0 +1,9 @@ +// +// Empty.swift +// SampleForPod +// +// Created by Matt Mathias on 4/12/23. +// Copyright © 2023 Google Inc. All rights reserved. +// + +import Foundation From d4df1fce4f147c91c35d074e2e2287e444b46846 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 12 Apr 2023 17:13:53 -0700 Subject: [PATCH 19/38] Fix typos and alignment issues from PR feedback --- GoogleSignIn/Sources/GIDAuthStateMigration.m | 2 +- GoogleSignIn/Sources/GIDEMMSupport.h | 2 -- GoogleSignIn/Sources/GIDEMMSupport.m | 6 ++--- GoogleSignIn/Sources/GIDGoogleUser.m | 6 ++--- GoogleSignIn/Sources/GIDGoogleUser_Private.h | 4 +-- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 1 - .../Tests/Unit/GIDFailingOIDAuthState.m | 8 +++--- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 1 - Samples/ObjC/SignInSample/Source/Empty.swift | 25 +++++++++++++------ 9 files changed, 30 insertions(+), 25 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index 79652a38..63ebe2cd 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -49,7 +49,7 @@ @implementation GIDAuthStateMigration - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { self = [super init]; if (self) { - self.keychainStore = keychainStore; + _keychainStore = keychainStore; } return self; } diff --git a/GoogleSignIn/Sources/GIDEMMSupport.h b/GoogleSignIn/Sources/GIDEMMSupport.h index 0d704264..f57a6af7 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.h +++ b/GoogleSignIn/Sources/GIDEMMSupport.h @@ -29,8 +29,6 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_DESIGNATED_INITIALIZER; -+ (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error; - /// Handles potential EMM error from token fetch response. + (void)handleTokenFetchEMMError:(nullable NSError *)error completion:(void (^)(NSError *_Nullable))completion; diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index 8b71f112..66a1def3 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -56,12 +56,12 @@ static NSString *const kErrorPayloadSeparator = @":"; // A list for recognized error codes. -typedef enum { +NS_ENUM(NSInteger, ErrorCode) { ErrorCodeNone = 0, ErrorCodeDeviceNotCompliant, ErrorCodeScreenlockRequired, ErrorCodeAppVerificationRequired, -} ErrorCode; +}; @implementation GIDEMMSupport @@ -71,7 +71,7 @@ - (instancetype)init { + (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error { NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey]; - ErrorCode errorCode = ErrorCodeNone; + enum ErrorCode errorCode = ErrorCodeNone; if (errorJSON) { id errorValue = errorJSON[kErrorKey]; diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index ba307355..77cc7f94 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -188,7 +188,7 @@ - (void)refreshTokensIfNeededWithCompletion:(GIDGoogleUserCompletion)completion }]; } -- (OIDAuthState *) authState { +- (OIDAuthState *)authState { return ((GTMAuthSession *)self.fetcherAuthorizer).authState; } @@ -239,11 +239,11 @@ - (instancetype)initWithAuthState:(OIDAuthState *)authState GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - self.authSessionDelegate = [[GIDEMMSupport alloc] init]; + _authSessionDelegate = [[GIDEMMSupport alloc] init]; authorization.delegate = self.authSessionDelegate; #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST authorization.authState.stateChangeDelegate = self; - self.fetcherAuthorizer = authorization; + _fetcherAuthorizer = authorization; [self updateTokensWithAuthState:authState]; } diff --git a/GoogleSignIn/Sources/GIDGoogleUser_Private.h b/GoogleSignIn/Sources/GIDGoogleUser_Private.h index d5c7f045..f07a1045 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser_Private.h +++ b/GoogleSignIn/Sources/GIDGoogleUser_Private.h @@ -16,8 +16,6 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h" -@import GTMAppAuth; - #ifdef SWIFT_PACKAGE @import AppAuth; #else @@ -32,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN typedef void (^GIDGoogleUserCompletion)(GIDGoogleUser *_Nullable user, NSError *_Nullable error); /// Internal methods for the class that are not part of the public API. -@interface GIDGoogleUser () +@interface GIDGoogleUser () @property(nonatomic, readwrite) GIDToken *accessToken; diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index 207a41aa..7a54ab24 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -66,7 +66,6 @@ @implementation GIDEMMSupportTest - (void)testEMMSupportDelegate { XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; - GIDEMMSupport *emmSupport = [[GIDEMMSupport alloc] init]; GIDFailingOIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; GTMAuthSession *authSession = [[GTMAuthSession alloc] initWithAuthState:authState]; diff --git a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m index ae2e7847..fa5267bf 100644 --- a/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m +++ b/GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.m @@ -22,9 +22,11 @@ @implementation GIDFailingOIDAuthState + (instancetype)testInstance { - return [[GIDFailingOIDAuthState alloc] - initWithAuthorizationResponse:[OIDAuthorizationResponse testInstance] - tokenResponse:[OIDTokenResponse testInstance]]; + OIDAuthorizationResponse *testAuthResponse = [OIDAuthorizationResponse testInstance]; + OIDTokenResponse *testTokenResponse = [OIDTokenResponse testInstance]; + + return [[GIDFailingOIDAuthState alloc] initWithAuthorizationResponse:testAuthResponse + tokenResponse:testTokenResponse]; } - (void)performActionWithFreshTokens:(OIDAuthStateAction)action diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 295f1071..f987c7c1 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -49,7 +49,6 @@ #import #import #import -//#import #import #endif diff --git a/Samples/ObjC/SignInSample/Source/Empty.swift b/Samples/ObjC/SignInSample/Source/Empty.swift index 702b9ee7..8aa2a7a7 100644 --- a/Samples/ObjC/SignInSample/Source/Empty.swift +++ b/Samples/ObjC/SignInSample/Source/Empty.swift @@ -1,9 +1,18 @@ -// -// Empty.swift -// SampleForPod -// -// Created by Matt Mathias on 4/12/23. -// Copyright © 2023 Google Inc. All rights reserved. -// +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import Foundation + +// This is necessary for `SignInSample`'s `Podfile` to use `use_frameworks! :linkage => :static` From c04dc0cb82ceefa61b6746845ed1a6209f73ecc4 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 12 Apr 2023 19:12:50 -0700 Subject: [PATCH 20/38] Set require app host to true in GoogleSignInSwiftSupport podspec --- GoogleSignInSwiftSupport.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GoogleSignInSwiftSupport.podspec b/GoogleSignInSwiftSupport.podspec index d0b1e0c3..75fa4866 100644 --- a/GoogleSignInSwiftSupport.podspec +++ b/GoogleSignInSwiftSupport.podspec @@ -33,6 +33,6 @@ Pod::Spec.new do |s| unit_tests.source_files = [ 'GoogleSignInSwift/Tests/Unit/*.swift', ] - unit_tests.requires_app_host = false + unit_tests.requires_app_host = true end end From 434ec5a2e6fe73afa3a0f12b57e245d3b5c883d6 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 12 Apr 2023 19:57:26 -0700 Subject: [PATCH 21/38] Update EMM support test to be more clear --- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 12 ++++-------- GoogleSignIn/Tests/Unit/GIDTestWorker.h | 9 ++------- GoogleSignIn/Tests/Unit/GIDTestWorker.m | 8 ++------ 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index 7a54ab24..eb30fb14 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -22,7 +22,7 @@ #import "GoogleSignIn/Sources/GIDEMMSupport.h" -#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h" +#import "GoogleSignIn/Sources/GIDGoogleUser_Private.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h" #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" @@ -66,19 +66,15 @@ @implementation GIDEMMSupportTest - (void)testEMMSupportDelegate { XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; - GIDEMMSupport *emmSupport = [[GIDEMMSupport alloc] init]; GIDFailingOIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; - GTMAuthSession *authSession = [[GTMAuthSession alloc] initWithAuthState:authState]; - authSession.delegate = emmSupport; + GIDGoogleUser *user = [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; GIDFakeFetcherService *fakeFetcherService = [[GIDFakeFetcherService alloc] - initWithAuthorizer:authSession]; + initWithAuthorizer:user.fetcherAuthorizer]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@""]]; GTMSessionFetcher *fakeFetcher = [fakeFetcherService fetcherWithRequest:request]; - GIDGoogleUser *user = [[GIDGoogleUser alloc] init]; - GIDTestWorker *testWorker = [[GIDTestWorker alloc] initWithGoogleUser:user - fetcher:fakeFetcher]; + GIDTestWorker *testWorker = [[GIDTestWorker alloc] initWithFetcher:fakeFetcher]; [testWorker failWorkWithCompletion:^(NSError * _Nullable error) { XCTAssertNotNil(error); diff --git a/GoogleSignIn/Tests/Unit/GIDTestWorker.h b/GoogleSignIn/Tests/Unit/GIDTestWorker.h index 5713947e..24cf3d77 100644 --- a/GoogleSignIn/Tests/Unit/GIDTestWorker.h +++ b/GoogleSignIn/Tests/Unit/GIDTestWorker.h @@ -16,7 +16,6 @@ #import -@class GIDGoogleUser; @class GTMSessionFetcher; NS_ASSUME_NONNULL_BEGIN @@ -24,12 +23,8 @@ NS_ASSUME_NONNULL_BEGIN /// Class used in testing EMM error handling in `GIDEMMSupportTest`. @interface GIDTestWorker : NSObject -/// Creates an instance with a Google user. -/// -/// Ensure that the `GIDGoogleUser` has some way to return an `authorizer` of time `GTMAuthSession` -/// with its delegate set to `GIDEMMSupport`. -- (instancetype)initWithGoogleUser:(nonnull GIDGoogleUser *)googleUser - fetcher:(nonnull GTMSessionFetcher *)fetcher; +/// Creates a fake "worker" instance with a `GTMSessionFetcher`. +- (instancetype)initWithFetcher:(nonnull GTMSessionFetcher *)fetcher; /// Fails the work encapsulated by this type with the given error. - (void)failWorkWithCompletion:(void (^)(NSError *_Nullable error))completion; diff --git a/GoogleSignIn/Tests/Unit/GIDTestWorker.m b/GoogleSignIn/Tests/Unit/GIDTestWorker.m index 1d33fd05..30e94b98 100644 --- a/GoogleSignIn/Tests/Unit/GIDTestWorker.m +++ b/GoogleSignIn/Tests/Unit/GIDTestWorker.m @@ -15,25 +15,21 @@ */ #import "GIDTestWorker.h" -#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h" #import #import "GoogleSignIn/Sources/GIDEMMSupport.h" @interface GIDTestWorker () -@property(nonatomic, strong) GIDGoogleUser *googleUser; @property(nonatomic, strong) GTMSessionFetcher *fetcher; @end @implementation GIDTestWorker -- (instancetype)initWithGoogleUser:(nonnull GIDGoogleUser *)googleUser - fetcher:(nonnull GTMSessionFetcher *)fetcher { +- (instancetype)initWithFetcher:(nonnull GTMSessionFetcher *)fetcher { self = [super init]; if (self) { - self.googleUser = googleUser; - self.fetcher = fetcher; + _fetcher = fetcher; } return self; } From 61daac5611a80a9f55273fcd961f078db2562e0a Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 13 Apr 2023 13:02:42 -0700 Subject: [PATCH 22/38] Remove unused init override in GIDAuthStateMigration --- GoogleSignIn/Sources/GIDAuthStateMigration.h | 6 ------ GoogleSignIn/Sources/GIDAuthStateMigration.m | 5 ----- 2 files changed, 11 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration.h index f5a1fe1d..44b26e4f 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.h +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.h @@ -24,12 +24,6 @@ NS_ASSUME_NONNULL_BEGIN /// A class providing migration support for auth state saved by older versions of the SDK. @interface GIDAuthStateMigration : NSObject -/// Creates an instance of this migration type. -/// -/// - Note: Uses `"auth"` as the keychain item name for the `GTMKeychainStore`, which is created -/// within the initializer. -- (instancetype)init; - /// Creates an instance of this migration type with the keychain storage wrapper it will use. - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore NS_DESIGNATED_INITIALIZER; diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index 63ebe2cd..37c1ffb7 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -54,11 +54,6 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { return self; } -- (instancetype)init { - GTMKeychainStore *keychainStore = [[GTMKeychainStore alloc] initWithItemName:@"auth"]; - return [self initWithKeychainStore:keychainStore]; -} - - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath keychainName:(NSString *)keychainName From 23bbea2dfef1c3f126a2baf8431942fa0425d4de Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 13 Apr 2023 13:06:02 -0700 Subject: [PATCH 23/38] Add back init in GIDAuthStateMigration.m to remove warning Xcode was warning that GIDAuthStateMigration did not override the designated initializer of the superclass. --- GoogleSignIn/Sources/GIDAuthStateMigration.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index 37c1ffb7..63ebe2cd 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -54,6 +54,11 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { return self; } +- (instancetype)init { + GTMKeychainStore *keychainStore = [[GTMKeychainStore alloc] initWithItemName:@"auth"]; + return [self initWithKeychainStore:keychainStore]; +} + - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath keychainName:(NSString *)keychainName From 10677aed1cde68886b277b50886f6bab85479046 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 13 Apr 2023 13:19:09 -0700 Subject: [PATCH 24/38] Move extractAuthorizationWithTokenURL from GIDAuthStateMigration.h to test case category --- GoogleSignIn/Sources/GIDAuthStateMigration.h | 4 ---- GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m | 7 +++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration.h index 44b26e4f..329be59f 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.h +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.h @@ -34,10 +34,6 @@ NS_ASSUME_NONNULL_BEGIN keychainName:(NSString *)keychainName isFreshInstall:(BOOL)isFreshInstall; -/// Returns a `GTMAuthSession` given the provided token URL. -- (nullable GTMAuthSession *) - extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath; - @end NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m index 5aa387a8..4866d01d 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m @@ -61,6 +61,13 @@ @interface GIDAuthStateMigration () + (nullable NSString *)passwordForService:(NSString *)service; +/// Returns a `GTMAuthSession` given the provided token URL. +/// +/// This method enables using an instance of `GIDAuthStateMigration` that is created with a fake +/// `GTMKeychainStore` and thereby minimizes mocking. +- (nullable GTMAuthSession *) + extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath; + @end @interface GIDAuthStateMigrationTest : XCTestCase From 74f01ee29e9fb8c01f9484e220bdbda182771f4a Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 13 Apr 2023 13:20:20 -0700 Subject: [PATCH 25/38] Add typedef to NS_ENUM --- GoogleSignIn/Sources/GIDEMMSupport.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index 66a1def3..7a742745 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -56,7 +56,7 @@ static NSString *const kErrorPayloadSeparator = @":"; // A list for recognized error codes. -NS_ENUM(NSInteger, ErrorCode) { +typedef NS_ENUM(NSInteger, ErrorCode) { ErrorCodeNone = 0, ErrorCodeDeviceNotCompliant, ErrorCodeScreenlockRequired, @@ -71,7 +71,7 @@ - (instancetype)init { + (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error { NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey]; - enum ErrorCode errorCode = ErrorCodeNone; + ErrorCode errorCode = ErrorCodeNone; if (errorJSON) { id errorValue = errorJSON[kErrorKey]; From bbe15574142d813c87d2385d7c891c9f989945d8 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 13 Apr 2023 15:17:52 -0700 Subject: [PATCH 26/38] Fix version numbers for deps in podspec and package --- .github/workflows/unit_tests.yml | 6 +++++- GoogleSignIn.podspec | 2 +- Package.swift | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 882a726a..d2ec3f52 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -16,6 +16,10 @@ jobs: matrix: os: [macos-12] podspec: [GoogleSignIn.podspec, GoogleSignInSwiftSupport.podspec] + flag: [ + "", + "--use-static-frameworks" + ] include: - podspec: GoogleSignInSwiftSupport.podspec includePodspecFlag: "--include-podspecs='GoogleSignIn.podspec'" @@ -28,7 +32,7 @@ jobs: - name: Lint podspec using local source run: | pod lib lint ${{ matrix.podspec }} --verbose \ - ${{ matrix.includePodspecFlag }} + ${{ matrix.includePodspecFlag }} ${{ matrix.flag }} spm-build-test: runs-on: ${{ matrix.os }} diff --git a/GoogleSignIn.podspec b/GoogleSignIn.podspec index d1e133b3..d26dd399 100644 --- a/GoogleSignIn.podspec +++ b/GoogleSignIn.podspec @@ -34,7 +34,7 @@ The Google Sign-In SDK allows users to sign in with their Google account from th s.ios.framework = 'UIKit' s.osx.framework = 'AppKit' s.dependency 'AppAuth', '~> 1.6' - s.dependency 'GTMAppAuth', '~> 3.0.0' + s.dependency 'GTMAppAuth', '~> 3.0' s.dependency 'GTMSessionFetcher/Core', '>= 1.1', '< 4.0' s.resource_bundle = { 'GoogleSignIn' => ['GoogleSignIn/Sources/{Resources,Strings}/*'] diff --git a/Package.swift b/Package.swift index 21434a00..024f296f 100644 --- a/Package.swift +++ b/Package.swift @@ -48,7 +48,7 @@ let package = Package( .package( name: "GTMAppAuth", url: "https://github.com/google/GTMAppAuth.git", - from: "3.0.0"), + "3.0.0" ..< "4.0.0"), .package( name: "GTMSessionFetcher", url: "https://github.com/google/gtm-session-fetcher.git", From 26d8f576a0636179e499ceedcf3c04360283b5f3 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 20 Apr 2023 11:22:43 -0700 Subject: [PATCH 27/38] Remove reference to fake fetcher error property --- GoogleSignIn/Tests/Unit/GIDFakeFetcher.m | 7 ------- 1 file changed, 7 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m index e4328f35..80712df0 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeFetcher.m @@ -17,12 +17,6 @@ typedef void (^FetchCompletionHandler)(NSData *, NSError *); -@interface GIDFakeFetcher () - -@property(nonatomic, strong, nullable) NSError *fetcherError; - -@end - @implementation GIDFakeFetcher { FetchCompletionHandler _handler; NSURL *_requestURL; @@ -63,7 +57,6 @@ - (void)beginFetchWithCompletionHandler:(FetchCompletionHandler)handler { - (void)authorizeRequestWithCompletion:(FetchCompletionHandler)completion { NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:self.request.URL]; [self.authorizer authorizeRequest:mutableRequest completionHandler:^(NSError * _Nullable error) { - self.fetcherError = error; completion(nil, error); }]; } From 61a08bd5af6206d51a23e29ea36b81788c6d7296 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 20 Apr 2023 11:44:07 -0700 Subject: [PATCH 28/38] Remove GIDTestWorker --- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 7 +--- GoogleSignIn/Tests/Unit/GIDTestWorker.h | 34 ---------------- GoogleSignIn/Tests/Unit/GIDTestWorker.m | 44 --------------------- 3 files changed, 2 insertions(+), 83 deletions(-) delete mode 100644 GoogleSignIn/Tests/Unit/GIDTestWorker.h delete mode 100644 GoogleSignIn/Tests/Unit/GIDTestWorker.m diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index eb30fb14..627cac16 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -31,7 +31,6 @@ #import "GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h" -#import "GoogleSignIn/Tests/Unit/GIDTestWorker.h" #ifdef SWIFT_PACKAGE @import AppAuth; @@ -72,11 +71,9 @@ - (void)testEMMSupportDelegate { initWithAuthorizer:user.fetcherAuthorizer]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@""]]; - GTMSessionFetcher *fakeFetcher = [fakeFetcherService fetcherWithRequest:request]; + GTMSessionFetcher *fetcher = [fakeFetcherService fetcherWithRequest:request]; - GIDTestWorker *testWorker = [[GIDTestWorker alloc] initWithFetcher:fakeFetcher]; - - [testWorker failWorkWithCompletion:^(NSError * _Nullable error) { + [fetcher beginFetchWithCompletionHandler:^(NSData * _Nullable data, NSError * _Nullable error) { XCTAssertNotNil(error); NSDictionary *userInfo = @{ @"OIDOAuthErrorResponseErrorKey": @{@"error": @"emm_passcode_required"}, diff --git a/GoogleSignIn/Tests/Unit/GIDTestWorker.h b/GoogleSignIn/Tests/Unit/GIDTestWorker.h deleted file mode 100644 index 24cf3d77..00000000 --- a/GoogleSignIn/Tests/Unit/GIDTestWorker.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@class GTMSessionFetcher; - -NS_ASSUME_NONNULL_BEGIN - -/// Class used in testing EMM error handling in `GIDEMMSupportTest`. -@interface GIDTestWorker : NSObject - -/// Creates a fake "worker" instance with a `GTMSessionFetcher`. -- (instancetype)initWithFetcher:(nonnull GTMSessionFetcher *)fetcher; - -/// Fails the work encapsulated by this type with the given error. -- (void)failWorkWithCompletion:(void (^)(NSError *_Nullable error))completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/GIDTestWorker.m b/GoogleSignIn/Tests/Unit/GIDTestWorker.m deleted file mode 100644 index 30e94b98..00000000 --- a/GoogleSignIn/Tests/Unit/GIDTestWorker.m +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "GIDTestWorker.h" -#import -#import "GoogleSignIn/Sources/GIDEMMSupport.h" - -@interface GIDTestWorker () - -@property(nonatomic, strong) GTMSessionFetcher *fetcher; - -@end - -@implementation GIDTestWorker - -- (instancetype)initWithFetcher:(nonnull GTMSessionFetcher *)fetcher { - self = [super init]; - if (self) { - _fetcher = fetcher; - } - return self; -} - -- (void)failWorkWithCompletion:(void (^)(NSError *_Nullable))completion { - [self.fetcher beginFetchWithCompletionHandler:^(NSData * _Nullable data, - NSError * _Nullable error) { - completion(error); - }]; -} - -@end From a87b9341f23d183b56969973364c35bdfa3a602d Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 20 Apr 2023 11:46:49 -0700 Subject: [PATCH 29/38] Rename authState to failingAuthState in EMM error handling test This updated name makes it more explicit that we expect the fetch to fail and that we want to inspect the error in the completion handler. --- GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index 627cac16..b28755e5 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -65,8 +65,8 @@ @implementation GIDEMMSupportTest - (void)testEMMSupportDelegate { XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; - GIDFailingOIDAuthState *authState = [GIDFailingOIDAuthState testInstance]; - GIDGoogleUser *user = [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; + GIDFailingOIDAuthState *failingAuthState = [GIDFailingOIDAuthState testInstance]; + GIDGoogleUser *user = [[GIDGoogleUser alloc] initWithAuthState:failingAuthState profileData:nil]; GIDFakeFetcherService *fakeFetcherService = [[GIDFakeFetcherService alloc] initWithAuthorizer:user.fetcherAuthorizer]; From 38641b70a35f0f3472285813f20c7bb66949205b Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Thu, 20 Apr 2023 13:26:00 -0700 Subject: [PATCH 30/38] Update GIDEMMSupport to more clearly handle the updated error --- GoogleSignIn/Sources/GIDEMMSupport.m | 46 +++++++++++++--------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index 7a742745..bba232df 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -69,30 +69,6 @@ - (instancetype)init { return [super init]; } -+ (nullable NSError *)handleTokenFetchEMMError:(nullable NSError *)error { - NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey]; - ErrorCode errorCode = ErrorCodeNone; - - if (errorJSON) { - id errorValue = errorJSON[kErrorKey]; - if ([errorValue isEqual:kScreenlockRequiredError]) { - errorCode = ErrorCodeScreenlockRequired; - } else if ([errorValue hasPrefix:kAppVerificationRequiredErrorPrefix]) { - errorCode = ErrorCodeAppVerificationRequired; - } else if ([errorValue hasPrefix:kGeneralErrorPrefix]) { - errorCode = ErrorCodeDeviceNotCompliant; - } - } - - if (errorCode) { - return [NSError errorWithDomain:kGIDSignInErrorDomain - code:kGIDSignInErrorCodeEMM - userInfo:error.userInfo]; - } else { - return error; - } -} - + (void)handleTokenFetchEMMError:(nullable NSError *)error completion:(void (^)(NSError *_Nullable))completion { NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey]; @@ -151,7 +127,27 @@ + (NSDictionary *)parametersWithParameters:(NSDictionary *)parameters - (nullable NSError *)updatedErrorForAuthSession:(GTMAuthSession *)authSession originalError:(NSError *)originalError { - return [GIDEMMSupport handleTokenFetchEMMError:originalError]; + NSDictionary *errorJSON = originalError.userInfo[OIDOAuthErrorResponseErrorKey]; + ErrorCode errorCode = ErrorCodeNone; + + if (errorJSON) { + id errorValue = errorJSON[kErrorKey]; + if ([errorValue isEqual:kScreenlockRequiredError]) { + errorCode = ErrorCodeScreenlockRequired; + } else if ([errorValue hasPrefix:kAppVerificationRequiredErrorPrefix]) { + errorCode = ErrorCodeAppVerificationRequired; + } else if ([errorValue hasPrefix:kGeneralErrorPrefix]) { + errorCode = ErrorCodeDeviceNotCompliant; + } + } + + if (errorCode) { + return [NSError errorWithDomain:kGIDSignInErrorDomain + code:kGIDSignInErrorCodeEMM + userInfo:originalError.userInfo]; + } else { + return originalError; + } } @end From 1a1041d9c9aeb1c21d558edc8f433d246f44618b Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Fri, 28 Apr 2023 16:07:56 -0700 Subject: [PATCH 31/38] Update GIDEMMSupport to use new update error delegate method --- GoogleSignIn/Sources/GIDEMMSupport.m | 29 ++++++---------------------- Package.swift | 3 +-- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index bba232df..b149a577 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -125,29 +125,12 @@ + (NSDictionary *)parametersWithParameters:(NSDictionary *)parameters authSession.authState.lastTokenResponse.additionalParameters]; } -- (nullable NSError *)updatedErrorForAuthSession:(GTMAuthSession *)authSession - originalError:(NSError *)originalError { - NSDictionary *errorJSON = originalError.userInfo[OIDOAuthErrorResponseErrorKey]; - ErrorCode errorCode = ErrorCodeNone; - - if (errorJSON) { - id errorValue = errorJSON[kErrorKey]; - if ([errorValue isEqual:kScreenlockRequiredError]) { - errorCode = ErrorCodeScreenlockRequired; - } else if ([errorValue hasPrefix:kAppVerificationRequiredErrorPrefix]) { - errorCode = ErrorCodeAppVerificationRequired; - } else if ([errorValue hasPrefix:kGeneralErrorPrefix]) { - errorCode = ErrorCodeDeviceNotCompliant; - } - } - - if (errorCode) { - return [NSError errorWithDomain:kGIDSignInErrorDomain - code:kGIDSignInErrorCodeEMM - userInfo:originalError.userInfo]; - } else { - return originalError; - } +- (void)updatedErrorForAuthSession:(GTMAuthSession *)authSession + originalError:(NSError *)originalError + completion:(void (^)(NSError * _Nullable))completion { + [GIDEMMSupport handleTokenFetchEMMError:originalError completion:^(NSError *_Nullable error) { + completion(error); + }]; } @end diff --git a/Package.swift b/Package.swift index 024f296f..81b8ec49 100644 --- a/Package.swift +++ b/Package.swift @@ -46,9 +46,8 @@ let package = Package( url: "https://github.com/openid/AppAuth-iOS.git", "1.6.0" ..< "2.0.0"), .package( - name: "GTMAppAuth", url: "https://github.com/google/GTMAppAuth.git", - "3.0.0" ..< "4.0.0"), + .branch("mdmathias/update-error-completion")), .package( name: "GTMSessionFetcher", url: "https://github.com/google/gtm-session-fetcher.git", From b16fbb86ed64a4e7566cf479b5e48449241a1694 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Fri, 28 Apr 2023 16:16:20 -0700 Subject: [PATCH 32/38] Remove duplicated constants --- GoogleSignIn/Sources/GIDEMMSupport.m | 5 ----- 1 file changed, 5 deletions(-) diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index b149a577..5fc3eca0 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -47,11 +47,6 @@ // The error key in the server response. static NSString *const kErrorKey = @"error"; -// Error strings in the server response. -static NSString *const kGeneralErrorPrefix = @"emm_"; -static NSString *const kScreenlockRequiredError = @"emm_passcode_required"; -static NSString *const kAppVerificationRequiredErrorPrefix = @"emm_app_verification_required"; - // Optional separator between error prefix and the payload. static NSString *const kErrorPayloadSeparator = @":"; From cce884e2c673fd52bf20f819b113cd8e82622371 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 3 May 2023 17:38:58 -0700 Subject: [PATCH 33/38] Use new EMM error handling delegate method name --- GoogleSignIn/Sources/GIDEMMSupport.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GoogleSignIn/Sources/GIDEMMSupport.m b/GoogleSignIn/Sources/GIDEMMSupport.m index 5fc3eca0..0e7b0369 100644 --- a/GoogleSignIn/Sources/GIDEMMSupport.m +++ b/GoogleSignIn/Sources/GIDEMMSupport.m @@ -120,9 +120,9 @@ + (NSDictionary *)parametersWithParameters:(NSDictionary *)parameters authSession.authState.lastTokenResponse.additionalParameters]; } -- (void)updatedErrorForAuthSession:(GTMAuthSession *)authSession - originalError:(NSError *)originalError - completion:(void (^)(NSError * _Nullable))completion { +- (void)updateErrorForAuthSession:(GTMAuthSession *)authSession + originalError:(NSError *)originalError + completion:(void (^)(NSError * _Nullable))completion { [GIDEMMSupport handleTokenFetchEMMError:originalError completion:^(NSError *_Nullable error) { completion(error); }]; From ca7f78fedb0f65322ebdd8b6f424ac90da210807 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Fri, 5 May 2023 15:35:06 -0700 Subject: [PATCH 34/38] Depend upon main GTMAppAuth branch --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 81b8ec49..8d9d4c72 100644 --- a/Package.swift +++ b/Package.swift @@ -47,7 +47,7 @@ let package = Package( "1.6.0" ..< "2.0.0"), .package( url: "https://github.com/google/GTMAppAuth.git", - .branch("mdmathias/update-error-completion")), + .branch("master")), .package( name: "GTMSessionFetcher", url: "https://github.com/google/gtm-session-fetcher.git", From 10b6b60c59a9d6ca20edb96a8b853ae2d64d616e Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Wed, 10 May 2023 12:49:02 -0700 Subject: [PATCH 35/38] Update GIDEMMSupportTest to swizzle a key window and alert controller This change supports CocoaPods using a host application for running tests. --- GoogleSignIn.podspec | 2 +- .../Tests/Unit/GIDEMMErrorHandlerTest.m | 17 +------ GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m | 48 +++++++++++++++++++ .../Tests/Unit/UIAlertAction+Testing.h | 27 +++++++++++ .../Tests/Unit/UIAlertAction+Testing.m | 23 +++++++++ 5 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h create mode 100644 GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m diff --git a/GoogleSignIn.podspec b/GoogleSignIn.podspec index d26dd399..d8407e90 100644 --- a/GoogleSignIn.podspec +++ b/GoogleSignIn.podspec @@ -34,7 +34,7 @@ The Google Sign-In SDK allows users to sign in with their Google account from th s.ios.framework = 'UIKit' s.osx.framework = 'AppKit' s.dependency 'AppAuth', '~> 1.6' - s.dependency 'GTMAppAuth', '~> 3.0' + s.dependency 'GTMAppAuth', '~> 4.0' s.dependency 'GTMSessionFetcher/Core', '>= 1.1', '< 4.0' s.resource_bundle = { 'GoogleSignIn' => ['GoogleSignIn/Sources/{Resources,Strings}/*'] diff --git a/GoogleSignIn/Tests/Unit/GIDEMMErrorHandlerTest.m b/GoogleSignIn/Tests/Unit/GIDEMMErrorHandlerTest.m index 0b3a5685..b51519c6 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMErrorHandlerTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMErrorHandlerTest.m @@ -21,6 +21,7 @@ #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" #import "GoogleSignIn/Sources/GIDSignInStrings.h" +#import "GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h" #ifdef SWIFT_PACKAGE @import GoogleUtilities_MethodSwizzler; @@ -34,22 +35,6 @@ NS_ASSUME_NONNULL_BEGIN -// Addtional methods added to UIAlertAction for testing. -@interface UIAlertAction (Testing) - -// Returns the handler block for this alert action. -- (void (^)(UIAlertAction *))actionHandler; - -@end - -@implementation UIAlertAction (Testing) - -- (void (^)(UIAlertAction *))actionHandler { - return [self valueForKey:@"handler"]; -} - -@end - // Unit test for GIDEMMErrorHandler. @interface GIDEMMErrorHandlerTest : XCTestCase @end diff --git a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m index b28755e5..990aa733 100644 --- a/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m +++ b/GoogleSignIn/Tests/Unit/GIDEMMSupportTest.m @@ -18,6 +18,7 @@ #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST +#import #import #import "GoogleSignIn/Sources/GIDEMMSupport.h" @@ -31,6 +32,7 @@ #import "GoogleSignIn/Tests/Unit/GIDFailingOIDAuthState.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h" +#import "GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h" #ifdef SWIFT_PACKAGE @import AppAuth; @@ -58,11 +60,15 @@ static NSString *const kEMMPasscodeInfoKey = @"emm_passcode_info"; @interface GIDEMMSupportTest : XCTestCase + // The view controller that has been presented, if any. +@property(nonatomic, strong, nullable) UIViewController *presentedViewController; + @end @implementation GIDEMMSupportTest - (void)testEMMSupportDelegate { + [self setupSwizzlers]; XCTestExpectation *emmErrorExpectation = [self expectationWithDescription:@"EMM AppAuth error"]; GIDFailingOIDAuthState *failingAuthState = [GIDFailingOIDAuthState testInstance]; @@ -86,7 +92,27 @@ - (void)testEMMSupportDelegate { [emmErrorExpectation fulfill]; }]; + // Wait for the code under test to be executed on the main thread. + XCTestExpectation *mainThreadExpectation = + [self expectationWithDescription:@"wait for main thread"]; + dispatch_async(dispatch_get_main_queue(), ^() { + [mainThreadExpectation fulfill]; + }); + [self waitForExpectations:@[mainThreadExpectation] timeout:1]; + + XCTAssertTrue([_presentedViewController isKindOfClass:[UIAlertController class]]); + UIAlertController *alert = (UIAlertController *)_presentedViewController; + XCTAssertNotNil(alert.title); + XCTAssertNotNil(alert.message); + XCTAssertEqual(alert.actions.count, 2); + + // Pretend to touch the "Cancel" button. + UIAlertAction *action = alert.actions[0]; + XCTAssertEqualObjects(action.title, @"Cancel"); + action.actionHandler(action); + [self waitForExpectations:@[emmErrorExpectation] timeout:1]; + [self unswizzle]; } - (void)testUpdatedEMMParametersWithParameters_NoEMMKey { @@ -254,6 +280,28 @@ - (NSString *)systemVersion { return [UIDevice currentDevice].systemVersion; } +- (void)setupSwizzlers { + UIWindow *fakeKeyWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + [GULSwizzler swizzleClass:[GIDEMMErrorHandler class] + selector:@selector(keyWindow) + isClassSelector:NO + withBlock:^() { return fakeKeyWindow; }]; + [GULSwizzler swizzleClass:[UIViewController class] + selector:@selector(presentViewController:animated:completion:) + isClassSelector:NO + withBlock:^(id obj, id arg1) { self->_presentedViewController = arg1; }]; +} + +- (void)unswizzle { + [GULSwizzler unswizzleClass:[GIDEMMErrorHandler class] + selector:@selector(keyWindow) + isClassSelector:NO]; + [GULSwizzler unswizzleClass:[UIViewController class] + selector:@selector(presentViewController:animated:completion:) + isClassSelector:NO]; + self.presentedViewController = nil; +} + @end NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h new file mode 100644 index 00000000..6e658413 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h @@ -0,0 +1,27 @@ + +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIAlertAction (Testing) + +/// Returns the handler block for this alert action. +- (void (^)(UIAlertAction *))actionHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m new file mode 100644 index 00000000..af81751d --- /dev/null +++ b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m @@ -0,0 +1,23 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "UIAlertAction+Testing.h" + +@implementation UIAlertAction (Testing) + +- (void (^)(UIAlertAction *))actionHandler { + return [self valueForKey:@"handler"]; +} + +@end From b940af4bc1f4d91973eb91d5079c3786594f1fb4 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Mon, 15 May 2023 17:54:30 -0700 Subject: [PATCH 36/38] Depend upon GTMAppAuth 4.0.0 --- GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h | 7 +++++++ GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m | 6 ++++++ Package.swift | 3 ++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h index 6e658413..18716804 100644 --- a/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h +++ b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.h @@ -13,10 +13,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#import + +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST + #import NS_ASSUME_NONNULL_BEGIN +/// Helper category for testing EMM support @interface UIAlertAction (Testing) /// Returns the handler block for this alert action. @@ -25,3 +30,5 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST diff --git a/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m index af81751d..a6b3df01 100644 --- a/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m +++ b/GoogleSignIn/Tests/Unit/UIAlertAction+Testing.m @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#import + +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST + #import "UIAlertAction+Testing.h" @implementation UIAlertAction (Testing) @@ -21,3 +25,5 @@ @implementation UIAlertAction (Testing) } @end + +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST diff --git a/Package.swift b/Package.swift index 8d9d4c72..8b498cc2 100644 --- a/Package.swift +++ b/Package.swift @@ -46,8 +46,9 @@ let package = Package( url: "https://github.com/openid/AppAuth-iOS.git", "1.6.0" ..< "2.0.0"), .package( + name: "GTMAppAuth", url: "https://github.com/google/GTMAppAuth.git", - .branch("master")), + from: "4.0.0"), .package( name: "GTMSessionFetcher", url: "https://github.com/google/gtm-session-fetcher.git", From 2dab4df47809a589281c9dabacca97ebbd64aa6d Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Mon, 15 May 2023 18:10:25 -0700 Subject: [PATCH 37/38] Stub expected method on keychainStore in GIDSignInTest --- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 1 + 1 file changed, 1 insertion(+) diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index c252c532..59e3ac75 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -510,6 +510,7 @@ - (void)testNotRestorePreviousSignInWhenSignedOutAndCompletionIsNil { - (void)testRestorePreviousSignInWhenCompletionIsNil { [[[_authorization expect] andReturn:_authState] authState]; + [[_keychainStore expect] saveAuthSession:OCMOCK_ANY error:[OCMArg anyObjectRef]]; [[[_authState expect] andReturnValue:[NSNumber numberWithBool:YES]] isAuthorized]; OIDTokenResponse *tokenResponse = From e862376fa2dbdc79b498f8f398e7be9f292e6b71 Mon Sep 17 00:00:00 2001 From: Matthew Mathias Date: Tue, 16 May 2023 11:15:56 -0700 Subject: [PATCH 38/38] Rename authorization -> authSession Also use ivar in GIDGoogleUser init instead of accessing via self. --- GoogleSignIn/Sources/GIDAuthStateMigration.m | 16 ++++++++-------- GoogleSignIn/Sources/GIDGoogleUser.m | 8 ++++---- .../Tests/Unit/GIDAuthStateMigrationTest.m | 13 +++++-------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index 63ebe2cd..f0827f03 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -73,13 +73,13 @@ - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL // action and go on to mark the migration check as having been performed. if (!isFreshInstall) { // Attempt migration - GTMAuthSession *authorization = - [self extractAuthorizationWithTokenURL:tokenURL callbackPath:callbackPath]; + GTMAuthSession *authSession = + [self extractAuthSessionWithTokenURL:tokenURL callbackPath:callbackPath]; // If migration was successful, save our migrated state to the keychain. - if (authorization) { + if (authSession) { NSError *err; - [self.keychainStore saveAuthSession:authorization error:&err]; + [self.keychainStore saveAuthSession:authSession error:&err]; // If we're unable to save to the keychain, return without marking migration performed. if (err) { return; @@ -93,8 +93,8 @@ - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL // Returns a |GTMAuthSession| object containing any old auth state or |nil| if none // was found or the migration failed. -- (nullable GTMAuthSession *) - extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath { +- (nullable GTMAuthSession *)extractAuthSessionWithTokenURL:(NSURL *)tokenURL + callbackPath:(NSString *)callbackPath { // Retrieve the last used fingerprint. NSString *fingerprint = [GIDAuthStateMigration passwordForService:kFingerprintService]; if (!fingerprint) { @@ -149,7 +149,7 @@ - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL // Use |GTMOAuth2Compatibility| to generate a |GTMAuthSession| from the // persistence string, redirect URI, client ID, and token endpoint URL. - GTMAuthSession *authorization = + GTMAuthSession *authSession = [GTMOAuth2Compatibility authSessionForPersistenceString:persistenceString tokenURL:tokenURL redirectURI:redirectURI @@ -157,7 +157,7 @@ - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL clientSecret:nil error:nil]; - return authorization; + return authSession; } // Returns the password string for a given service string stored by an old version of the SDK or diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 77cc7f94..ec300839 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -237,13 +237,13 @@ - (instancetype)initWithAuthState:(OIDAuthState *)authState _tokenRefreshHandlerQueue = [[NSMutableArray alloc] init]; _profile = profileData; - GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState]; + GTMAuthSession *authSession = [[GTMAuthSession alloc] initWithAuthState:authState]; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST _authSessionDelegate = [[GIDEMMSupport alloc] init]; - authorization.delegate = self.authSessionDelegate; + authSession.delegate = _authSessionDelegate; #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST - authorization.authState.stateChangeDelegate = self; - _fetcherAuthorizer = authorization; + authSession.authState.stateChangeDelegate = self; + _fetcherAuthorizer = authSession; [self updateTokensWithAuthState:authState]; } diff --git a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m index 4866d01d..85ff7cca 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m @@ -56,9 +56,6 @@ @interface GIDAuthStateMigration () -+ (nullable GTMAuthSession *) - extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath; - + (nullable NSString *)passwordForService:(NSString *)service; /// Returns a `GTMAuthSession` given the provided token URL. @@ -66,7 +63,7 @@ + (nullable NSString *)passwordForService:(NSString *)service; /// This method enables using an instance of `GIDAuthStateMigration` that is created with a fake /// `GTMKeychainStore` and thereby minimizes mocking. - (nullable GTMAuthSession *) - extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath; + extractAuthSessionWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath; @end @@ -187,8 +184,8 @@ - (void)testExtractAuthorization { GIDAuthStateMigration *migration = [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; GTMAuthSession *authorization = - [migration extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] - callbackPath:kCallbackPath]; + [migration extractAuthSessionWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath]; XCTAssertNotNil(authorization); } @@ -199,8 +196,8 @@ - (void)testExtractAuthorization_HostedDomain { GIDAuthStateMigration *migration = [[GIDAuthStateMigration alloc] initWithKeychainStore:_mockGTMKeychainStore]; GTMAuthSession *authorization = - [migration extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] - callbackPath:kCallbackPath]; + [migration extractAuthSessionWithTokenURL:[NSURL URLWithString:kTokenURL] + callbackPath:kCallbackPath]; XCTAssertNotNil(authorization); }