Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-13]
os: [macos-15]
podspec: [GoogleSignIn.podspec, GoogleSignInSwiftSupport.podspec]
flag: [
"",
Expand Down
8 changes: 6 additions & 2 deletions GoogleSignIn/Sources/GIDSignIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@
// Error string for user cancelations.
static NSString *const kUserCanceledError = @"The user canceled the sign-in flow.";

// User preference key to detect fresh install of the app.
static NSString *const kAppHasRunBeforeKey = @"GID_AppHasRunBefore";
NSString *const kAppHasRunBeforeKey = @"GID_AppHasRunBefore";

// Maximum retry interval in seconds for the fetcher.
static const NSTimeInterval kFetcherMaxRetryInterval = 15.0;
Expand Down Expand Up @@ -553,6 +552,11 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore

// Check to see if the 3P app is being run for the first time after a fresh install.
BOOL isFreshInstall = [self isFreshInstall];

// If this is a fresh install, ensure that any pre-existing keychain data is purged.
if (isFreshInstall) {
[self removeAllKeychainEntries];
}

NSString *authorizationEnpointURL = [NSString stringWithFormat:kAuthorizationURLTemplate,
[GIDSignInPreferences googleAuthorizationServer]];
Expand Down
3 changes: 3 additions & 0 deletions GoogleSignIn/Sources/GIDSignIn_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ NS_ASSUME_NONNULL_BEGIN
@class GIDAppCheck;
@class GIDAuthStateMigration;

/// User preference key to detect fresh install of the app.
extern NSString *const kAppHasRunBeforeKey;

/// Represents a completion block that takes a `GIDSignInResult` on success or an error if the
/// operation was unsuccessful.
typedef void (^GIDSignInCompletion)(GIDSignInResult *_Nullable signInResult,
Expand Down
15 changes: 13 additions & 2 deletions GoogleSignIn/Tests/Unit/GIDSignInTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@
@"com.google.UnitTests:///emmcallback?action=unrecognized";
static NSString * const kDevicePolicyAppBundleID = @"com.google.DevicePolicy";

static NSString * const kAppHasRunBeforeKey = @"GPP_AppHasRunBefore";

static NSString * const kFingerprintKeychainName = @"fingerprint";
static NSString * const kVerifierKeychainName = @"verifier";
static NSString * const kVerifierKey = @"verifier";
Expand Down Expand Up @@ -993,6 +991,19 @@ - (void)testNotHandleWrongPath {
XCTAssertFalse(_completionCalled, @"should not call delegate");
}

#pragma mark - Test Fresh Install

- (void)testFreshInstall_removesKeychainEntries {
// Simulate that the app has been deleted and user defaults removed.
[NSUserDefaults.standardUserDefaults removeObjectForKey:kAppHasRunBeforeKey];
// Initialization should check `isFreshInstall`.
GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore
authStateMigrationService:_authStateMigrationService];
// If `isFreshInstall`, keychain entries should be removed.
XCTAssertNotNil(signIn);
XCTAssertTrue(self->_keychainRemoved);
}

#pragma mark - Tests - disconnectWithCallback:

// Verifies disconnect calls callback with no errors if access token is present.
Expand Down
Loading