From 0974883ab56ef8f739c86370847aff0c6c0b4a64 Mon Sep 17 00:00:00 2001 From: Camden King Date: Thu, 5 Jun 2025 14:50:21 -0700 Subject: [PATCH 01/16] create fake --- .../Tests/Unit/GIDFakeAuthStateMigration.h | 22 ++++++++++ .../Tests/Unit/GIDFakeAuthStateMigration.m | 41 +++++++++++++++++++ GoogleSignIn/Tests/Unit/GIDSignInTest.m | 5 +++ 3 files changed, 68 insertions(+) create mode 100644 GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h create mode 100644 GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.m diff --git a/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h b/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h new file mode 100644 index 00000000..709793a0 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h @@ -0,0 +1,22 @@ +/* + * Copyright 2025 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 "GoogleSignIn/Sources/GIDAuthStateMigration.h" + +/// A fake |GIDAuthStateMigration| for testing. +@interface GIDFakeAuthStateMigration : GIDAuthStateMigration + +@end diff --git a/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.m b/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.m new file mode 100644 index 00000000..7bb4dcf3 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.m @@ -0,0 +1,41 @@ +/* + * Copyright 2025 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 "GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h" + + +NS_ASSUME_NONNULL_BEGIN + +@implementation GIDFakeAuthStateMigration + +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { + return [self init]; +} + +- (instancetype)init { + self = [super init]; + return self; +} + +- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL + callbackPath:(NSString *)callbackPath + keychainName:(NSString *)keychainName + isFreshInstall:(BOOL)isFreshInstall { + return; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 7d5195d8..bdb6c378 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -40,6 +40,7 @@ #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST +#import "GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h" #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" @@ -221,6 +222,9 @@ @interface GIDSignInTest : XCTestCase { // Whether callback block has been called. BOOL _completionCalled; + // Fake for GIDAuthStateMigration + GIDFakeAuthStateMigration *_authStateMigrationService; + // Fake fetcher service to emulate network requests. GIDFakeFetcherService *_fetcherService; @@ -331,6 +335,7 @@ - (void)setUp { callback:COPY_TO_ARG_BLOCK(self->_savedTokenCallback)]); // Fakes + _authStateMigrationService = [[GIDFakeAuthStateMigration alloc] init]; _fetcherService = [[GIDFakeFetcherService alloc] init]; _fakeMainBundle = [[GIDFakeMainBundle alloc] init]; [_fakeMainBundle startFakingWithClientID:kClientId]; From e5b86b5873aca0efbcc324441fd5c8d0e7b6d4ff Mon Sep 17 00:00:00 2001 From: Camden King Date: Thu, 5 Jun 2025 14:52:42 -0700 Subject: [PATCH 02/16] Revert "only attempt migrations one time" This reverts commit fd0a5a8226c65e9cfa17cd02ff5534bee0f6fd95. --- GoogleSignIn/Sources/GIDAuthStateMigration.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration.m index cb4cfbe6..3085fa76 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration.m @@ -107,6 +107,10 @@ - (void)performDataProtectedMigrationIfNeeded { if (authSession) { NSError *err; [self.keychainStore saveAuthSession:authSession error:&err]; + // If we're unable to save to the keychain, return without marking migration performed. + if (err) { + return; + }; [keychainStoreLegacy removeAuthSessionWithError:nil]; } @@ -134,6 +138,10 @@ - (void)performGIDMigrationIfNeededWithTokenURL:(NSURL *)tokenURL if (authSession) { NSError *err; [self.keychainStore saveAuthSession:authSession error:&err]; + // If we're unable to save to the keychain, return without marking migration performed. + if (err) { + return; + }; } // Mark the migration check as having been performed. From b5d9e4523ce48ac9565b187a878275057d1dbc97 Mon Sep 17 00:00:00 2001 From: Camden King Date: Fri, 6 Jun 2025 10:38:36 -0700 Subject: [PATCH 03/16] update fake and create test --- .../Fake}/GIDFakeAuthStateMigration.h | 0 .../Fake}/GIDFakeAuthStateMigration.m | 4 +- .../GIDAuthStateMigration.h | 0 .../GIDAuthStateMigration.m | 0 .../Implementation/GIDAuthStateMigration.h | 38 +++ .../Implementation/GIDAuthStateMigration.m | 253 ++++++++++++++++++ 6 files changed, 293 insertions(+), 2 deletions(-) rename GoogleSignIn/{Tests/Unit => Sources/GIDAuthStateMigration/Fake}/GIDFakeAuthStateMigration.h (100%) rename GoogleSignIn/{Tests/Unit => Sources/GIDAuthStateMigration/Fake}/GIDFakeAuthStateMigration.m (94%) rename GoogleSignIn/Sources/{ => GIDAuthStateMigration}/GIDAuthStateMigration.h (100%) rename GoogleSignIn/Sources/{ => GIDAuthStateMigration}/GIDAuthStateMigration.m (100%) create mode 100644 GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h create mode 100644 GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m diff --git a/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h similarity index 100% rename from GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h rename to GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h diff --git a/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m similarity index 94% rename from GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.m rename to GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m index 7bb4dcf3..f232e9b7 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m @@ -21,11 +21,11 @@ @implementation GIDFakeAuthStateMigration - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { - return [self init]; + self = [super initWithKeychainStore:keychainStore]; + return self; } - (instancetype)init { - self = [super init]; return self; } diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h similarity index 100% rename from GoogleSignIn/Sources/GIDAuthStateMigration.h rename to GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m similarity index 100% rename from GoogleSignIn/Sources/GIDAuthStateMigration.m rename to GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h new file mode 100644 index 00000000..738368fc --- /dev/null +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 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 GTMKeychainStore; +@class GTMAuthSession; + +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 with the keychain storage wrapper it will use. +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore NS_DESIGNATED_INITIALIZER; + +/// Perform necessary migrations from legacy auth state storage to most recent GTMAppAuth version. +- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL + callbackPath:(NSString *)callbackPath + keychainName:(NSString *)keychainName + isFreshInstall:(BOOL)isFreshInstall; + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m new file mode 100644 index 00000000..8819ac64 --- /dev/null +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m @@ -0,0 +1,253 @@ +// Copyright 2021 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 "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h" + +#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" + +@import GTMAppAuth; + +#ifdef SWIFT_PACKAGE +@import AppAuth; +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +// User preference key to detect whether or not the migration to GTMAppAuth has been performed. +static NSString *const kGTMAppAuthMigrationCheckPerformedKey = @"GID_MigrationCheckPerformed"; + +// User preference key to detect whether or not the data protected migration has been performed. +static NSString *const kDataProtectedMigrationCheckPerformedKey = + @"GID_DataProtectedMigrationCheckPerformed"; + +// Keychain account used to store additional state in SDKs previous to v5, including GPPSignIn. +static NSString *const kOldKeychainAccount = @"GooglePlus"; + +// The value used for the kSecAttrGeneric key by GTMAppAuth and GTMOAuth2. +static NSString *const kGenericAttribute = @"OAuth"; + +// 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 + +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { + self = [super init]; + if (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 { + // If this is a fresh install, take no action and mark the migration checks as having been + // performed. + if (isFreshInstall) { + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + [defaults setBool:YES forKey:kDataProtectedMigrationCheckPerformedKey]; +#elif TARGET_OS_IOS + [defaults setBool:YES forKey:kGTMAppAuthMigrationCheckPerformedKey]; +#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST + return; + } + +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + [self performDataProtectedMigrationIfNeeded]; +#elif TARGET_OS_IOS + [self performGIDMigrationIfNeededWithTokenURL:tokenURL + callbackPath:callbackPath + keychainName:keychainName]; +#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST +} + +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST +// Migrate from the fileBasedKeychain to dataProtectedKeychain with GTMAppAuth 5.0. +- (void)performDataProtectedMigrationIfNeeded { + // See if we've performed the migration check previously. + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + if ([defaults boolForKey:kDataProtectedMigrationCheckPerformedKey]) { + return; + } + + GTMKeychainAttribute *fileBasedKeychain = [GTMKeychainAttribute useFileBasedKeychain]; + NSSet *attributes = [NSSet setWithArray:@[fileBasedKeychain]]; + GTMKeychainStore *keychainStoreLegacy = + [[GTMKeychainStore alloc] initWithItemName:self.keychainStore.itemName + keychainAttributes:attributes]; + GTMAuthSession *authSession = [keychainStoreLegacy retrieveAuthSessionWithError:nil]; + // If migration was successful, save our migrated state to the keychain. + if (authSession) { + NSError *err; + [self.keychainStore saveAuthSession:authSession error:&err]; + // If we're unable to save to the keychain, return without marking migration performed. + if (err) { + return; + }; + [keychainStoreLegacy removeAuthSessionWithError:nil]; + } + + // Mark the migration check as having been performed. + [defaults setBool:YES forKey:kDataProtectedMigrationCheckPerformedKey]; +} + +#elif TARGET_OS_IOS +// Migrate from GPPSignIn 1.x or GIDSignIn 1.0 - 4.x to the GTMAppAuth storage introduced in +// GIDSignIn 5.0. +- (void)performGIDMigrationIfNeededWithTokenURL:(NSURL *)tokenURL + callbackPath:(NSString *)callbackPath + keychainName:(NSString *)keychainName { + // See if we've performed the migration check previously. + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + if ([defaults boolForKey:kGTMAppAuthMigrationCheckPerformedKey]) { + return; + } + + // Attempt migration + GTMAuthSession *authSession = + [self extractAuthSessionWithTokenURL:tokenURL callbackPath:callbackPath]; + + // If migration was successful, save our migrated state to the keychain. + if (authSession) { + NSError *err; + [self.keychainStore saveAuthSession:authSession error:&err]; + // If we're unable to save to the keychain, return without marking migration performed. + if (err) { + return; + }; + } + + // Mark the migration check as having been performed. + [defaults setBool:YES forKey:kGTMAppAuthMigrationCheckPerformedKey]; +} + +// Returns a |GTMAuthSession| object containing any old auth state or |nil| if none +// was found or the migration failed. +- (nullable GTMAuthSession *)extractAuthSessionWithTokenURL:(NSURL *)tokenURL + callbackPath:(NSString *)callbackPath { + // Retrieve the last used fingerprint. + NSString *fingerprint = [GIDAuthStateMigration passwordForService:kFingerprintService]; + if (!fingerprint) { + return nil; + } + + // Retrieve the GTMOAuth2 persistence string. + NSError *passwordError; + NSString *GTMOAuth2PersistenceString = + [self.keychainStore.keychainHelper passwordForService:fingerprint error:&passwordError]; + if (passwordError) { + return nil; + } + + // Parse the fingerprint. + NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; + NSString *pattern = + [NSString stringWithFormat:@"^%@-(.+)-(?:email|profile|https:\\/\\/).*$", bundleID]; + NSError *error; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern + options:0 + error:&error]; + NSRange matchRange = NSMakeRange(0, fingerprint.length); + NSArray *matches = [regex matchesInString:fingerprint + options:0 + range:matchRange]; + if ([matches count] != 1) { + return nil; + } + + // Extract the client ID from the fingerprint. + NSString *clientID = [fingerprint substringWithRange:[matches[0] rangeAtIndex:1]]; + + // Generate the redirect URI from the extracted client ID. + NSString *scheme = + [[[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:clientID] clientIdentifierScheme]; + NSString *redirectURI = [NSString stringWithFormat:@"%@:%@", scheme, callbackPath]; + + // Retrieve the additional token request parameters value. + NSString *additionalTokenRequestParametersService = + [NSString stringWithFormat:@"%@~~atrp", fingerprint]; + NSString *additionalTokenRequestParameters = + [GIDAuthStateMigration passwordForService:additionalTokenRequestParametersService]; + + // Generate a persistence string that includes additional token request parameters if present. + NSString *persistenceString = GTMOAuth2PersistenceString; + if (additionalTokenRequestParameters) { + persistenceString = [NSString stringWithFormat:@"%@&%@", + GTMOAuth2PersistenceString, + additionalTokenRequestParameters]; + } + + // Use |GTMOAuth2Compatibility| to generate a |GTMAuthSession| from the + // persistence string, redirect URI, client ID, and token endpoint URL. + GTMAuthSession *authSession = + [GTMOAuth2Compatibility authSessionForPersistenceString:persistenceString + tokenURL:tokenURL + redirectURI:redirectURI + clientID:clientID + clientSecret:nil + error:nil]; + + return authSession; +} + +// Returns the password string for a given service string stored by an old version of the SDK or +// |nil| if no matching keychain item was found. ++ (nullable NSString *)passwordForService:(NSString *)service { + if (!service.length) { + return nil; + } + CFDataRef result = NULL; + NSDictionary *query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrGeneric : kGenericAttribute, + (id)kSecAttrAccount : kOldKeychainAccount, + (id)kSecAttrService : service, + (id)kSecReturnData : (id)kCFBooleanTrue, + (id)kSecMatchLimit : (id)kSecMatchLimitOne, + }; + OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&result); + NSData *passwordData; + if (status == noErr && [(__bridge NSData *)result length] > 0) { + passwordData = [(__bridge NSData *)result copy]; + } + if (result != NULL) { + CFRelease(result); + } + if (!passwordData) { + return nil; + } + NSString *password = [[NSString alloc] initWithData:passwordData encoding:NSUTF8StringEncoding]; + return password; +} +#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST + +@end + +NS_ASSUME_NONNULL_END From 31e8734658dd8f21de9ff9e4648c3981008ecedc Mon Sep 17 00:00:00 2001 From: Camden King Date: Fri, 6 Jun 2025 10:38:59 -0700 Subject: [PATCH 04/16] update fake and create test --- .../Fake/GIDFakeAuthStateMigration.h | 7 +++- .../Fake/GIDFakeAuthStateMigration.m | 7 +++- .../Implementation/GIDAuthStateMigration.h | 38 ------------------- GoogleSignIn/Sources/GIDSignIn.m | 19 ++++++---- GoogleSignIn/Sources/GIDSignIn_Private.h | 5 ++- .../Tests/Unit/GIDAuthStateMigrationTest.m | 2 +- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 37 +++++++++++++++--- 7 files changed, 60 insertions(+), 55 deletions(-) delete mode 100644 GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h index 709793a0..fc611e53 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h @@ -14,9 +14,14 @@ * limitations under the License. */ -#import "GoogleSignIn/Sources/GIDAuthStateMigration.h" +#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h" /// A fake |GIDAuthStateMigration| for testing. @interface GIDFakeAuthStateMigration : GIDAuthStateMigration +/// Callback that is called when `migrateIfNeededWithTokenURL` is invoked. +@property (nonatomic, nullable) void (^migrationInvokedCallback) + (NSURL * _Nullable tokenURL, NSString * _Nullable callbackPath, NSString * _Nullable keychainName, + BOOL isFreshInstall); + @end diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m index f232e9b7..1f1b37d1 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#import "GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h" +#import "GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h" NS_ASSUME_NONNULL_BEGIN @implementation GIDFakeAuthStateMigration +@synthesize migrationInvokedCallback = _migrationInvokedCallback; + - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { self = [super initWithKeychainStore:keychainStore]; return self; @@ -33,6 +35,9 @@ - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath keychainName:(NSString *)keychainName isFreshInstall:(BOOL)isFreshInstall { + if (_migrationInvokedCallback) { + _migrationInvokedCallback(tokenURL, callbackPath, keychainName, isFreshInstall); + } return; } diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h deleted file mode 100644 index 738368fc..00000000 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 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 GTMKeychainStore; -@class GTMAuthSession; - -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 with the keychain storage wrapper it will use. -- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore NS_DESIGNATED_INITIALIZER; - -/// Perform necessary migrations from legacy auth state storage to most recent GTMAppAuth version. -- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL - callbackPath:(NSString *)callbackPath - keychainName:(NSString *)keychainName - isFreshInstall:(BOOL)isFreshInstall; - -@end - -NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 640761e1..cac0ee93 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -21,7 +21,7 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDProfileData.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignInResult.h" -#import "GoogleSignIn/Sources/GIDAuthStateMigration.h" +#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h" #import "GoogleSignIn/Sources/GIDEMMSupport.h" #import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" #import "GoogleSignIn/Sources/GIDSignInPreferences.h" @@ -186,6 +186,8 @@ @implementation GIDSignIn { // Flag indicating developer's intent to use App Check. BOOL _configureAppCheckCalled; #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST + // Service for performing auth state migrations. + GIDAuthStateMigration *_authStateMigrationService; } #pragma mark - Public methods @@ -490,15 +492,18 @@ + (GIDSignIn *)sharedInstance { dispatch_once(&once, ^{ GTMKeychainStore *keychainStore = [[GTMKeychainStore alloc] initWithItemName:kGTMAppAuthKeychainName]; + GIDAuthStateMigration *authStateMigrationService = + [[GIDAuthStateMigration alloc] initWithKeychainStore:keychainStore]; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST if (@available(iOS 14.0, *)) { GIDAppCheck *appCheck = [GIDAppCheck appCheckUsingAppAttestProvider]; sharedInstance = [[self alloc] initWithKeychainStore:keychainStore + authStateMigrationService:authStateMigrationService appCheck:appCheck]; } #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST if (!sharedInstance) { - sharedInstance = [[self alloc] initWithKeychainStore:keychainStore]; + sharedInstance = [[self alloc] initWithKeychainStore:keychainStore authStateMigrationService:authStateMigrationService]; } }); return sharedInstance; @@ -533,7 +538,8 @@ - (void)configureDebugProviderWithAPIKey:(NSString *)APIKey #pragma mark - Private methods -- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore + authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService { self = [super init]; if (self) { // Get the bundle of the current executable. @@ -561,9 +567,7 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { tokenEndpoint:[NSURL URLWithString:tokenEndpointURL]]; _keychainStore = keychainStore; // Perform migration of auth state from old versions of the SDK if needed. - GIDAuthStateMigration *migration = - [[GIDAuthStateMigration alloc] initWithKeychainStore:_keychainStore]; - [migration migrateIfNeededWithTokenURL:_appAuthConfiguration.tokenEndpoint + [authStateMigrationService migrateIfNeededWithTokenURL:_appAuthConfiguration.tokenEndpoint callbackPath:kBrowserCallbackPath keychainName:kGTMAppAuthKeychainName isFreshInstall:isFreshInstall]; @@ -573,8 +577,9 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore + authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService appCheck:(GIDAppCheck *)appCheck { - self = [self initWithKeychainStore:keychainStore]; + self = [self initWithKeychainStore:keychainStore authStateMigrationService:authStateMigrationService]; if (self) { _appCheck = appCheck; _configureAppCheckCalled = NO; diff --git a/GoogleSignIn/Sources/GIDSignIn_Private.h b/GoogleSignIn/Sources/GIDSignIn_Private.h index 4072a4a0..bdc79057 100644 --- a/GoogleSignIn/Sources/GIDSignIn_Private.h +++ b/GoogleSignIn/Sources/GIDSignIn_Private.h @@ -30,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @class GIDSignInInternalOptions; @class GTMKeychainStore; @class GIDAppCheck; +@class GIDAuthStateMigration; /// Represents a completion block that takes a `GIDSignInResult` on success or an error if the /// operation was unsuccessful. @@ -46,11 +47,13 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error); @property(nonatomic, readwrite, nullable) GIDGoogleUser *currentUser; /// Private initializer taking a `GTMKeychainStore`. -- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore; +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore + authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST /// Private initializer taking a `GTMKeychainStore` and `GIDAppCheckProvider`. - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore + authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService appCheck:(GIDAppCheck *)appCheck API_AVAILABLE(ios(14)); #endif // TARGET_OS_IOS || !TARGET_OS_MACCATALYST diff --git a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m index 457b84de..20b16451 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m @@ -14,7 +14,7 @@ #import -#import "GoogleSignIn/Sources/GIDAuthStateMigration.h" +#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h" #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" #if TARGET_OS_OSX #import "GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h" diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index bdb6c378..6386b818 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -40,7 +40,7 @@ #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h" #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST -#import "GoogleSignIn/Tests/Unit/GIDFakeAuthStateMigration.h" +#import "GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h" #import "GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h" #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" @@ -344,7 +344,8 @@ - (void)setUp { // Object under test [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAppHasRunBeforeKey]; - _signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore]; + _signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore + authStateMigrationService:_authStateMigrationService]; _hint = nil; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST @@ -403,6 +404,7 @@ - (void)testConfigureSucceeds { userDefaults:_testUserDefaults]; GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore + authStateMigrationService:_authStateMigrationService appCheck:appCheck]; [signIn configureWithCompletion:^(NSError * _Nullable error) { XCTAssertNil(error); @@ -426,6 +428,7 @@ - (void)testConfigureFailsNoTokenOrError { userDefaults:_testUserDefaults]; GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore + authStateMigrationService:_authStateMigrationService appCheck:appCheck]; // Should fail if missing both token and error @@ -444,7 +447,8 @@ - (void)testConfigureFailsNoTokenOrError { - (void)testInitWithKeychainStore { GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"]; GIDSignIn *signIn; - signIn = [[GIDSignIn alloc] initWithKeychainStore:store]; + signIn = [[GIDSignIn alloc] initWithKeychainStore:store + authStateMigrationService:_authStateMigrationService]; XCTAssertNotNil(signIn.configuration); XCTAssertEqual(signIn.configuration.clientID, kClientId); XCTAssertNil(signIn.configuration.serverClientID); @@ -459,7 +463,8 @@ - (void)testInitWithKeychainStore_noConfig { openIDRealm:nil]; GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"]; GIDSignIn *signIn; - signIn = [[GIDSignIn alloc] initWithKeychainStore:store]; + signIn = [[GIDSignIn alloc] initWithKeychainStore:store + authStateMigrationService:_authStateMigrationService]; XCTAssertNil(signIn.configuration); } @@ -471,7 +476,8 @@ - (void)testInitWithKeychainStore_fullConfig { GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"]; GIDSignIn *signIn; - signIn = [[GIDSignIn alloc] initWithKeychainStore:store]; + signIn = [[GIDSignIn alloc] initWithKeychainStore:store + authStateMigrationService:_authStateMigrationService]; XCTAssertNotNil(signIn.configuration); XCTAssertEqual(signIn.configuration.clientID, kClientId); XCTAssertEqual(signIn.configuration.serverClientID, kServerClientId); @@ -486,10 +492,29 @@ - (void)testInitWithKeychainStore_invalidConfig { openIDRealm:nil]; GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"]; GIDSignIn *signIn; - signIn = [[GIDSignIn alloc] initWithKeychainStore:store]; + signIn = [[GIDSignIn alloc] initWithKeychainStore:store + authStateMigrationService:_authStateMigrationService]; XCTAssertNil(signIn.configuration); } +- (void)testInitWithKeychainStore_attemptsMigration { + NSString *expectedKeychainName = @"foo"; + + XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called."]; + _authStateMigrationService.migrationInvokedCallback = + ^(NSURL *tokenURL, NSString *callbackPath, NSString *keychainName, BOOL isFreshInstall) { + XCTAssertFalse(isFreshInstall); + [expectation fulfill]; + }; + + GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:expectedKeychainName]; + GIDSignIn *signIn; + signIn = [[GIDSignIn alloc] initWithKeychainStore:store + authStateMigrationService:_authStateMigrationService]; + + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + - (void)testRestorePreviousSignInNoRefresh_hasPreviousUser { [[[_authorization stub] andReturn:_authState] authState]; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST From a52d83b4cfc5543d1fb35a85b10cd4a1266b58f1 Mon Sep 17 00:00:00 2001 From: Camden King Date: Fri, 6 Jun 2025 10:40:43 -0700 Subject: [PATCH 05/16] remove unneeded local variable from GIDSignIn --- GoogleSignIn/Sources/GIDSignIn.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index cac0ee93..0548e3d6 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -186,8 +186,6 @@ @implementation GIDSignIn { // Flag indicating developer's intent to use App Check. BOOL _configureAppCheckCalled; #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST - // Service for performing auth state migrations. - GIDAuthStateMigration *_authStateMigrationService; } #pragma mark - Public methods From 4397dd68f38799ba11966ed24cc060974755e341 Mon Sep 17 00:00:00 2001 From: Camden King <74014435+camden-king@users.noreply.github.com> Date: Mon, 9 Jun 2025 10:31:09 -0700 Subject: [PATCH 06/16] Attempt migrations once (#528) --- .../Implementation/GIDAuthStateMigration.m | 8 -------- 1 file changed, 8 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m index 8819ac64..9b43d6e5 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m @@ -107,10 +107,6 @@ - (void)performDataProtectedMigrationIfNeeded { if (authSession) { NSError *err; [self.keychainStore saveAuthSession:authSession error:&err]; - // If we're unable to save to the keychain, return without marking migration performed. - if (err) { - return; - }; [keychainStoreLegacy removeAuthSessionWithError:nil]; } @@ -138,10 +134,6 @@ - (void)performGIDMigrationIfNeededWithTokenURL:(NSURL *)tokenURL if (authSession) { NSError *err; [self.keychainStore saveAuthSession:authSession error:&err]; - // If we're unable to save to the keychain, return without marking migration performed. - if (err) { - return; - }; } // Mark the migration check as having been performed. From 7a301c1bb7733cbad411e1e48cc633daba508e8d Mon Sep 17 00:00:00 2001 From: Camden King Date: Tue, 10 Jun 2025 10:52:14 -0700 Subject: [PATCH 07/16] changes from review --- .../Fake/GIDFakeAuthStateMigration.m | 4 ---- GoogleSignIn/Sources/GIDSignIn.m | 14 ++++++++------ GoogleSignIn/Tests/Unit/GIDSignInTest.m | 11 +++++------ 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m index 1f1b37d1..a0da9e13 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m @@ -27,10 +27,6 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { return self; } -- (instancetype)init { - return self; -} - - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath keychainName:(NSString *)keychainName diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 0548e3d6..d4e08e18 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -491,7 +491,7 @@ + (GIDSignIn *)sharedInstance { GTMKeychainStore *keychainStore = [[GTMKeychainStore alloc] initWithItemName:kGTMAppAuthKeychainName]; GIDAuthStateMigration *authStateMigrationService = - [[GIDAuthStateMigration alloc] initWithKeychainStore:keychainStore]; + [[GIDAuthStateMigration alloc] initWithKeychainStore:keychainStore]; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST if (@available(iOS 14.0, *)) { GIDAppCheck *appCheck = [GIDAppCheck appCheckUsingAppAttestProvider]; @@ -501,7 +501,8 @@ + (GIDSignIn *)sharedInstance { } #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST if (!sharedInstance) { - sharedInstance = [[self alloc] initWithKeychainStore:keychainStore authStateMigrationService:authStateMigrationService]; + sharedInstance = [[self alloc] initWithKeychainStore:keychainStore + authStateMigrationService:authStateMigrationService]; } }); return sharedInstance; @@ -566,9 +567,9 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore _keychainStore = keychainStore; // Perform migration of auth state from old versions of the SDK if needed. [authStateMigrationService migrateIfNeededWithTokenURL:_appAuthConfiguration.tokenEndpoint - callbackPath:kBrowserCallbackPath - keychainName:kGTMAppAuthKeychainName - isFreshInstall:isFreshInstall]; + callbackPath:kBrowserCallbackPath + keychainName:kGTMAppAuthKeychainName + isFreshInstall:isFreshInstall]; } return self; } @@ -577,7 +578,8 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService appCheck:(GIDAppCheck *)appCheck { - self = [self initWithKeychainStore:keychainStore authStateMigrationService:authStateMigrationService]; + self = [self initWithKeychainStore:keychainStore + authStateMigrationService:authStateMigrationService]; if (self) { _appCheck = appCheck; _configureAppCheckCalled = NO; diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 6386b818..73a6d49d 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -502,14 +502,13 @@ - (void)testInitWithKeychainStore_attemptsMigration { XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called."]; _authStateMigrationService.migrationInvokedCallback = - ^(NSURL *tokenURL, NSString *callbackPath, NSString *keychainName, BOOL isFreshInstall) { - XCTAssertFalse(isFreshInstall); - [expectation fulfill]; - }; + ^(NSURL *tokenURL, NSString *callbackPath, NSString *keychainName, BOOL isFreshInstall) { + XCTAssertFalse(isFreshInstall); + [expectation fulfill]; + }; GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:expectedKeychainName]; - GIDSignIn *signIn; - signIn = [[GIDSignIn alloc] initWithKeychainStore:store + GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:store authStateMigrationService:_authStateMigrationService]; [self waitForExpectationsWithTimeout:1 handler:nil]; From 4d0707a05547a8869ccd1c1b99cb2966cc22b0ca Mon Sep 17 00:00:00 2001 From: Camden King Date: Tue, 10 Jun 2025 11:25:03 -0700 Subject: [PATCH 08/16] update comment + spacing --- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 73a6d49d..5cba753d 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -222,7 +222,7 @@ @interface GIDSignInTest : XCTestCase { // Whether callback block has been called. BOOL _completionCalled; - // Fake for GIDAuthStateMigration + // Fake for |GIDAuthStateMigration|. GIDFakeAuthStateMigration *_authStateMigrationService; // Fake fetcher service to emulate network requests. @@ -509,7 +509,7 @@ - (void)testInitWithKeychainStore_attemptsMigration { GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:expectedKeychainName]; GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:store - authStateMigrationService:_authStateMigrationService]; + authStateMigrationService:_authStateMigrationService]; [self waitForExpectationsWithTimeout:1 handler:nil]; } From 6ef11d8b168a3fe91f391db43958d16030e40c5d Mon Sep 17 00:00:00 2001 From: Camden King Date: Tue, 17 Jun 2025 15:43:38 -0700 Subject: [PATCH 09/16] check signIn not nil --- 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 5cba753d..eb367322 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -511,6 +511,7 @@ - (void)testInitWithKeychainStore_attemptsMigration { GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:store authStateMigrationService:_authStateMigrationService]; + XCTAssertNotNil(signIn.configuration); [self waitForExpectationsWithTimeout:1 handler:nil]; } From 69058b6316b8f9ddc5c3b23a226f07c63a780880 Mon Sep 17 00:00:00 2001 From: Camden King <74014435+camden-king@users.noreply.github.com> Date: Wed, 11 Jun 2025 09:14:56 -0700 Subject: [PATCH 10/16] Update GIDAuthStateMigration to not perform migration when built for Mac Catalyst (#526) --- .../Implementation/GIDAuthStateMigration.m | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m index 9b43d6e5..69631adc 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m @@ -71,24 +71,24 @@ - (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL // performed. if (isFreshInstall) { NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; -#if TARGET_OS_OSX || TARGET_OS_MACCATALYST +#if TARGET_OS_OSX [defaults setBool:YES forKey:kDataProtectedMigrationCheckPerformedKey]; -#elif TARGET_OS_IOS +#elif TARGET_OS_IOS && !TARGET_OS_MACCATALYST [defaults setBool:YES forKey:kGTMAppAuthMigrationCheckPerformedKey]; -#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST +#endif // TARGET_OS_OSX return; } -#if TARGET_OS_OSX || TARGET_OS_MACCATALYST +#if TARGET_OS_OSX [self performDataProtectedMigrationIfNeeded]; -#elif TARGET_OS_IOS +#elif TARGET_OS_IOS && !TARGET_OS_MACCATALYST [self performGIDMigrationIfNeededWithTokenURL:tokenURL callbackPath:callbackPath keychainName:keychainName]; -#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST +#endif // TARGET_OS_OSX } -#if TARGET_OS_OSX || TARGET_OS_MACCATALYST +#if TARGET_OS_OSX // Migrate from the fileBasedKeychain to dataProtectedKeychain with GTMAppAuth 5.0. - (void)performDataProtectedMigrationIfNeeded { // See if we've performed the migration check previously. @@ -114,7 +114,7 @@ - (void)performDataProtectedMigrationIfNeeded { [defaults setBool:YES forKey:kDataProtectedMigrationCheckPerformedKey]; } -#elif TARGET_OS_IOS +#elif TARGET_OS_IOS && !TARGET_OS_MACCATALYST // Migrate from GPPSignIn 1.x or GIDSignIn 1.0 - 4.x to the GTMAppAuth storage introduced in // GIDSignIn 5.0. - (void)performGIDMigrationIfNeededWithTokenURL:(NSURL *)tokenURL @@ -238,7 +238,7 @@ + (nullable NSString *)passwordForService:(NSString *)service { NSString *password = [[NSString alloc] initWithData:passwordData encoding:NSUTF8StringEncoding]; return password; } -#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST +#endif // TARGET_OS_OSX @end From 645e2810a963665f1d6d5f458fe76218c25cb5b0 Mon Sep 17 00:00:00 2001 From: Camden King Date: Fri, 6 Jun 2025 10:38:36 -0700 Subject: [PATCH 11/16] update fake and create test --- .../GIDAuthStateMigration.m | 10 +++++ .../Implementation/GIDAuthStateMigration.h | 38 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m index 3085fa76..ef2e2d2e 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m @@ -12,7 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +<<<<<<< HEAD #import "GoogleSignIn/Sources/GIDAuthStateMigration.h" +======= +#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h" +>>>>>>> 43b6160 (update fake and create test) #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" @@ -107,10 +111,13 @@ - (void)performDataProtectedMigrationIfNeeded { if (authSession) { NSError *err; [self.keychainStore saveAuthSession:authSession error:&err]; +<<<<<<< HEAD // If we're unable to save to the keychain, return without marking migration performed. if (err) { return; }; +======= +>>>>>>> 43b6160 (update fake and create test) [keychainStoreLegacy removeAuthSessionWithError:nil]; } @@ -138,10 +145,13 @@ - (void)performGIDMigrationIfNeededWithTokenURL:(NSURL *)tokenURL if (authSession) { NSError *err; [self.keychainStore saveAuthSession:authSession error:&err]; +<<<<<<< HEAD // If we're unable to save to the keychain, return without marking migration performed. if (err) { return; }; +======= +>>>>>>> 43b6160 (update fake and create test) } // Mark the migration check as having been performed. diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h new file mode 100644 index 00000000..738368fc --- /dev/null +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 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 GTMKeychainStore; +@class GTMAuthSession; + +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 with the keychain storage wrapper it will use. +- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore NS_DESIGNATED_INITIALIZER; + +/// Perform necessary migrations from legacy auth state storage to most recent GTMAppAuth version. +- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL + callbackPath:(NSString *)callbackPath + keychainName:(NSString *)keychainName + isFreshInstall:(BOOL)isFreshInstall; + +@end + +NS_ASSUME_NONNULL_END From 7b9bac081ec000230fb867cdfd1b48e1a3e1fb76 Mon Sep 17 00:00:00 2001 From: Camden King Date: Tue, 17 Jun 2025 16:00:39 -0700 Subject: [PATCH 12/16] rebase --- .../Implementation/GIDAuthStateMigration.h | 38 ------------------- GoogleSignIn/Sources/GIDSignIn.m | 2 + 2 files changed, 2 insertions(+), 38 deletions(-) delete mode 100644 GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h deleted file mode 100644 index 738368fc..00000000 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 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 GTMKeychainStore; -@class GTMAuthSession; - -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 with the keychain storage wrapper it will use. -- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore NS_DESIGNATED_INITIALIZER; - -/// Perform necessary migrations from legacy auth state storage to most recent GTMAppAuth version. -- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL - callbackPath:(NSString *)callbackPath - keychainName:(NSString *)keychainName - isFreshInstall:(BOOL)isFreshInstall; - -@end - -NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index d4e08e18..8aeda8ed 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -186,6 +186,8 @@ @implementation GIDSignIn { // Flag indicating developer's intent to use App Check. BOOL _configureAppCheckCalled; #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST + // Service for performing auth state migrations. + GIDAuthStateMigration *_authStateMigrationService; } #pragma mark - Public methods From 26a118a43968c3d250a87578180e544ef4aa1114 Mon Sep 17 00:00:00 2001 From: Camden King Date: Tue, 17 Jun 2025 16:23:57 -0700 Subject: [PATCH 13/16] rebase --- .../GIDAuthStateMigration.m | 263 ------------------ 1 file changed, 263 deletions(-) delete mode 100644 GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m deleted file mode 100644 index ef2e2d2e..00000000 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.m +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2021 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. - -<<<<<<< HEAD -#import "GoogleSignIn/Sources/GIDAuthStateMigration.h" -======= -#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h" ->>>>>>> 43b6160 (update fake and create test) - -#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" - -@import GTMAppAuth; - -#ifdef SWIFT_PACKAGE -@import AppAuth; -#else -#import -#endif - -NS_ASSUME_NONNULL_BEGIN - -// User preference key to detect whether or not the migration to GTMAppAuth has been performed. -static NSString *const kGTMAppAuthMigrationCheckPerformedKey = @"GID_MigrationCheckPerformed"; - -// User preference key to detect whether or not the data protected migration has been performed. -static NSString *const kDataProtectedMigrationCheckPerformedKey = - @"GID_DataProtectedMigrationCheckPerformed"; - -// Keychain account used to store additional state in SDKs previous to v5, including GPPSignIn. -static NSString *const kOldKeychainAccount = @"GooglePlus"; - -// The value used for the kSecAttrGeneric key by GTMAppAuth and GTMOAuth2. -static NSString *const kGenericAttribute = @"OAuth"; - -// 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 - -- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { - self = [super init]; - if (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 { - // If this is a fresh install, take no action and mark the migration checks as having been - // performed. - if (isFreshInstall) { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; -#if TARGET_OS_OSX - [defaults setBool:YES forKey:kDataProtectedMigrationCheckPerformedKey]; -#elif TARGET_OS_IOS && !TARGET_OS_MACCATALYST - [defaults setBool:YES forKey:kGTMAppAuthMigrationCheckPerformedKey]; -#endif // TARGET_OS_OSX - return; - } - -#if TARGET_OS_OSX - [self performDataProtectedMigrationIfNeeded]; -#elif TARGET_OS_IOS && !TARGET_OS_MACCATALYST - [self performGIDMigrationIfNeededWithTokenURL:tokenURL - callbackPath:callbackPath - keychainName:keychainName]; -#endif // TARGET_OS_OSX -} - -#if TARGET_OS_OSX -// Migrate from the fileBasedKeychain to dataProtectedKeychain with GTMAppAuth 5.0. -- (void)performDataProtectedMigrationIfNeeded { - // See if we've performed the migration check previously. - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - if ([defaults boolForKey:kDataProtectedMigrationCheckPerformedKey]) { - return; - } - - GTMKeychainAttribute *fileBasedKeychain = [GTMKeychainAttribute useFileBasedKeychain]; - NSSet *attributes = [NSSet setWithArray:@[fileBasedKeychain]]; - GTMKeychainStore *keychainStoreLegacy = - [[GTMKeychainStore alloc] initWithItemName:self.keychainStore.itemName - keychainAttributes:attributes]; - GTMAuthSession *authSession = [keychainStoreLegacy retrieveAuthSessionWithError:nil]; - // If migration was successful, save our migrated state to the keychain. - if (authSession) { - NSError *err; - [self.keychainStore saveAuthSession:authSession error:&err]; -<<<<<<< HEAD - // If we're unable to save to the keychain, return without marking migration performed. - if (err) { - return; - }; -======= ->>>>>>> 43b6160 (update fake and create test) - [keychainStoreLegacy removeAuthSessionWithError:nil]; - } - - // Mark the migration check as having been performed. - [defaults setBool:YES forKey:kDataProtectedMigrationCheckPerformedKey]; -} - -#elif TARGET_OS_IOS && !TARGET_OS_MACCATALYST -// Migrate from GPPSignIn 1.x or GIDSignIn 1.0 - 4.x to the GTMAppAuth storage introduced in -// GIDSignIn 5.0. -- (void)performGIDMigrationIfNeededWithTokenURL:(NSURL *)tokenURL - callbackPath:(NSString *)callbackPath - keychainName:(NSString *)keychainName { - // See if we've performed the migration check previously. - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - if ([defaults boolForKey:kGTMAppAuthMigrationCheckPerformedKey]) { - return; - } - - // Attempt migration - GTMAuthSession *authSession = - [self extractAuthSessionWithTokenURL:tokenURL callbackPath:callbackPath]; - - // If migration was successful, save our migrated state to the keychain. - if (authSession) { - NSError *err; - [self.keychainStore saveAuthSession:authSession error:&err]; -<<<<<<< HEAD - // If we're unable to save to the keychain, return without marking migration performed. - if (err) { - return; - }; -======= ->>>>>>> 43b6160 (update fake and create test) - } - - // Mark the migration check as having been performed. - [defaults setBool:YES forKey:kGTMAppAuthMigrationCheckPerformedKey]; -} - -// Returns a |GTMAuthSession| object containing any old auth state or |nil| if none -// was found or the migration failed. -- (nullable GTMAuthSession *)extractAuthSessionWithTokenURL:(NSURL *)tokenURL - callbackPath:(NSString *)callbackPath { - // Retrieve the last used fingerprint. - NSString *fingerprint = [GIDAuthStateMigration passwordForService:kFingerprintService]; - if (!fingerprint) { - return nil; - } - - // Retrieve the GTMOAuth2 persistence string. - NSError *passwordError; - NSString *GTMOAuth2PersistenceString = - [self.keychainStore.keychainHelper passwordForService:fingerprint error:&passwordError]; - if (passwordError) { - return nil; - } - - // Parse the fingerprint. - NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; - NSString *pattern = - [NSString stringWithFormat:@"^%@-(.+)-(?:email|profile|https:\\/\\/).*$", bundleID]; - NSError *error; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern - options:0 - error:&error]; - NSRange matchRange = NSMakeRange(0, fingerprint.length); - NSArray *matches = [regex matchesInString:fingerprint - options:0 - range:matchRange]; - if ([matches count] != 1) { - return nil; - } - - // Extract the client ID from the fingerprint. - NSString *clientID = [fingerprint substringWithRange:[matches[0] rangeAtIndex:1]]; - - // Generate the redirect URI from the extracted client ID. - NSString *scheme = - [[[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:clientID] clientIdentifierScheme]; - NSString *redirectURI = [NSString stringWithFormat:@"%@:%@", scheme, callbackPath]; - - // Retrieve the additional token request parameters value. - NSString *additionalTokenRequestParametersService = - [NSString stringWithFormat:@"%@~~atrp", fingerprint]; - NSString *additionalTokenRequestParameters = - [GIDAuthStateMigration passwordForService:additionalTokenRequestParametersService]; - - // Generate a persistence string that includes additional token request parameters if present. - NSString *persistenceString = GTMOAuth2PersistenceString; - if (additionalTokenRequestParameters) { - persistenceString = [NSString stringWithFormat:@"%@&%@", - GTMOAuth2PersistenceString, - additionalTokenRequestParameters]; - } - - // Use |GTMOAuth2Compatibility| to generate a |GTMAuthSession| from the - // persistence string, redirect URI, client ID, and token endpoint URL. - GTMAuthSession *authSession = - [GTMOAuth2Compatibility authSessionForPersistenceString:persistenceString - tokenURL:tokenURL - redirectURI:redirectURI - clientID:clientID - clientSecret:nil - error:nil]; - - return authSession; -} - -// Returns the password string for a given service string stored by an old version of the SDK or -// |nil| if no matching keychain item was found. -+ (nullable NSString *)passwordForService:(NSString *)service { - if (!service.length) { - return nil; - } - CFDataRef result = NULL; - NSDictionary *query = @{ - (id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrGeneric : kGenericAttribute, - (id)kSecAttrAccount : kOldKeychainAccount, - (id)kSecAttrService : service, - (id)kSecReturnData : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitOne, - }; - OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&result); - NSData *passwordData; - if (status == noErr && [(__bridge NSData *)result length] > 0) { - passwordData = [(__bridge NSData *)result copy]; - } - if (result != NULL) { - CFRelease(result); - } - if (!passwordData) { - return nil; - } - NSString *password = [[NSString alloc] initWithData:passwordData encoding:NSUTF8StringEncoding]; - return password; -} -#endif // TARGET_OS_OSX - -@end - -NS_ASSUME_NONNULL_END From 59d117238982ed406b53a7249d12c2fa79aeff48 Mon Sep 17 00:00:00 2001 From: Camden King Date: Wed, 18 Jun 2025 11:05:24 -0700 Subject: [PATCH 14/16] changes from review --- GoogleSignIn/Sources/GIDSignIn.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 8aeda8ed..ef7ac3eb 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -186,8 +186,6 @@ @implementation GIDSignIn { // Flag indicating developer's intent to use App Check. BOOL _configureAppCheckCalled; #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST - // Service for performing auth state migrations. - GIDAuthStateMigration *_authStateMigrationService; } #pragma mark - Public methods @@ -540,7 +538,7 @@ - (void)configureDebugProviderWithAPIKey:(NSString *)APIKey #pragma mark - Private methods - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore - authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService { + authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService { self = [super init]; if (self) { // Get the bundle of the current executable. @@ -578,7 +576,7 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore - authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService + authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService appCheck:(GIDAppCheck *)appCheck { self = [self initWithKeychainStore:keychainStore authStateMigrationService:authStateMigrationService]; From e56d34f5e3d5ff4bf418606d6b7cc574305986a9 Mon Sep 17 00:00:00 2001 From: Camden King Date: Wed, 18 Jun 2025 11:20:29 -0700 Subject: [PATCH 15/16] changes from review --- .../GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m | 2 +- GoogleSignIn/Sources/GIDSignIn_Private.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m index a0da9e13..0346dba1 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.m @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#import "GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h" +#import "GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h" NS_ASSUME_NONNULL_BEGIN diff --git a/GoogleSignIn/Sources/GIDSignIn_Private.h b/GoogleSignIn/Sources/GIDSignIn_Private.h index bdc79057..bb642cb7 100644 --- a/GoogleSignIn/Sources/GIDSignIn_Private.h +++ b/GoogleSignIn/Sources/GIDSignIn_Private.h @@ -48,12 +48,12 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error); /// Private initializer taking a `GTMKeychainStore`. - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore - authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService; + authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST /// Private initializer taking a `GTMKeychainStore` and `GIDAppCheckProvider`. - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore - authStateMigrationService:(GIDAuthStateMigration *) authStateMigrationService + authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService appCheck:(GIDAppCheck *)appCheck API_AVAILABLE(ios(14)); #endif // TARGET_OS_IOS || !TARGET_OS_MACCATALYST From 1181124d9815c4a717d46238ff657074b754ec24 Mon Sep 17 00:00:00 2001 From: Camden King Date: Wed, 18 Jun 2025 12:05:09 -0700 Subject: [PATCH 16/16] removed line break --- .../GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m | 1 - 1 file changed, 1 deletion(-) diff --git a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m index 69631adc..b5c21773 100644 --- a/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m +++ b/GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m @@ -13,7 +13,6 @@ // limitations under the License. #import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h" - #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" @import GTMAppAuth;