From 54df79417e61e59729894f973f3bfe14e9723c84 Mon Sep 17 00:00:00 2001 From: brianna Date: Wed, 17 Apr 2024 12:43:20 -0700 Subject: [PATCH 01/28] Create method verifyAccountDetailsInteractivelyWithOptions. --- .../Implementations/GIDVerifyAccountDetail.m | 57 +++++++++++++++++++ .../GoogleSignIn/GIDVerifyAccountDetail.h | 4 ++ 2 files changed, 61 insertions(+) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index ef551702..9b7f58bc 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -16,9 +16,13 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiedAccountDetailResult.h" +#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" +#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" + #if TARGET_OS_IOS @implementation GIDVerifyAccountDetail @@ -47,6 +51,59 @@ - (void)verifyAccountDetails:(NSArray *)accountDet // TODO(#383): Implement this method. } +// Starts authorization flow using the provided options. +- (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions *)options { + if (!options.interactive) { + return; + } + + // Ensure that a configuration is set. + if (!_configuration) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"No active configuration. Make sure GIDClientID is set in Info.plist."]; + return; + } + + // Explicitly throw exception for missing client ID here. This must come before + // scheme check because schemes rely on reverse client IDs. + [self assertValidParameters:options]; + + [self assertValidPresentingViewController:options]; + + // If the application does not support the required URL schemes tell the developer so. + GIDSignInCallbackSchemes *schemes = + [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; + NSArray *unsupportedSchemes = [schemes unsupportedSchemes]; + if (unsupportedSchemes.count != 0) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"Your app is missing support for the following URL schemes: %@", + [unsupportedSchemes componentsJoinedByString:@", "]]; + } + // TODO(#397): Start the incremental authorization flow. +} + +#pragma mark - Helpers + +// Asserts the parameters being valid. +- (void)assertValidParameters:(GIDSignInInternalOptions *)options { + if (![options.configuration.clientID length]) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"You must specify |clientID| in |GIDConfiguration|"]; + } +} + +// Assert that the presenting view controller has been set. +- (void)assertValidPresentingViewController:(GIDSignInInternalOptions *)options { + if (!options.presentingViewController) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"|presentingViewController| must be set."]; + } +} + @end #endif // TARGET_OS_IOS diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index dca4586e..139d3fa8 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN +@class GIDConfiguration; @class GIDVerifiableAccountDetail; @class GIDVerifiedAccountDetailResult; @@ -39,6 +40,9 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve /// This class is used to verify a user's Google account details. @interface GIDVerifyAccountDetail : NSObject +/// The active configuration for this instance of `GIDVerifyAccountDetail`. +@property(nonatomic, nullable) GIDConfiguration *configuration; + /// Starts an interactive verification flow. /// /// The completion will be called at the end of this process. Any saved verification From 58969855dfe502092a457d2c0e2c0380fc66f204 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 18 Apr 2024 09:31:55 -0700 Subject: [PATCH 02/28] Move configuration creation methods to GIDConfiguration from GIDSignIn. --- GoogleSignIn/Sources/GIDConfiguration.m | 35 +++++++++++++++++++ GoogleSignIn/Sources/GIDSignIn.m | 34 +----------------- .../Public/GoogleSignIn/GIDConfiguration.h | 5 +++ 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/GoogleSignIn/Sources/GIDConfiguration.m b/GoogleSignIn/Sources/GIDConfiguration.m index 34ba3c8d..8a0415cb 100644 --- a/GoogleSignIn/Sources/GIDConfiguration.m +++ b/GoogleSignIn/Sources/GIDConfiguration.m @@ -26,6 +26,12 @@ // The key for the openIDRealm property to be used with NSSecureCoding. static NSString *const kOpenIDRealmKey = @"openIDRealm"; +// Info.plist config keys +static NSString *const kConfigClientIDKey = @"GIDClientID"; +static NSString *const kConfigServerClientIDKey = @"GIDServerClientID"; +static NSString *const kConfigHostedDomainKey = @"GIDHostedDomain"; +static NSString *const kConfigOpenIDRealmKey = @"GIDOpenIDRealm"; + NS_ASSUME_NONNULL_BEGIN @implementation GIDConfiguration @@ -59,6 +65,35 @@ - (instancetype)initWithClientID:(NSString *)clientID return self; } +// Try to retrieve a configuration value from an |NSBundle|'s Info.plist for a given key. ++ (nullable NSString *)configValueFromBundle:(NSBundle *)bundle forKey:(NSString *)key { + NSString *value; + id configValue = [bundle objectForInfoDictionaryKey:key]; + if ([configValue isKindOfClass:[NSString class]]) { + value = configValue; + } + return value; +} + ++ (nullable instancetype)configurationFromBundle:(NSBundle *)bundle { + // Retrieve any valid config parameters from the bundle's Info.plist. + NSString *clientID = [self configValueFromBundle:bundle forKey:kConfigClientIDKey]; + NSString *serverClientID = [self configValueFromBundle:bundle + forKey:kConfigServerClientIDKey]; + NSString *hostedDomain = [self configValueFromBundle:bundle forKey:kConfigHostedDomainKey]; + NSString *openIDRealm = [self configValueFromBundle:bundle forKey:kConfigOpenIDRealmKey]; + + // If we have at least a client ID, try to construct a configuration. + if (clientID) { + return [[self alloc] initWithClientID:clientID + serverClientID:serverClientID + hostedDomain:hostedDomain + openIDRealm:openIDRealm]; + } + + return nil; +} + // Extend NSObject's default description for easier debugging. - (NSString *)description { return [NSString stringWithFormat: diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 4b942ed9..a6c2a1e9 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -458,7 +458,7 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore { // If we have a bundle, try to set the active configuration from the bundle's Info.plist. if (bundle) { - _configuration = [GIDSignIn configurationFromBundle:bundle]; + _configuration = [GIDConfiguration configurationFromBundle:bundle]; } // Check to see if the 3P app is being run for the first time after a fresh install. @@ -1019,38 +1019,6 @@ - (GIDProfileData *)profileDataWithIDToken:(OIDIDToken *)idToken { imageURL:[NSURL URLWithString:idToken.claims[kBasicProfilePictureKey]]]; } -// Try to retrieve a configuration value from an |NSBundle|'s Info.plist for a given key. -+ (nullable NSString *)configValueFromBundle:(NSBundle *)bundle forKey:(NSString *)key { - NSString *value; - id configValue = [bundle objectForInfoDictionaryKey:key]; - if ([configValue isKindOfClass:[NSString class]]) { - value = configValue; - } - return value; -} - -// Try to generate a |GIDConfiguration| from an |NSBundle|'s Info.plist. -+ (nullable GIDConfiguration *)configurationFromBundle:(NSBundle *)bundle { - GIDConfiguration *configuration; - - // Retrieve any valid config parameters from the bundle's Info.plist. - NSString *clientID = [GIDSignIn configValueFromBundle:bundle forKey:kConfigClientIDKey]; - NSString *serverClientID = [GIDSignIn configValueFromBundle:bundle - forKey:kConfigServerClientIDKey]; - NSString *hostedDomain = [GIDSignIn configValueFromBundle:bundle forKey:kConfigHostedDomainKey]; - NSString *openIDRealm = [GIDSignIn configValueFromBundle:bundle forKey:kConfigOpenIDRealmKey]; - - // If we have at least a client ID, try to construct a configuration. - if (clientID) { - configuration = [[GIDConfiguration alloc] initWithClientID:clientID - serverClientID:serverClientID - hostedDomain:hostedDomain - openIDRealm:openIDRealm]; - } - - return configuration; -} - @end NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h index 4902fa37..1d331f26 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h @@ -71,6 +71,11 @@ NS_ASSUME_NONNULL_BEGIN hostedDomain:(nullable NSString *)hostedDomain openIDRealm:(nullable NSString *)openIDRealm NS_DESIGNATED_INITIALIZER; +/// Try to generate a |GIDConfiguration| from an |NSBundle|'s Info.plist. +/// +/// @param bundle The bundle to generate a configuration value. ++ (nullable instancetype)configurationFromBundle:(NSBundle *)bundle; + @end NS_ASSUME_NONNULL_END From 94a4175aaf41fca753fdea9917cdd5163773c594 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 18 Apr 2024 09:33:12 -0700 Subject: [PATCH 03/28] Implement default options creation methods. --- .../Sources/GIDSignInInternalOptions.m | 1 - .../Implementations/GIDVerifyAccountDetail.m | 78 +++++-------------- .../GoogleSignIn/GIDVerifyAccountDetail.h | 18 ----- 3 files changed, 20 insertions(+), 77 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignInInternalOptions.m b/GoogleSignIn/Sources/GIDSignInInternalOptions.m index 8be7223a..e60ce0c0 100644 --- a/GoogleSignIn/Sources/GIDSignInInternalOptions.m +++ b/GoogleSignIn/Sources/GIDSignInInternalOptions.m @@ -36,7 +36,6 @@ + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)con GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; if (options) { options->_interactive = YES; - options->_continuation = NO; options->_addScopesFlow = addScopesFlow; options->_configuration = configuration; options->_presentingViewController = presentingViewController; diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 9b7f58bc..97c31953 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -31,7 +31,10 @@ - (void)verifyAccountDetails:(NSArray *)accountDet presentingViewController:(UIViewController *)presentingViewController completion:(nullable void (^)(GIDVerifiedAccountDetailResult *_Nullable verifyResult, NSError *_Nullable error))completion { - // TODO(#383): Implement this method. + [self verifyAccountDetails:accountDetails + presentingViewController:presentingViewController + hint:nil + completion:completion]; } - (void)verifyAccountDetails:(NSArray *)accountDetails @@ -39,69 +42,28 @@ - (void)verifyAccountDetails:(NSArray *)accountDet hint:(nullable NSString *)hint completion:(nullable void (^)(GIDVerifiedAccountDetailResult *_Nullable verifyResult, NSError *_Nullable error))completion { - // TODO(#383): Implement this method. -} + // Get the bundle of the current executable. + NSBundle *bundle = NSBundle.mainBundle; -- (void)verifyAccountDetails:(NSArray *)accountDetails - presentingViewController:(UIViewController *)presentingViewController - hint:(nullable NSString *)hint - additionalScopes:(nullable NSArray *)additionalScopes - completion:(nullable void (^)(GIDVerifiedAccountDetailResult *_Nullable verifyResult, - NSError *_Nullable error))completion { - // TODO(#383): Implement this method. -} - -// Starts authorization flow using the provided options. -- (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions *)options { - if (!options.interactive) { - return; - } - - // Ensure that a configuration is set. - if (!_configuration) { - // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) - [NSException raise:NSInvalidArgumentException - format:@"No active configuration. Make sure GIDClientID is set in Info.plist."]; - return; + // If we have a bundle, try to set the active configuration from the bundle's Info.plist. + if (bundle) { + _configuration = [GIDConfiguration configurationFromBundle:bundle]; } - - // Explicitly throw exception for missing client ID here. This must come before - // scheme check because schemes rely on reverse client IDs. - [self assertValidParameters:options]; - - [self assertValidPresentingViewController:options]; - - // If the application does not support the required URL schemes tell the developer so. - GIDSignInCallbackSchemes *schemes = - [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; - NSArray *unsupportedSchemes = [schemes unsupportedSchemes]; - if (unsupportedSchemes.count != 0) { - // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) - [NSException raise:NSInvalidArgumentException - format:@"Your app is missing support for the following URL schemes: %@", - [unsupportedSchemes componentsJoinedByString:@", "]]; - } - // TODO(#397): Start the incremental authorization flow. -} -#pragma mark - Helpers + GIDSignInInternalOptions *options = + [GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration + presentingViewController:presentingViewController + loginHint:hint + addScopesFlow:YES + accountDetailsToVerify:accountDetails + verifyCompletion:completion]; -// Asserts the parameters being valid. -- (void)assertValidParameters:(GIDSignInInternalOptions *)options { - if (![options.configuration.clientID length]) { - // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) - [NSException raise:NSInvalidArgumentException - format:@"You must specify |clientID| in |GIDConfiguration|"]; - } + [self verifyAccountDetailsInteractivelyWithOptions:options]; } -// Assert that the presenting view controller has been set. -- (void)assertValidPresentingViewController:(GIDSignInInternalOptions *)options { - if (!options.presentingViewController) { - // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) - [NSException raise:NSInvalidArgumentException - format:@"|presentingViewController| must be set."]; - } +// Starts authorization flow using the provided options. +- (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions *)options { + // TODO(#397): Sanity checks and start the incremental authorization flow. } @end diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index 139d3fa8..f077be4d 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -72,24 +72,6 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve completion:(nullable void (^)(GIDVerifiedAccountDetailResult *_Nullable verifyResult, NSError *_Nullable error))completion; -/// Starts an interactive verification flow using the provided hint and additional scopes. -/// -/// The completion will be called at the end of this process. Any saved verification -/// state will be replaced by the result of this flow. -/// -/// @param accountDetails A list of verifiable account details. -/// @param presentingViewController The view controller used to present the flow. -/// @param hint An optional hint for the authorization server, for example the user's ID or email -/// address, to be prefilled if possible. -/// @param additionalScopes An optional array of scopes to request in addition to the basic profile scopes. -/// @param completion The optional block called asynchronously on the main queue upon completion. -- (void)verifyAccountDetails:(NSArray *)accountDetails - presentingViewController:(UIViewController *)presentingViewController - hint:(nullable NSString *)hint - additionalScopes:(nullable NSArray *)additionalScopes - completion:(nullable void (^)(GIDVerifiedAccountDetailResult *_Nullable verifyResult, - NSError *_Nullable error))completion; - @end NS_ASSUME_NONNULL_END From 4c2a6431162ae429edc3eb47603bd1c7f92da869 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 18 Apr 2024 16:14:23 -0700 Subject: [PATCH 04/28] Options validation. --- .../Implementations/GIDVerifyAccountDetail.m | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 97c31953..d98c14bb 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -63,7 +63,55 @@ - (void)verifyAccountDetails:(NSArray *)accountDet // Starts authorization flow using the provided options. - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions *)options { - // TODO(#397): Sanity checks and start the incremental authorization flow. + if (!options.interactive) { + return; + } + + // Ensure that a configuration is set. + if (!_configuration) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"No active configuration. Make sure GIDClientID is set in Info.plist."]; + return; + } + + // Explicitly throw exception for missing client ID here. This must come before + // scheme check because schemes rely on reverse client IDs. + [self assertValidParameters:options]; + + [self assertValidPresentingViewController:options]; + + // If the application does not support the required URL schemes tell the developer so. + GIDSignInCallbackSchemes *schemes = + [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; + NSArray *unsupportedSchemes = [schemes unsupportedSchemes]; + if (unsupportedSchemes.count != 0) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"Your app is missing support for the following URL schemes: %@", + [unsupportedSchemes componentsJoinedByString:@", "]]; + } + // TODO(#397): Start the incremental authorization flow. +} + +#pragma mark - Helpers + +// Asserts the parameters being valid. +- (void)assertValidParameters:(GIDSignInInternalOptions *)options { + if (![options.configuration.clientID length]) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"You must specify |clientID| in |GIDConfiguration|"]; + } +} + +// Assert that the presenting view controller has been set. +- (void)assertValidPresentingViewController:(GIDSignInInternalOptions *)options { + if (!options.presentingViewController) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"|presentingViewController| must be set."]; + } } @end From 78e175d2387b979fe2424a9c0b3c26df014b222f Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 25 Apr 2024 12:50:24 -0700 Subject: [PATCH 05/28] Add config initializers. --- .../Implementations/GIDVerifyAccountDetail.m | 31 ++++-- .../GoogleSignIn/GIDVerifyAccountDetail.h | 3 + .../Tests/Unit/GIDVerifyAccountDetailTest.m | 97 +++++++++++++++++++ 3 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index d98c14bb..0314c518 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -27,6 +27,29 @@ @implementation GIDVerifyAccountDetail +- (instancetype)initWithConfig:(GIDConfiguration *)configuration { + self = [super init]; + if (self) { + _configuration = configuration; + } + return self; +} + +- (instancetype)init { + GIDConfiguration *configuration; + // Get the bundle of the current executable. + NSBundle *bundle = NSBundle.mainBundle; + + // If we have a bundle, try to set the active configuration from the bundle's Info.plist. + if (bundle) { + configuration = [GIDConfiguration configurationFromBundle:bundle]; + } + + return [self initWithConfig:configuration]; +} + +#pragma mark - Public methods + - (void)verifyAccountDetails:(NSArray *)accountDetails presentingViewController:(UIViewController *)presentingViewController completion:(nullable void (^)(GIDVerifiedAccountDetailResult *_Nullable verifyResult, @@ -42,14 +65,6 @@ - (void)verifyAccountDetails:(NSArray *)accountDet hint:(nullable NSString *)hint completion:(nullable void (^)(GIDVerifiedAccountDetailResult *_Nullable verifyResult, NSError *_Nullable error))completion { - // Get the bundle of the current executable. - NSBundle *bundle = NSBundle.mainBundle; - - // If we have a bundle, try to set the active configuration from the bundle's Info.plist. - if (bundle) { - _configuration = [GIDConfiguration configurationFromBundle:bundle]; - } - GIDSignInInternalOptions *options = [GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration presentingViewController:presentingViewController diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index f077be4d..53d68e40 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -43,6 +43,9 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve /// The active configuration for this instance of `GIDVerifyAccountDetail`. @property(nonatomic, nullable) GIDConfiguration *configuration; +- (instancetype)initWithConfig:(GIDConfiguration *)config + NS_DESIGNATED_INITIALIZER; + /// Starts an interactive verification flow. /// /// The completion will be called at the end of this process. Any saved verification diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m new file mode 100644 index 00000000..f6545343 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -0,0 +1,97 @@ +#import + +#if TARGET_OS_IOS +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" + +#import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" + +static NSString * const kClientId = @"FakeClientID"; + +@interface GIDVerifyAccountDetailTests : XCTestCase { +@private + // Mock |UIViewController|. + UIViewController *_presentingViewController; + + // Fake [NSBundle mainBundle]; + GIDFakeMainBundle *_fakeMainBundle; + + // The |GIDVerifyAccountDetail| object being tested. + GIDVerifyAccountDetail *_verifyAccountDetail; + + // [comment] + NSArray *_verifiableAccountDetails; + + GIDConfiguration *_configuration; +} +@end + +@implementation GIDVerifyAccountDetailTests + +#pragma mark - Lifecycle + +- (void)setUp { + [super setUp]; + + _presentingViewController = [[UIViewController alloc] init]; + +// _verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + _verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + + GIDVerifiableAccountDetail *ageOver18Detail = [[GIDVerifiableAccountDetail alloc] initWithAccountDetailType:GIDAccountDetailTypeAgeOver18]; + _verifiableAccountDetails = @[ageOver18Detail]; + + _fakeMainBundle = [[GIDFakeMainBundle alloc] init]; + [_fakeMainBundle startFakingWithClientID:kClientId]; + [_fakeMainBundle fakeAllSchemesSupported]; +} + + +#pragma mark - Tests + +- (void)testPresentingViewControllerException { + _presentingViewController = nil; + + XCTAssertThrows([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]); +} + +- (void)testClientIDMissingException { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" + _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; +#pragma GCC diagnostic pop + BOOL threw = NO; + @try { + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]; + } @catch (NSException *exception) { + threw = YES; + XCTAssertEqualObjects(exception.description, + @"You must specify |clientID| in |GIDConfiguration|"); + } @finally { + } + XCTAssert(threw); +} + +- (void)testSchemesNotSupportedException { + [_fakeMainBundle fakeMissingAllSchemes]; + BOOL threw = NO; + @try { + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]; + } @catch (NSException *exception) { + threw = YES; + XCTAssertEqualObjects(exception.description, + @"Your app is missing support for the following URL schemes: " + "fakeclientid"); + } @finally { + } + XCTAssert(threw); +} + +@end + +#endif // TARGET_OS_IOS From a5b9a6163885df39f67800945abff5577d4d8dce Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 25 Apr 2024 14:50:17 -0700 Subject: [PATCH 06/28] Fix spacing. --- .../Implementations/GIDVerifyAccountDetail.m | 14 ++---- .../GoogleSignIn/GIDVerifyAccountDetail.h | 2 +- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 49 ++++++++++++------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 1a637f70..7598d456 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -38,10 +38,7 @@ - (instancetype)initWithConfig:(GIDConfiguration *)configuration { - (instancetype)init { GIDConfiguration *configuration; - // Get the bundle of the current executable. NSBundle *bundle = NSBundle.mainBundle; - - // If we have a bundle, try to set the active configuration from the bundle's Info.plist. if (bundle) { configuration = [GIDConfiguration configurationFromBundle:bundle]; } @@ -77,26 +74,25 @@ - (void)verifyAccountDetails:(NSArray *)accountDet [self verifyAccountDetailsInteractivelyWithOptions:options]; } -// Starts authorization flow using the provided options. - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions *)options { if (!options.interactive) { return; } - + // Ensure that a configuration is set. if (!_configuration) { // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) [NSException raise:NSInvalidArgumentException format:@"No active configuration. Make sure GIDClientID is set in Info.plist."]; - return; + return; } - + // Explicitly throw exception for missing client ID here. This must come before // scheme check because schemes rely on reverse client IDs. [self assertValidParameters:options]; - + [self assertValidPresentingViewController:options]; - + // If the application does not support the required URL schemes tell the developer so. GIDSignInCallbackSchemes *schemes = [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index 53d68e40..ff967ac8 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -44,7 +44,7 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve @property(nonatomic, nullable) GIDConfiguration *configuration; - (instancetype)initWithConfig:(GIDConfiguration *)config - NS_DESIGNATED_INITIALIZER; +NS_DESIGNATED_INITIALIZER; /// Starts an interactive verification flow. /// diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index f6545343..2d1de588 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -1,3 +1,17 @@ +// Copyright 2024 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 @@ -9,19 +23,17 @@ @interface GIDVerifyAccountDetailTests : XCTestCase { @private - // Mock |UIViewController|. + // The |UIViewController| object being tested. UIViewController *_presentingViewController; - // Fake [NSBundle mainBundle]; + // Fake [NSBundle mainBundle]. GIDFakeMainBundle *_fakeMainBundle; // The |GIDVerifyAccountDetail| object being tested. GIDVerifyAccountDetail *_verifyAccountDetail; - // [comment] + // The list of account details when testing [GIDVerifiableAccountDetail]. NSArray *_verifiableAccountDetails; - - GIDConfiguration *_configuration; } @end @@ -34,7 +46,6 @@ - (void)setUp { _presentingViewController = [[UIViewController alloc] init]; -// _verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; _verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; GIDVerifiableAccountDetail *ageOver18Detail = [[GIDVerifiableAccountDetail alloc] initWithAccountDetailType:GIDAccountDetailTypeAgeOver18]; @@ -59,20 +70,20 @@ - (void)testPresentingViewControllerException { - (void)testClientIDMissingException { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnonnull" - _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; + _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; #pragma GCC diagnostic pop - BOOL threw = NO; - @try { - [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil]; - } @catch (NSException *exception) { - threw = YES; - XCTAssertEqualObjects(exception.description, - @"You must specify |clientID| in |GIDConfiguration|"); - } @finally { - } - XCTAssert(threw); + BOOL threw = NO; + @try { + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]; + } @catch (NSException *exception) { + threw = YES; + XCTAssertEqualObjects(exception.description, + @"You must specify |clientID| in |GIDConfiguration|"); + } @finally { + } + XCTAssert(threw); } - (void)testSchemesNotSupportedException { From d70400a93098d3e1baf724f15cc04c43e47f0115 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 25 Apr 2024 15:23:37 -0700 Subject: [PATCH 07/28] Add import to use GIDAccountDetailTypeAgeOver18. --- .../Implementations/GIDVerifyAccountDetail.m | 2 ++ GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m | 1 + 2 files changed, 3 insertions(+) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 7598d456..8bfb4a61 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -74,6 +74,8 @@ - (void)verifyAccountDetails:(NSArray *)accountDet [self verifyAccountDetailsInteractivelyWithOptions:options]; } +#pragma mark - Authentication flow + - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions *)options { if (!options.interactive) { return; diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index 2d1de588..e83cfbb1 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -16,6 +16,7 @@ #if TARGET_OS_IOS #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" From f858d20104f665499ead2647cd643328ebf60740 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 25 Apr 2024 15:38:08 -0700 Subject: [PATCH 08/28] Import GIDConfiguration to test file. --- .../Implementations/GIDVerifyAccountDetail.m | 1 - GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 8bfb4a61..8cc5c438 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -16,7 +16,6 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" -#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiedAccountDetailResult.h" diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index e83cfbb1..2d41e199 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -15,6 +15,7 @@ #import #if TARGET_OS_IOS +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" From 4a97c00b861ff007e6146253fae1380f09e5f7ee Mon Sep 17 00:00:00 2001 From: brianna Date: Mon, 29 Apr 2024 15:52:07 -0700 Subject: [PATCH 09/28] Create OIDAuthorizationRequest. --- .../Implementations/GIDVerifyAccountDetail.m | 83 ++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 8cc5c438..7af2ee25 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -20,17 +20,59 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiedAccountDetailResult.h" +#import "GoogleSignIn/Sources/GIDEMMSupport.h" #import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" +#import "GoogleSignIn/Sources/GIDSignInPreferences.h" + +@import GTMAppAuth; + +#ifdef SWIFT_PACKAGE +@import AppAuth; +@import GTMSessionFetcherCore; +#else +#import +#import +#import +#endif #if TARGET_OS_IOS -@implementation GIDVerifyAccountDetail +// The URL template for the authorization endpoint. +static NSString *const kAuthorizationURLTemplate = @"https://%@/o/oauth2/v2/auth"; + +// The URL template for the token endpoint. +static NSString *const kTokenURLTemplate = @"https://%@/token"; + +// Expected path in the URL scheme to be handled. +static NSString *const kBrowserCallbackPath = @"/oauth2callback"; + +// The EMM support version +static NSString *const kEMMVersion = @"1"; + +// Parameters for the auth and token exchange endpoints. +static NSString *const kAudienceParameter = @"audience"; +static NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; +static NSString *const kLoginHintParameter = @"login_hint"; +static NSString *const kHostedDomainParameter = @"hd"; + +@implementation GIDVerifyAccountDetail { + // AppAuth configuration object. + OIDServiceConfiguration *_appAuthConfiguration; +} - (instancetype)initWithConfig:(GIDConfiguration *)configuration { self = [super init]; if (self) { _configuration = configuration; + + NSString *authorizationEndpointURL = [NSString stringWithFormat:kAuthorizationURLTemplate, + [GIDSignInPreferences googleAuthorizationServer]]; + NSString *tokenEndpointURL = [NSString stringWithFormat:kTokenURLTemplate, + [GIDSignInPreferences googleTokenServer]]; + _appAuthConfiguration = [[OIDServiceConfiguration alloc] + initWithAuthorizationEndpoint:[NSURL URLWithString:authorizationEndpointURL] + tokenEndpoint:[NSURL URLWithString:tokenEndpointURL]]; } return self; } @@ -104,7 +146,44 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * format:@"Your app is missing support for the following URL schemes: %@", [unsupportedSchemes componentsJoinedByString:@", "]]; } - // TODO(#397): Start the incremental authorization flow. + NSURL *redirectURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", + [schemes clientIdentifierScheme], + kBrowserCallbackPath]]; + + NSMutableDictionary *additionalParameters = [@{} mutableCopy]; + additionalParameters[kIncludeGrantedScopesParameter] = @"true"; + if (options.configuration.serverClientID) { + additionalParameters[kAudienceParameter] = options.configuration.serverClientID; + } + if (options.loginHint) { + additionalParameters[kLoginHintParameter] = options.loginHint; + } + if (options.configuration.hostedDomain) { + additionalParameters[kHostedDomainParameter] = options.configuration.hostedDomain; + } + + [additionalParameters addEntriesFromDictionary: + [GIDEMMSupport parametersWithParameters:options.extraParams + emmSupport:kEMMVersion + isPasscodeInfoRequired:NO]]; + additionalParameters[kSDKVersionLoggingParameter] = GIDVersion(); + additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment(); + + NSMutableArray *scopes; + for (GIDVerifiableAccountDetail *detail in options.accountDetailsToVerify) { + NSString *scopeString = [detail scope]; + if (scopeString) { + [scopes addObject:scopeString]; + } + } + + OIDAuthorizationRequest *request = + [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration + clientId:options.configuration.clientID + scopes:scopes + redirectURL:redirectURL + responseType:OIDResponseTypeCode + additionalParameters:additionalParameters]; } #pragma mark - Helpers From c4d0a163a4c46bc8fdca95a26132172488a9c797 Mon Sep 17 00:00:00 2001 From: brianna Date: Tue, 30 Apr 2024 14:03:25 -0700 Subject: [PATCH 10/28] Add tests for config initializers. --- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index 2d41e199..bca49f74 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -22,6 +22,9 @@ #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" static NSString * const kClientId = @"FakeClientID"; +static NSString * const kServerClientId = @"FakeServerClientID"; +static NSString * const kOpenIDRealm = @"FakeRealm"; +static NSString * const kFakeHostedDomain = @"fakehosteddomain.com"; @interface GIDVerifyAccountDetailTests : XCTestCase { @private @@ -61,6 +64,48 @@ - (void)setUp { #pragma mark - Tests +- (void)testInit { + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + XCTAssertNotNil(verifyAccountDetail.configuration); + XCTAssertEqual(verifyAccountDetail.configuration.clientID, kClientId); + XCTAssertNil(verifyAccountDetail.configuration.serverClientID); + XCTAssertNil(verifyAccountDetail.configuration.hostedDomain); + XCTAssertNil(verifyAccountDetail.configuration.openIDRealm); + +} + +- (void)testInit_noConfig { + [_fakeMainBundle fakeWithClientID:nil + serverClientID:nil + hostedDomain:nil + openIDRealm:nil]; + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + XCTAssertNil(verifyAccountDetail.configuration); +} + + +- (void)testInit_fullConfig { + [_fakeMainBundle fakeWithClientID:kClientId + serverClientID:kServerClientId + hostedDomain:kFakeHostedDomain + openIDRealm:kOpenIDRealm]; + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + XCTAssertNotNil(verifyAccountDetail.configuration); + XCTAssertEqual(verifyAccountDetail.configuration.clientID, kClientId); + XCTAssertEqual(verifyAccountDetail.configuration.serverClientID, kServerClientId); + XCTAssertEqual(verifyAccountDetail.configuration.hostedDomain, kFakeHostedDomain); + XCTAssertEqual(verifyAccountDetail.configuration.openIDRealm, kOpenIDRealm); +} + +- (void)testInit_invalidConfig { + [_fakeMainBundle fakeWithClientID:@[ @"bad", @"config", @"values" ] + serverClientID:nil + hostedDomain:nil + openIDRealm:nil]; + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + XCTAssertNil(verifyAccountDetail.configuration); +} + - (void)testPresentingViewControllerException { _presentingViewController = nil; From e04a1ea934dd56d49e5dd26651d3a0f6396306d8 Mon Sep 17 00:00:00 2001 From: brianna Date: Wed, 1 May 2024 13:15:56 -0700 Subject: [PATCH 11/28] Add in initializer with config tests. --- .../Implementations/GIDVerifyAccountDetail.m | 2 +- .../GoogleSignIn/GIDVerifyAccountDetail.h | 2 +- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 93 +++++++++++++------ 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 8cc5c438..940097a6 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -27,7 +27,7 @@ @implementation GIDVerifyAccountDetail -- (instancetype)initWithConfig:(GIDConfiguration *)configuration { +- (instancetype)initWithConfig:(nullable GIDConfiguration *)configuration { self = [super init]; if (self) { _configuration = configuration; diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index ff967ac8..424124a2 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -43,7 +43,7 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve /// The active configuration for this instance of `GIDVerifyAccountDetail`. @property(nonatomic, nullable) GIDConfiguration *configuration; -- (instancetype)initWithConfig:(GIDConfiguration *)config +- (instancetype)initWithConfig:(nullable GIDConfiguration *)config NS_DESIGNATED_INITIALIZER; /// Starts an interactive verification flow. diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index 2d41e199..cbc98976 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -22,6 +22,9 @@ #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" static NSString * const kClientId = @"FakeClientID"; +static NSString * const kServerClientId = @"FakeServerClientID"; +static NSString * const kOpenIDRealm = @"FakeRealm"; +static NSString * const kFakeHostedDomain = @"fakehosteddomain.com"; @interface GIDVerifyAccountDetailTests : XCTestCase { @private @@ -54,13 +57,61 @@ - (void)setUp { _verifiableAccountDetails = @[ageOver18Detail]; _fakeMainBundle = [[GIDFakeMainBundle alloc] init]; - [_fakeMainBundle startFakingWithClientID:kClientId]; - [_fakeMainBundle fakeAllSchemesSupported]; } #pragma mark - Tests +- (void)testInit { + [_fakeMainBundle startFakingWithClientID:kClientId]; + + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + XCTAssertNotNil(verifyAccountDetail.configuration); + XCTAssertEqual(verifyAccountDetail.configuration.clientID, kClientId); + XCTAssertNil(verifyAccountDetail.configuration.serverClientID); + XCTAssertNil(verifyAccountDetail.configuration.hostedDomain); + XCTAssertNil(verifyAccountDetail.configuration.openIDRealm); + +} + +- (void)testInit_noConfig { + [_fakeMainBundle startFakingWithClientID:kClientId]; + [_fakeMainBundle fakeWithClientID:nil + serverClientID:nil + hostedDomain:nil + openIDRealm:nil]; + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + + XCTAssertNil(verifyAccountDetail.configuration); +} + + +- (void)testInit_fullConfig { + [_fakeMainBundle startFakingWithClientID:kClientId]; + [_fakeMainBundle fakeWithClientID:kClientId + serverClientID:kServerClientId + hostedDomain:kFakeHostedDomain + openIDRealm:kOpenIDRealm]; + + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + XCTAssertNotNil(verifyAccountDetail.configuration); + XCTAssertEqual(verifyAccountDetail.configuration.clientID, kClientId); + XCTAssertEqual(verifyAccountDetail.configuration.serverClientID, kServerClientId); + XCTAssertEqual(verifyAccountDetail.configuration.hostedDomain, kFakeHostedDomain); + XCTAssertEqual(verifyAccountDetail.configuration.openIDRealm, kOpenIDRealm); +} + +- (void)testInit_invalidConfig { + [_fakeMainBundle startFakingWithClientID:kClientId]; + [_fakeMainBundle fakeWithClientID:@[ @"bad", @"config", @"values" ] + serverClientID:nil + hostedDomain:nil + openIDRealm:nil]; + + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; + XCTAssertNil(verifyAccountDetail.configuration); +} + - (void)testPresentingViewControllerException { _presentingViewController = nil; @@ -74,35 +125,21 @@ - (void)testClientIDMissingException { #pragma GCC diagnostic ignored "-Wnonnull" _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; #pragma GCC diagnostic pop - BOOL threw = NO; - @try { - [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil]; - } @catch (NSException *exception) { - threw = YES; - XCTAssertEqualObjects(exception.description, - @"You must specify |clientID| in |GIDConfiguration|"); - } @finally { - } - XCTAssert(threw); + + XCTAssertThrowsSpecificNamed( + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController completion:nil], + NSException, + NSInvalidArgumentException, + @"You must specify |clientID| in |GIDConfiguration|"); } - (void)testSchemesNotSupportedException { - [_fakeMainBundle fakeMissingAllSchemes]; - BOOL threw = NO; - @try { - [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil]; - } @catch (NSException *exception) { - threw = YES; - XCTAssertEqualObjects(exception.description, - @"Your app is missing support for the following URL schemes: " - "fakeclientid"); - } @finally { - } - XCTAssert(threw); + XCTAssertThrowsSpecificNamed( + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController completion:nil], + NSException, + NSInvalidArgumentException, + @"Your app is missing support for the following URL schemes: " + "fakeclientid"); } @end From 93fb453e6ced7a3a75e0b0d00d2cd39a4837d12f Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 2 May 2024 10:26:23 -0700 Subject: [PATCH 12/28] Make used variables properties. --- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index cbc98976..46337649 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -26,20 +26,18 @@ static NSString * const kOpenIDRealm = @"FakeRealm"; static NSString * const kFakeHostedDomain = @"fakehosteddomain.com"; -@interface GIDVerifyAccountDetailTests : XCTestCase { -@private - // The |UIViewController| object being tested. - UIViewController *_presentingViewController; +@interface GIDVerifyAccountDetailTests : XCTestCase +// The |UIViewController| object being tested. +@property UIViewController *presentingViewController; - // Fake [NSBundle mainBundle]. - GIDFakeMainBundle *_fakeMainBundle; +// Fake [NSBundle mainBundle]. +@property GIDFakeMainBundle *fakeMainBundle; - // The |GIDVerifyAccountDetail| object being tested. - GIDVerifyAccountDetail *_verifyAccountDetail; +// The |GIDVerifyAccountDetail| object being tested. +@property GIDVerifyAccountDetail *verifyAccountDetail; - // The list of account details when testing [GIDVerifiableAccountDetail]. - NSArray *_verifiableAccountDetails; -} +// The list of account details when testing [GIDVerifiableAccountDetail]. +@property NSArray *verifiableAccountDetails; @end @implementation GIDVerifyAccountDetailTests @@ -71,7 +69,6 @@ - (void)testInit { XCTAssertNil(verifyAccountDetail.configuration.serverClientID); XCTAssertNil(verifyAccountDetail.configuration.hostedDomain); XCTAssertNil(verifyAccountDetail.configuration.openIDRealm); - } - (void)testInit_noConfig { From 066fa07f5b09b03ad72c19a4082e2168b660fe69 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 2 May 2024 15:39:52 -0700 Subject: [PATCH 13/28] Add TODO for request/response handling tests. --- GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index 46337649..d7c6d87f 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -109,6 +109,8 @@ - (void)testInit_invalidConfig { XCTAssertNil(verifyAccountDetail.configuration); } +// TODO(#405): Write tests for request and response handling. + - (void)testPresentingViewControllerException { _presentingViewController = nil; From dc6560b7e569615b72f212572cf572b5d4ebb9d3 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 2 May 2024 18:18:38 -0700 Subject: [PATCH 14/28] Exclude MacOS for `GIDEMMSupport` use. --- .../Implementations/GIDVerifyAccountDetail.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 2ff65fd2..45598e30 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -36,7 +36,7 @@ #import #endif -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST // The URL template for the authorization endpoint. static NSString *const kAuthorizationURLTemplate = @"https://%@/o/oauth2/v2/auth"; @@ -208,4 +208,4 @@ - (void)assertValidPresentingViewController:(GIDSignInInternalOptions *)options @end -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST From fa7845ccfbd65f0abefad46cb7cdbd7a97b56122 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 2 May 2024 18:42:39 -0700 Subject: [PATCH 15/28] Silence unused 'request' variable for now until response is implemented. --- .../Implementations/GIDVerifyAccountDetail.m | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 45598e30..6bdae75f 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -177,13 +177,14 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * } } - OIDAuthorizationRequest *request = - [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration - clientId:options.configuration.clientID - scopes:scopes - redirectURL:redirectURL - responseType:OIDResponseTypeCode - additionalParameters:additionalParameters]; + // TODO(#405): Use request variable to present request and process response. + __unused OIDAuthorizationRequest *request = + [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration + clientId:options.configuration.clientID + scopes:scopes + redirectURL:redirectURL + responseType:OIDResponseTypeCode + additionalParameters:additionalParameters]; } #pragma mark - Helpers From 8bfd659eb794fa74c8967923ebe873dfe3c9c0f0 Mon Sep 17 00:00:00 2001 From: brianna Date: Tue, 7 May 2024 15:02:53 -0700 Subject: [PATCH 16/28] Add tests for config initializer and current user exception. --- .../Implementations/GIDVerifyAccountDetail.m | 11 +++ .../Tests/Unit/GIDVerifyAccountDetailTest.m | 85 +++++++++++++++++-- 2 files changed, 88 insertions(+), 8 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 940097a6..72b9bc83 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -88,6 +88,8 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * return; } + [self assertValidCurrentUser]; + // Explicitly throw exception for missing client ID here. This must come before // scheme check because schemes rely on reverse client IDs. [self assertValidParameters:options]; @@ -109,6 +111,15 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * #pragma mark - Helpers +// Assert that a current user exists. +- (void)assertValidCurrentUser { + if (!GIDSignIn.sharedInstance.currentUser) { + // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) + [NSException raise:NSInvalidArgumentException + format:@"|currentUser| must be set to verify."]; + } +} + // Asserts the parameters being valid. - (void)assertValidParameters:(GIDSignInInternalOptions *)options { if (![options.configuration.clientID length]) { diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index 46337649..c7c14cdb 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -19,7 +19,11 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" +#import "GoogleSignIn/Sources/GIDSignIn_Private.h" +#import "GoogleSignIn/Sources/GIDGoogleUser_Private.h" + #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" +#import "GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h" static NSString * const kClientId = @"FakeClientID"; static NSString * const kServerClientId = @"FakeServerClientID"; @@ -51,7 +55,9 @@ - (void)setUp { _verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; - GIDVerifiableAccountDetail *ageOver18Detail = [[GIDVerifiableAccountDetail alloc] initWithAccountDetailType:GIDAccountDetailTypeAgeOver18]; + GIDVerifiableAccountDetail *ageOver18Detail = [[GIDVerifiableAccountDetail alloc] + initWithAccountDetailType: + GIDAccountDetailTypeAgeOver18]; _verifiableAccountDetails = @[ageOver18Detail]; _fakeMainBundle = [[GIDFakeMainBundle alloc] init]; @@ -109,12 +115,60 @@ - (void)testInit_invalidConfig { XCTAssertNil(verifyAccountDetail.configuration); } +- (void)testInitWithConfig_noConfig { + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] initWithConfig:nil]; + XCTAssertNil(verifyAccountDetail.configuration); +} + +- (void)testInitWithConfig_fullConfig { + GIDConfiguration *configuration = [[GIDConfiguration alloc] initWithClientID:kClientId + serverClientID:kServerClientId + hostedDomain:kFakeHostedDomain + openIDRealm:kOpenIDRealm]; + + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] + initWithConfig:configuration]; + XCTAssertNotNil(verifyAccountDetail.configuration); + XCTAssertEqual(verifyAccountDetail.configuration.clientID, kClientId); + XCTAssertEqual(verifyAccountDetail.configuration.serverClientID, kServerClientId); + XCTAssertEqual(verifyAccountDetail.configuration.hostedDomain, kFakeHostedDomain); + XCTAssertEqual(verifyAccountDetail.configuration.openIDRealm, kOpenIDRealm); +} + +- (void)testCurrentUserException { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" + _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; +#pragma GCC diagnostic pop + + OIDAuthState *authState = [OIDAuthState testInstance]; + GIDSignIn.sharedInstance.currentUser = nil; + + XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil], + NSException, + NSInvalidArgumentException, + @"|currentUser| must be set to verify."); +} + - (void)testPresentingViewControllerException { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" + _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:kClientId]; +#pragma GCC diagnostic pop _presentingViewController = nil; - XCTAssertThrows([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil]); + OIDAuthState *authState = [OIDAuthState testInstance]; + GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; + + XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil], + NSException, + NSInvalidArgumentException, + @"|presentingViewController| must be set."); } - (void)testClientIDMissingException { @@ -123,16 +177,31 @@ - (void)testClientIDMissingException { _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; #pragma GCC diagnostic pop - XCTAssertThrowsSpecificNamed( - [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController completion:nil], + OIDAuthState *authState = [OIDAuthState testInstance]; + GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; + + XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil], NSException, NSInvalidArgumentException, @"You must specify |clientID| in |GIDConfiguration|"); } - (void)testSchemesNotSupportedException { - XCTAssertThrowsSpecificNamed( - [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController completion:nil], +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" + _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:kClientId]; +#pragma GCC diagnostic pop + + OIDAuthState *authState = [OIDAuthState testInstance]; + GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; + + XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil], NSException, NSInvalidArgumentException, @"Your app is missing support for the following URL schemes: " From 9376a4b7904f7fb364852f28a1114607498be528 Mon Sep 17 00:00:00 2001 From: brianna Date: Tue, 7 May 2024 17:41:48 -0700 Subject: [PATCH 17/28] Create fake main bundle initializer and modify tests. --- GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h | 9 ++- GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m | 31 ++++++++-- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 62 +++++++++++-------- 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h index 3086880e..559cfbb7 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h @@ -22,12 +22,19 @@ */ @interface GIDFakeMainBundle : NSObject +- (instancetype)initWithClientID:(id)clientID + serverClientID:(id)serverClientID + hostedDomain:(id)hostedDomain + openIDRealm:(id)openIDRealm; + +- (void)startFaking; + /** * @fn startFakingWithClientID: * @brief Starts faking [NSBundle mainBundle] * @param clientID The fake client idenfitier for the app. */ -- (void)startFakingWithClientID:(NSString *)clientID; +- (void)startFakingWithClientID:(nullable NSString *)clientID; /** * @fn stopFaking diff --git a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m index d017e60c..e66c29df 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m @@ -37,16 +37,31 @@ @implementation GIDFakeMainBundle { NSMutableDictionary *_fakeConfig; } -- (void)startFakingWithClientID:(NSString *)clientId { - _clientId = clientId; +- (instancetype)initWithClientID:(id)clientID + serverClientID:(id)serverClientID + hostedDomain:(id)hostedDomain + openIDRealm:(id)openIDRealm { + self = [super init]; + + if (self) { + _clientId = clientID; + + _fakeConfig = clientID ? [@{ @"GIDClientID" : clientID } mutableCopy] : [@{} mutableCopy]; + + _fakeConfig[kConfigClientIDKey] = clientID; + _fakeConfig[kConfigServerClientIDKey] = serverClientID; + _fakeConfig[kConfigHostedDomainKey] = hostedDomain; + _fakeConfig[kConfigOpenIDRealmKey] = openIDRealm; + } + return self; +} +- (void)startFaking { _fakedKeys = @[ kCFBundleURLTypesKey, kConfigClientIDKey, kConfigServerClientIDKey, kConfigHostedDomainKey, kConfigOpenIDRealmKey ]; - - _fakeConfig = [@{ @"GIDClientID" : clientId } mutableCopy]; [GULSwizzler swizzleClass:[NSBundle class] selector:@selector(objectForInfoDictionaryKey:) @@ -62,6 +77,14 @@ - (void)startFakingWithClientID:(NSString *)clientId { }]; } +- (void)startFakingWithClientID:(nullable NSString *)clientId { + _clientId = clientId; + + _fakeConfig = clientId ? [@{ @"GIDClientID" : clientId } mutableCopy] : [@{} mutableCopy]; + + [self startFaking]; +} + - (void)stopFaking { [GULSwizzler unswizzleClass:[NSBundle class] selector:@selector(objectForInfoDictionaryKey:) diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index c7c14cdb..ea642f04 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -25,6 +25,12 @@ #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" #import "GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h" +#ifdef SWIFT_PACKAGE +@import OCMock; +#else +#import +#endif + static NSString * const kClientId = @"FakeClientID"; static NSString * const kServerClientId = @"FakeServerClientID"; static NSString * const kOpenIDRealm = @"FakeRealm"; @@ -60,7 +66,10 @@ - (void)setUp { GIDAccountDetailTypeAgeOver18]; _verifiableAccountDetails = @[ageOver18Detail]; - _fakeMainBundle = [[GIDFakeMainBundle alloc] init]; + _fakeMainBundle = [[GIDFakeMainBundle alloc] initWithClientID:kClientId + serverClientID:kServerClientId + hostedDomain:kFakeHostedDomain + openIDRealm:kOpenIDRealm]; } @@ -78,11 +87,7 @@ - (void)testInit { } - (void)testInit_noConfig { - [_fakeMainBundle startFakingWithClientID:kClientId]; - [_fakeMainBundle fakeWithClientID:nil - serverClientID:nil - hostedDomain:nil - openIDRealm:nil]; + [_fakeMainBundle startFakingWithClientID:nil]; GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; XCTAssertNil(verifyAccountDetail.configuration); @@ -90,11 +95,7 @@ - (void)testInit_noConfig { - (void)testInit_fullConfig { - [_fakeMainBundle startFakingWithClientID:kClientId]; - [_fakeMainBundle fakeWithClientID:kClientId - serverClientID:kServerClientId - hostedDomain:kFakeHostedDomain - openIDRealm:kOpenIDRealm]; + [_fakeMainBundle startFaking]; GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; XCTAssertNotNil(verifyAccountDetail.configuration); @@ -105,11 +106,12 @@ - (void)testInit_fullConfig { } - (void)testInit_invalidConfig { - [_fakeMainBundle startFakingWithClientID:kClientId]; - [_fakeMainBundle fakeWithClientID:@[ @"bad", @"config", @"values" ] - serverClientID:nil - hostedDomain:nil - openIDRealm:nil]; + _fakeMainBundle = [[GIDFakeMainBundle alloc] initWithClientID:@[ @"bad", @"config", @"values" ] + serverClientID:nil + hostedDomain:nil + openIDRealm:nil]; + [_fakeMainBundle startFaking]; + GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; XCTAssertNil(verifyAccountDetail.configuration); @@ -127,7 +129,7 @@ - (void)testInitWithConfig_fullConfig { openIDRealm:kOpenIDRealm]; GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] - initWithConfig:configuration]; + initWithConfig:configuration]; XCTAssertNotNil(verifyAccountDetail.configuration); XCTAssertEqual(verifyAccountDetail.configuration.clientID, kClientId); XCTAssertEqual(verifyAccountDetail.configuration.serverClientID, kServerClientId); @@ -142,7 +144,7 @@ - (void)testCurrentUserException { #pragma GCC diagnostic pop OIDAuthState *authState = [OIDAuthState testInstance]; - GIDSignIn.sharedInstance.currentUser = nil; +// GIDSignIn.sharedInstance.currentUser = nil; XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController @@ -160,8 +162,16 @@ - (void)testPresentingViewControllerException { _presentingViewController = nil; OIDAuthState *authState = [OIDAuthState testInstance]; - GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState - profileData:nil]; +// GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState +// profileData:nil]; + +// GIDSignIn *signIn = [[GIDSignIn alloc] initPrivate]; + id signIn = OCMClassMock([GIDSignIn class]); + OCMStub([signIn sharedInstance]).andReturn(signIn); + + GIDGoogleUser *currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; + OCMStub([signIn currentUser]).andReturn(currentUser); XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController @@ -177,9 +187,9 @@ - (void)testClientIDMissingException { _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; #pragma GCC diagnostic pop - OIDAuthState *authState = [OIDAuthState testInstance]; - GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState - profileData:nil]; +// OIDAuthState *authState = [OIDAuthState testInstance]; +// GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState +// profileData:nil]; XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController @@ -195,9 +205,9 @@ - (void)testSchemesNotSupportedException { _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:kClientId]; #pragma GCC diagnostic pop - OIDAuthState *authState = [OIDAuthState testInstance]; - GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState - profileData:nil]; +// OIDAuthState *authState = [OIDAuthState testInstance]; +// GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState +// profileData:nil]; XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails presentingViewController:_presentingViewController From 4cebc057ffc001435e3390d044ec38b1d55b9a51 Mon Sep 17 00:00:00 2001 From: brianna Date: Wed, 8 May 2024 15:20:12 -0700 Subject: [PATCH 18/28] Remove Emm flow support and move GIDSignIn strings to avoid repeated code. --- GoogleSignIn/Sources/GIDGoogleUser.m | 4 ---- GoogleSignIn/Sources/GIDSignIn.m | 8 -------- .../Implementations/GIDVerifyAccountDetail.m | 19 ++----------------- .../Sources/Public/GoogleSignIn/GIDSignIn.h | 8 ++++++++ 4 files changed, 10 insertions(+), 29 deletions(-) diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index ec300839..466d7bef 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -43,10 +43,6 @@ static NSString *const kProfileDataKey = @"profileData"; static NSString *const kAuthStateKey = @"authState"; -// Parameters for the token exchange endpoint. -static NSString *const kAudienceParameter = @"audience"; -static NSString *const kOpenIDRealmParameter = @"openid.realm"; - // Additional parameter names for EMM. static NSString *const kEMMSupportParameterName = @"emm_support"; diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 8ad38645..6d82a713 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -124,14 +124,6 @@ // The delay before the new sign-in flow can be presented after the existing one is cancelled. static const NSTimeInterval kPresentationDelayAfterCancel = 1.0; -// Parameters for the auth and token exchange endpoints. -static NSString *const kAudienceParameter = @"audience"; -// See b/11669751 . -static NSString *const kOpenIDRealmParameter = @"openid.realm"; -static NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; -static NSString *const kLoginHintParameter = @"login_hint"; -static NSString *const kHostedDomainParameter = @"hd"; - // Minimum time to expiration for a restored access token. static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0; diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 6bdae75f..96733983 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -20,7 +20,6 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiedAccountDetailResult.h" -#import "GoogleSignIn/Sources/GIDEMMSupport.h" #import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" #import "GoogleSignIn/Sources/GIDSignInPreferences.h" @@ -47,15 +46,6 @@ // Expected path in the URL scheme to be handled. static NSString *const kBrowserCallbackPath = @"/oauth2callback"; -// The EMM support version -static NSString *const kEMMVersion = @"1"; - -// Parameters for the auth and token exchange endpoints. -static NSString *const kAudienceParameter = @"audience"; -static NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; -static NSString *const kLoginHintParameter = @"login_hint"; -static NSString *const kHostedDomainParameter = @"hd"; - @implementation GIDVerifyAccountDetail { // AppAuth configuration object. OIDServiceConfiguration *_appAuthConfiguration; @@ -151,7 +141,7 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * kBrowserCallbackPath]]; NSMutableDictionary *additionalParameters = [@{} mutableCopy]; - additionalParameters[kIncludeGrantedScopesParameter] = @"true"; + additionalParameters[kIncludeGrantedScopesParameter] = @"false"; if (options.configuration.serverClientID) { additionalParameters[kAudienceParameter] = options.configuration.serverClientID; } @@ -161,11 +151,6 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * if (options.configuration.hostedDomain) { additionalParameters[kHostedDomainParameter] = options.configuration.hostedDomain; } - - [additionalParameters addEntriesFromDictionary: - [GIDEMMSupport parametersWithParameters:options.extraParams - emmSupport:kEMMVersion - isPasscodeInfoRequired:NO]]; additionalParameters[kSDKVersionLoggingParameter] = GIDVersion(); additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment(); @@ -179,7 +164,7 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * // TODO(#405): Use request variable to present request and process response. __unused OIDAuthorizationRequest *request = - [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration + [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration clientId:options.configuration.clientID scopes:scopes redirectURL:redirectURL diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h index 2576b13d..15068513 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h @@ -29,6 +29,14 @@ NS_ASSUME_NONNULL_BEGIN +// Parameters for the auth and token exchange endpoints. +static NSString *const kAudienceParameter = @"audience"; +// See b/11669751 . +static NSString *const kOpenIDRealmParameter = @"openid.realm"; +static NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; +static NSString *const kLoginHintParameter = @"login_hint"; +static NSString *const kHostedDomainParameter = @"hd"; + /// The error domain for `NSError`s returned by the Google Sign-In SDK. extern NSErrorDomain const kGIDSignInErrorDomain; From 51c5a368c1c43c9c850a0eb2b4975588305bed00 Mon Sep 17 00:00:00 2001 From: brianna Date: Wed, 8 May 2024 16:30:06 -0700 Subject: [PATCH 19/28] Unblock testing in GIDVerifyAccountDetailTest by changing GIDSignInTest strict mocks to less restrictive. Also, fix nullability warnings in GIDFakeMainBundle. --- GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h | 28 +++-- GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m | 16 +-- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 4 +- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 111 +++++++++--------- 4 files changed, 85 insertions(+), 74 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h index 559cfbb7..cea717d6 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h @@ -22,11 +22,23 @@ */ @interface GIDFakeMainBundle : NSObject -- (instancetype)initWithClientID:(id)clientID - serverClientID:(id)serverClientID - hostedDomain:(id)hostedDomain - openIDRealm:(id)openIDRealm; +/** + * @fn initWithClientID:serverClientID:hostedDomain:openIDRealm: + * @brief Initializes a GIDFakeMainBundle object. + * @param clientID The fake client idenfitier for the app. + * @param serverClientID The fake server client idenfitier for the app. + * @param hostedDomain The fake hosted domain for the app. + * @param openIDRealm The fake OpenID realm for the app. + */ +- (nullable instancetype)initWithClientID:(nullable id)clientID + serverClientID:(nullable id)serverClientID + hostedDomain:(nullable id)hostedDomain + openIDRealm:(nullable id)openIDRealm; +/** + * @fn startFaking: + * @brief Starts faking [NSBundle mainBundle] + */ - (void)startFaking; /** @@ -94,9 +106,9 @@ * @param hostedDomain The fake hosted domain for the app. * @param openIDRealm The fake OpenID realm for the app. */ -- (void)fakeWithClientID:(id)clientID - serverClientID:(id)serverClientID - hostedDomain:(id)hostedDomain - openIDRealm:(id)openIDRealm; +- (void)fakeWithClientID:(nullable id)clientID + serverClientID:(nullable id)serverClientID + hostedDomain:(nullable id)hostedDomain + openIDRealm:(nullable id)openIDRealm; @end diff --git a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m index e66c29df..c4d11a12 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m @@ -37,10 +37,10 @@ @implementation GIDFakeMainBundle { NSMutableDictionary *_fakeConfig; } -- (instancetype)initWithClientID:(id)clientID - serverClientID:(id)serverClientID - hostedDomain:(id)hostedDomain - openIDRealm:(id)openIDRealm { +- (nullable instancetype)initWithClientID:(nullable id)clientID + serverClientID:(nullable id)serverClientID + hostedDomain:(nullable id)hostedDomain + openIDRealm:(nullable id)openIDRealm { self = [super init]; if (self) { @@ -48,10 +48,10 @@ - (instancetype)initWithClientID:(id)clientID _fakeConfig = clientID ? [@{ @"GIDClientID" : clientID } mutableCopy] : [@{} mutableCopy]; - _fakeConfig[kConfigClientIDKey] = clientID; - _fakeConfig[kConfigServerClientIDKey] = serverClientID; - _fakeConfig[kConfigHostedDomainKey] = hostedDomain; - _fakeConfig[kConfigOpenIDRealmKey] = openIDRealm; + [self fakeWithClientID:clientID + serverClientID:serverClientID + hostedDomain:hostedDomain + openIDRealm:openIDRealm]; } return self; } diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index c64f1611..7fed4c13 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -286,12 +286,12 @@ - (void)setUp { #elif TARGET_OS_OSX _presentingWindow = OCMStrictClassMock([NSWindow class]); #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST - _authState = OCMStrictClassMock([OIDAuthState class]); + _authState = OCMClassMock([OIDAuthState class]); OCMStub([_authState alloc]).andReturn(_authState); OCMStub([_authState initWithAuthorizationResponse:OCMOCK_ANY]).andReturn(_authState); _tokenResponse = OCMStrictClassMock([OIDTokenResponse class]); _tokenRequest = OCMStrictClassMock([OIDTokenRequest class]); - _authorization = OCMStrictClassMock([GTMAuthSession class]); + _authorization = OCMClassMock([GTMAuthSession class]); _keychainStore = OCMStrictClassMock([GTMKeychainStore class]); OCMStub( [_keychainStore retrieveAuthSessionWithItemName:OCMOCK_ANY error:OCMArg.anyObjectRef] diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index ea642f04..d1a2f772 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -25,11 +25,15 @@ #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h" #import "GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h" -#ifdef SWIFT_PACKAGE -@import OCMock; -#else -#import -#endif +// Exception Reasons +static NSString * const kSchemesNotSupportedExceptionReason = + @"Your app is missing support for the following URL schemes: fakeclientid"; +static NSString * const kClientIDMissingExceptionReason = + @"You must specify |clientID| in |GIDConfiguration|"; +static NSString * const kMissingCurrentUserExceptionReason = + @"|currentUser| must be set to verify."; +static NSString * const kMissingPresentingViewControllerExceptionReason = + @"|presentingViewController| must be set."; static NSString * const kClientId = @"FakeClientID"; static NSString * const kServerClientId = @"FakeServerClientID"; @@ -61,9 +65,8 @@ - (void)setUp { _verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; - GIDVerifiableAccountDetail *ageOver18Detail = [[GIDVerifiableAccountDetail alloc] - initWithAccountDetailType: - GIDAccountDetailTypeAgeOver18]; + GIDVerifiableAccountDetail *ageOver18Detail = + [[GIDVerifiableAccountDetail alloc] initWithAccountDetailType:GIDAccountDetailTypeAgeOver18]; _verifiableAccountDetails = @[ageOver18Detail]; _fakeMainBundle = [[GIDFakeMainBundle alloc] initWithClientID:kClientId @@ -72,7 +75,6 @@ - (void)setUp { openIDRealm:kOpenIDRealm]; } - #pragma mark - Tests - (void)testInit { @@ -112,7 +114,6 @@ - (void)testInit_invalidConfig { openIDRealm:nil]; [_fakeMainBundle startFaking]; - GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; XCTAssertNil(verifyAccountDetail.configuration); } @@ -144,14 +145,16 @@ - (void)testCurrentUserException { #pragma GCC diagnostic pop OIDAuthState *authState = [OIDAuthState testInstance]; -// GIDSignIn.sharedInstance.currentUser = nil; - - XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil], - NSException, - NSInvalidArgumentException, - @"|currentUser| must be set to verify."); + GIDSignIn.sharedInstance.currentUser = nil; + + @try { + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]; + } @catch (NSException *exception) { + XCTAssertEqual(exception.name, NSInvalidArgumentException); + XCTAssertEqualObjects(exception.reason, kMissingCurrentUserExceptionReason); + } } - (void)testPresentingViewControllerException { @@ -162,23 +165,16 @@ - (void)testPresentingViewControllerException { _presentingViewController = nil; OIDAuthState *authState = [OIDAuthState testInstance]; -// GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState -// profileData:nil]; - -// GIDSignIn *signIn = [[GIDSignIn alloc] initPrivate]; - id signIn = OCMClassMock([GIDSignIn class]); - OCMStub([signIn sharedInstance]).andReturn(signIn); - - GIDGoogleUser *currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState - profileData:nil]; - OCMStub([signIn currentUser]).andReturn(currentUser); - - XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil], - NSException, - NSInvalidArgumentException, - @"|presentingViewController| must be set."); + GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; + @try { + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]; + } @catch (NSException *exception) { + XCTAssertEqual(exception.name, NSInvalidArgumentException); + XCTAssertEqualObjects(exception.reason, kMissingPresentingViewControllerExceptionReason); + } } - (void)testClientIDMissingException { @@ -187,16 +183,18 @@ - (void)testClientIDMissingException { _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; #pragma GCC diagnostic pop -// OIDAuthState *authState = [OIDAuthState testInstance]; -// GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState -// profileData:nil]; - - XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil], - NSException, - NSInvalidArgumentException, - @"You must specify |clientID| in |GIDConfiguration|"); + OIDAuthState *authState = [OIDAuthState testInstance]; + GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; + + @try { + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]; + } @catch (NSException *exception) { + XCTAssertEqual(exception.name, NSInvalidArgumentException); + XCTAssertEqualObjects(exception.reason, kClientIDMissingExceptionReason); + } } - (void)testSchemesNotSupportedException { @@ -205,17 +203,18 @@ - (void)testSchemesNotSupportedException { _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:kClientId]; #pragma GCC diagnostic pop -// OIDAuthState *authState = [OIDAuthState testInstance]; -// GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState -// profileData:nil]; - - XCTAssertThrowsSpecificNamed([_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails - presentingViewController:_presentingViewController - completion:nil], - NSException, - NSInvalidArgumentException, - @"Your app is missing support for the following URL schemes: " - "fakeclientid"); + OIDAuthState *authState = [OIDAuthState testInstance]; + GIDSignIn.sharedInstance.currentUser = [[GIDGoogleUser alloc] initWithAuthState:authState + profileData:nil]; + + @try { + [_verifyAccountDetail verifyAccountDetails:_verifiableAccountDetails + presentingViewController:_presentingViewController + completion:nil]; + } @catch (NSException *exception) { + XCTAssertEqual(exception.name, NSInvalidArgumentException); + XCTAssertEqualObjects(exception.reason, kSchemesNotSupportedExceptionReason); + } } @end From 6ce9f101fe2b7e95259acfee7671096f24f7e320 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 9 May 2024 14:02:46 -0700 Subject: [PATCH 20/28] Address formatting and indicate designated initializer in GIDFakeMainBundle. --- .../GoogleSignIn/GIDVerifyAccountDetail.h | 6 +++++- GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h | 3 ++- GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m | 7 +++++++ GoogleSignIn/Tests/Unit/GIDSignInTest.m | 2 ++ .../Tests/Unit/GIDVerifyAccountDetailTest.m | 18 +++++++++++------- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index 424124a2..a500c591 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -43,8 +43,12 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve /// The active configuration for this instance of `GIDVerifyAccountDetail`. @property(nonatomic, nullable) GIDConfiguration *configuration; +/// Initialize a `GIDVerifyAccountDetail` object by specifying all available properties. +/// +/// @param config The configuration to be used. +/// @return An initialized `GIDVerifyAccountDetail` instance. - (instancetype)initWithConfig:(nullable GIDConfiguration *)config -NS_DESIGNATED_INITIALIZER; + NS_DESIGNATED_INITIALIZER; /// Starts an interactive verification flow. /// diff --git a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h index cea717d6..d6039d8b 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h +++ b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h @@ -33,7 +33,8 @@ - (nullable instancetype)initWithClientID:(nullable id)clientID serverClientID:(nullable id)serverClientID hostedDomain:(nullable id)hostedDomain - openIDRealm:(nullable id)openIDRealm; + openIDRealm:(nullable id)openIDRealm + NS_DESIGNATED_INITIALIZER; /** * @fn startFaking: diff --git a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m index c4d11a12..9f1843ae 100644 --- a/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m +++ b/GoogleSignIn/Tests/Unit/GIDFakeMainBundle.m @@ -56,6 +56,13 @@ - (nullable instancetype)initWithClientID:(nullable id)clientID return self; } +- (instancetype)init { + return [self initWithClientID:nil + serverClientID:nil + hostedDomain:nil + openIDRealm:nil]; +} + - (void)startFaking { _fakedKeys = @[ kCFBundleURLTypesKey, kConfigClientIDKey, diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 7fed4c13..537375d0 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -286,6 +286,8 @@ - (void)setUp { #elif TARGET_OS_OSX _presentingWindow = OCMStrictClassMock([NSWindow class]); #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST + + // TODO: Fix strict mocks from carrying forward to subsequent tests. (#410) _authState = OCMClassMock([OIDAuthState class]); OCMStub([_authState alloc]).andReturn(_authState); OCMStub([_authState initWithAuthorizationResponse:OCMOCK_ANY]).andReturn(_authState); diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index d1a2f772..b980d260 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -41,16 +41,16 @@ static NSString * const kFakeHostedDomain = @"fakehosteddomain.com"; @interface GIDVerifyAccountDetailTests : XCTestCase -// The |UIViewController| object being tested. +/// The |UIViewController| object being tested. @property UIViewController *presentingViewController; -// Fake [NSBundle mainBundle]. +/// Fake [NSBundle mainBundle]. @property GIDFakeMainBundle *fakeMainBundle; -// The |GIDVerifyAccountDetail| object being tested. +/// The |GIDVerifyAccountDetail| object being tested. @property GIDVerifyAccountDetail *verifyAccountDetail; -// The list of account details when testing [GIDVerifiableAccountDetail]. +/// The list of account details when testing [GIDVerifiableAccountDetail]. @property NSArray *verifiableAccountDetails; @end @@ -75,6 +75,11 @@ - (void)setUp { openIDRealm:kOpenIDRealm]; } +- (void)tearDown { + [_fakeMainBundle stopFaking]; + [super tearDown]; +} + #pragma mark - Tests - (void)testInit { @@ -129,8 +134,8 @@ - (void)testInitWithConfig_fullConfig { hostedDomain:kFakeHostedDomain openIDRealm:kOpenIDRealm]; - GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] - initWithConfig:configuration]; + GIDVerifyAccountDetail *verifyAccountDetail = + [[GIDVerifyAccountDetail alloc] initWithConfig:configuration]; XCTAssertNotNil(verifyAccountDetail.configuration); XCTAssertEqual(verifyAccountDetail.configuration.clientID, kClientId); XCTAssertEqual(verifyAccountDetail.configuration.serverClientID, kServerClientId); @@ -144,7 +149,6 @@ - (void)testCurrentUserException { _verifyAccountDetail.configuration = [[GIDConfiguration alloc] initWithClientID:nil]; #pragma GCC diagnostic pop - OIDAuthState *authState = [OIDAuthState testInstance]; GIDSignIn.sharedInstance.currentUser = nil; @try { From 4d981eb5b69c4756a5eb01023e59932ee8fb56eb Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 9 May 2024 14:42:49 -0700 Subject: [PATCH 21/28] Add stopFaking calls in appropriate tests. --- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index b980d260..5bc43bd7 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -75,11 +75,6 @@ - (void)setUp { openIDRealm:kOpenIDRealm]; } -- (void)tearDown { - [_fakeMainBundle stopFaking]; - [super tearDown]; -} - #pragma mark - Tests - (void)testInit { @@ -91,6 +86,8 @@ - (void)testInit { XCTAssertNil(verifyAccountDetail.configuration.serverClientID); XCTAssertNil(verifyAccountDetail.configuration.hostedDomain); XCTAssertNil(verifyAccountDetail.configuration.openIDRealm); + + [_fakeMainBundle stopFaking]; } - (void)testInit_noConfig { @@ -98,6 +95,8 @@ - (void)testInit_noConfig { GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; XCTAssertNil(verifyAccountDetail.configuration); + + [_fakeMainBundle stopFaking]; } @@ -110,6 +109,8 @@ - (void)testInit_fullConfig { XCTAssertEqual(verifyAccountDetail.configuration.serverClientID, kServerClientId); XCTAssertEqual(verifyAccountDetail.configuration.hostedDomain, kFakeHostedDomain); XCTAssertEqual(verifyAccountDetail.configuration.openIDRealm, kOpenIDRealm); + + [_fakeMainBundle stopFaking]; } - (void)testInit_invalidConfig { @@ -121,6 +122,8 @@ - (void)testInit_invalidConfig { GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] init]; XCTAssertNil(verifyAccountDetail.configuration); + + [_fakeMainBundle stopFaking]; } - (void)testInitWithConfig_noConfig { From b744a4bc4d42bb0f4b3a145b1f9a042ddbe07323 Mon Sep 17 00:00:00 2001 From: brianna Date: Thu, 9 May 2024 15:21:15 -0700 Subject: [PATCH 22/28] Fix indentation and remove parameter from `additionalParameters`. --- .../Implementations/GIDVerifyAccountDetail.m | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 96733983..90dd527a 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -141,7 +141,6 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * kBrowserCallbackPath]]; NSMutableDictionary *additionalParameters = [@{} mutableCopy]; - additionalParameters[kIncludeGrantedScopesParameter] = @"false"; if (options.configuration.serverClientID) { additionalParameters[kAudienceParameter] = options.configuration.serverClientID; } @@ -164,12 +163,12 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * // TODO(#405): Use request variable to present request and process response. __unused OIDAuthorizationRequest *request = - [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration - clientId:options.configuration.clientID - scopes:scopes - redirectURL:redirectURL - responseType:OIDResponseTypeCode - additionalParameters:additionalParameters]; + [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration + clientId:options.configuration.clientID + scopes:scopes + redirectURL:redirectURL + responseType:OIDResponseTypeCode + additionalParameters:additionalParameters]; } #pragma mark - Helpers From 89b92d3674e8a02be1258ea07503dcc2395d7291 Mon Sep 17 00:00:00 2001 From: brianna Date: Fri, 10 May 2024 15:12:49 -0700 Subject: [PATCH 23/28] Let parameter-less `init` be nullable and require `initWithConfig` to pass a configuration. --- .../Implementations/GIDVerifyAccountDetail.m | 8 ++++++-- .../Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h | 2 +- GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m | 5 ----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 72b9bc83..8761c52c 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -27,7 +27,7 @@ @implementation GIDVerifyAccountDetail -- (instancetype)initWithConfig:(nullable GIDConfiguration *)configuration { +- (instancetype)initWithConfig:(GIDConfiguration *)configuration { self = [super init]; if (self) { _configuration = configuration; @@ -35,13 +35,17 @@ - (instancetype)initWithConfig:(nullable GIDConfiguration *)configuration { return self; } -- (instancetype)init { +- (nullable instancetype)init { GIDConfiguration *configuration; NSBundle *bundle = NSBundle.mainBundle; if (bundle) { configuration = [GIDConfiguration configurationFromBundle:bundle]; } + if (!configuration) { + return nil; + } + return [self initWithConfig:configuration]; } diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index a500c591..c623a28c 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -47,7 +47,7 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve /// /// @param config The configuration to be used. /// @return An initialized `GIDVerifyAccountDetail` instance. -- (instancetype)initWithConfig:(nullable GIDConfiguration *)config +- (instancetype)initWithConfig:(GIDConfiguration *)config NS_DESIGNATED_INITIALIZER; /// Starts an interactive verification flow. diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index 5bc43bd7..a9ea0369 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -126,11 +126,6 @@ - (void)testInit_invalidConfig { [_fakeMainBundle stopFaking]; } -- (void)testInitWithConfig_noConfig { - GIDVerifyAccountDetail *verifyAccountDetail = [[GIDVerifyAccountDetail alloc] initWithConfig:nil]; - XCTAssertNil(verifyAccountDetail.configuration); -} - - (void)testInitWithConfig_fullConfig { GIDConfiguration *configuration = [[GIDConfiguration alloc] initWithClientID:kClientId serverClientID:kServerClientId From 78daa0b1475bea2bae8d10f0dcba1f5f8183753a Mon Sep 17 00:00:00 2001 From: brianna Date: Fri, 10 May 2024 16:21:40 -0700 Subject: [PATCH 24/28] Create `GIDSignInConstants` class to hold common constants across the sign-in and verify flow. --- GoogleSignIn/Sources/GIDGoogleUser.m | 1 + GoogleSignIn/Sources/GIDSignIn.m | 1 + GoogleSignIn/Sources/GIDSignInConstants.h | 25 +++++++++++++++++ GoogleSignIn/Sources/GIDSignInConstants.m | 27 +++++++++++++++++++ .../Implementations/GIDVerifyAccountDetail.m | 1 + .../Sources/Public/GoogleSignIn/GIDSignIn.h | 8 ------ 6 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 GoogleSignIn/Sources/GIDSignInConstants.h create mode 100644 GoogleSignIn/Sources/GIDSignInConstants.m diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 466d7bef..0ec2738c 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -23,6 +23,7 @@ #import "GoogleSignIn/Sources/GIDEMMSupport.h" #import "GoogleSignIn/Sources/GIDProfileData_Private.h" #import "GoogleSignIn/Sources/GIDSignIn_Private.h" +#import "GoogleSignIn/Sources/GIDSignInConstants.h" #import "GoogleSignIn/Sources/GIDSignInPreferences.h" #import "GoogleSignIn/Sources/GIDToken_Private.h" diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 6d82a713..be35b604 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -22,6 +22,7 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignInResult.h" #import "GoogleSignIn/Sources/GIDEMMSupport.h" +#import "GoogleSignIn/Sources/GIDSignInConstants.h" #import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" #import "GoogleSignIn/Sources/GIDSignInPreferences.h" #import "GoogleSignIn/Sources/GIDCallbackQueue.h" diff --git a/GoogleSignIn/Sources/GIDSignInConstants.h b/GoogleSignIn/Sources/GIDSignInConstants.h new file mode 100644 index 00000000..a1cb17ad --- /dev/null +++ b/GoogleSignIn/Sources/GIDSignInConstants.h @@ -0,0 +1,25 @@ +/* + * Copyright 2024 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 + +// Parameters for the auth and token exchange endpoints. +extern NSString *const kAudienceParameter; +// See b/11669751 . +extern NSString *const kOpenIDRealmParameter; +extern NSString *const kIncludeGrantedScopesParameter; +extern NSString *const kLoginHintParameter; +extern NSString *const kHostedDomainParameter; diff --git a/GoogleSignIn/Sources/GIDSignInConstants.m b/GoogleSignIn/Sources/GIDSignInConstants.m new file mode 100644 index 00000000..7c7fb300 --- /dev/null +++ b/GoogleSignIn/Sources/GIDSignInConstants.m @@ -0,0 +1,27 @@ +/* + * Copyright 2024 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 + +#import "GoogleSignIn/Sources/GIDSignInConstants.h" + +// Parameters for the auth and token exchange endpoints. +NSString *const kAudienceParameter = @"audience"; +// See b/11669751 . +NSString *const kOpenIDRealmParameter = @"openid.realm"; +NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; +NSString *const kLoginHintParameter = @"login_hint"; +NSString *const kHostedDomainParameter = @"hd"; diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 90dd527a..5a7740c0 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -22,6 +22,7 @@ #import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" +#import "GoogleSignIn/Sources/GIDSignInConstants.h" #import "GoogleSignIn/Sources/GIDSignInPreferences.h" @import GTMAppAuth; diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h index 15068513..2576b13d 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h @@ -29,14 +29,6 @@ NS_ASSUME_NONNULL_BEGIN -// Parameters for the auth and token exchange endpoints. -static NSString *const kAudienceParameter = @"audience"; -// See b/11669751 . -static NSString *const kOpenIDRealmParameter = @"openid.realm"; -static NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; -static NSString *const kLoginHintParameter = @"login_hint"; -static NSString *const kHostedDomainParameter = @"hd"; - /// The error domain for `NSError`s returned by the Google Sign-In SDK. extern NSErrorDomain const kGIDSignInErrorDomain; From 7112ce5b86a8573260679468d4bab4cd078470ac Mon Sep 17 00:00:00 2001 From: brianna Date: Fri, 10 May 2024 16:36:28 -0700 Subject: [PATCH 25/28] Fix method description and make `initWithConfig` nullable. --- .../Implementations/GIDVerifyAccountDetail.m | 2 +- .../Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 8761c52c..152d90a5 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -27,7 +27,7 @@ @implementation GIDVerifyAccountDetail -- (instancetype)initWithConfig:(GIDConfiguration *)configuration { +- (nullable instancetype)initWithConfig:(GIDConfiguration *)configuration { self = [super init]; if (self) { _configuration = configuration; diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index c623a28c..c2c57c05 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -47,7 +47,8 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve /// /// @param config The configuration to be used. /// @return An initialized `GIDVerifyAccountDetail` instance. -- (instancetype)initWithConfig:(GIDConfiguration *)config +/// Otherwise, `nil` if the configuration is invalid or the initializer fails. +- (nullable instancetype)initWithConfig:(GIDConfiguration *)config NS_DESIGNATED_INITIALIZER; /// Starts an interactive verification flow. From aac80b45d224a16cedc1eafc61e71a9333ba0537 Mon Sep 17 00:00:00 2001 From: brianna Date: Tue, 14 May 2024 14:15:32 -0700 Subject: [PATCH 26/28] Move constants to `GIDSignInConstants` and update doc comments. --- GoogleSignIn/Sources/GIDSignIn.m | 9 --------- GoogleSignIn/Sources/GIDSignInConstants.h | 20 +++++++++++++++++-- GoogleSignIn/Sources/GIDSignInConstants.m | 8 +++++++- .../Implementations/GIDVerifyAccountDetail.m | 20 ++++++------------- .../GoogleSignIn/GIDVerifyAccountDetail.h | 4 ++-- .../Tests/Unit/GIDVerifyAccountDetailTest.m | 4 ++-- 6 files changed, 35 insertions(+), 30 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index be35b604..0452b24f 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -70,21 +70,12 @@ // The name of the query parameter used for logging the restart of auth from EMM callback. static NSString *const kEMMRestartAuthParameter = @"emmres"; -// The URL template for the authorization endpoint. -static NSString *const kAuthorizationURLTemplate = @"https://%@/o/oauth2/v2/auth"; - -// The URL template for the token endpoint. -static NSString *const kTokenURLTemplate = @"https://%@/token"; - // The URL template for the URL to get user info. static NSString *const kUserInfoURLTemplate = @"https://%@/oauth2/v3/userinfo?access_token=%@"; // The URL template for the URL to revoke the token. static NSString *const kRevokeTokenURLTemplate = @"https://%@/o/oauth2/revoke?token=%@"; -// Expected path in the URL scheme to be handled. -static NSString *const kBrowserCallbackPath = @"/oauth2callback"; - // Expected path for EMM callback. static NSString *const kEMMCallbackPath = @"/emmcallback"; diff --git a/GoogleSignIn/Sources/GIDSignInConstants.h b/GoogleSignIn/Sources/GIDSignInConstants.h index a1cb17ad..e04db0fa 100644 --- a/GoogleSignIn/Sources/GIDSignInConstants.h +++ b/GoogleSignIn/Sources/GIDSignInConstants.h @@ -16,10 +16,26 @@ #import -// Parameters for the auth and token exchange endpoints. +/// The URL template for the authorization endpoint. +extern NSString *const kAuthorizationURLTemplate; + +/// The URL template for the token endpoint. +extern NSString *const kTokenURLTemplate; + +/// Expected path in the URL scheme to be handled. +extern NSString *const kBrowserCallbackPath; + +/// The name of the audience parameter for the auth and token exchange endpoints. extern NSString *const kAudienceParameter; -// See b/11669751 . + +/// The name of the open ID realm parameter for the auth and token exchange endpoints. extern NSString *const kOpenIDRealmParameter; + +/// The name of the include granted scopes parameter for the auth and token exchange endpoints. extern NSString *const kIncludeGrantedScopesParameter; + +/// The name of the login hint parameter for the auth and token exchange endpoints. extern NSString *const kLoginHintParameter; + +/// The name of the hosted domain parameter for the auth and token exchange endpoints. extern NSString *const kHostedDomainParameter; diff --git a/GoogleSignIn/Sources/GIDSignInConstants.m b/GoogleSignIn/Sources/GIDSignInConstants.m index 7c7fb300..e8055428 100644 --- a/GoogleSignIn/Sources/GIDSignInConstants.m +++ b/GoogleSignIn/Sources/GIDSignInConstants.m @@ -18,9 +18,15 @@ #import "GoogleSignIn/Sources/GIDSignInConstants.h" +// The URL templates for the authorization and token endpoints. +NSString *const kAuthorizationURLTemplate = @"https://%@/o/oauth2/v2/auth"; +NSString *const kTokenURLTemplate = @"https://%@/token"; + +// Expected path in the URL scheme to be handled. +NSString *const kBrowserCallbackPath = @"/oauth2callback"; + // Parameters for the auth and token exchange endpoints. NSString *const kAudienceParameter = @"audience"; -// See b/11669751 . NSString *const kOpenIDRealmParameter = @"openid.realm"; NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; NSString *const kLoginHintParameter = @"login_hint"; diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index cac3bb09..21c624bc 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -38,17 +38,8 @@ #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST -// The URL template for the authorization endpoint. -static NSString *const kAuthorizationURLTemplate = @"https://%@/o/oauth2/v2/auth"; - -// The URL template for the token endpoint. -static NSString *const kTokenURLTemplate = @"https://%@/token"; - -// Expected path in the URL scheme to be handled. -static NSString *const kBrowserCallbackPath = @"/oauth2callback"; - @implementation GIDVerifyAccountDetail { - // AppAuth configuration object. + /// AppAuth configuration object. OIDServiceConfiguration *_appAuthConfiguration; } @@ -135,7 +126,7 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * // If the application does not support the required URL schemes tell the developer so. GIDSignInCallbackSchemes *schemes = - [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; + [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; NSArray *unsupportedSchemes = [schemes unsupportedSchemes]; if (unsupportedSchemes.count != 0) { // NOLINTNEXTLINE(google-objc-avoid-throwing-exception) @@ -143,9 +134,10 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * format:@"Your app is missing support for the following URL schemes: %@", [unsupportedSchemes componentsJoinedByString:@", "]]; } - NSURL *redirectURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", - [schemes clientIdentifierScheme], - kBrowserCallbackPath]]; + NSString *redirectURI = [NSString stringWithFormat:@"%@:%@", + [schemes clientIdentifierScheme], + kBrowserCallbackPath]; + NSURL *redirectURL = [NSURL URLWithString:redirectURI]; NSMutableDictionary *additionalParameters = [@{} mutableCopy]; if (options.configuration.serverClientID) { diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h index 6fb68b24..3eb2dea8 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h @@ -16,7 +16,7 @@ #import -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST #import @@ -91,4 +91,4 @@ typedef void (^GIDVerifyCompletion)(GIDVerifiedAccountDetailResult *_Nullable ve NS_ASSUME_NONNULL_END -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST diff --git a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m index 5b6d92a5..a5efdfff 100644 --- a/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m +++ b/GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m @@ -14,7 +14,7 @@ #import -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifiableAccountDetail.h" @@ -223,4 +223,4 @@ - (void)testSchemesNotSupportedException { @end -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST From 298d9c4f365cb8559cdc8ff68e50d0248cb42165 Mon Sep 17 00:00:00 2001 From: brianna Date: Tue, 14 May 2024 14:25:46 -0700 Subject: [PATCH 27/28] Update preprocessor directives to exclude TARGET_OS_MACCATALYST. --- GoogleSignIn/Sources/GIDSignInInternalOptions.h | 16 ++++++++-------- GoogleSignIn/Sources/GIDSignInInternalOptions.m | 4 ++-- .../Tests/Unit/GIDSignInInternalOptionsTest.m | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignInInternalOptions.h b/GoogleSignIn/Sources/GIDSignInInternalOptions.h index c722d5d4..7a36e210 100644 --- a/GoogleSignIn/Sources/GIDSignInInternalOptions.h +++ b/GoogleSignIn/Sources/GIDSignInInternalOptions.h @@ -24,9 +24,9 @@ #import "GoogleSignIn/Sources/GIDSignIn_Private.h" -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDVerifyAccountDetail.h" -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST @class GIDConfiguration; @class GIDSignInResult; @@ -45,10 +45,10 @@ NS_ASSUME_NONNULL_BEGIN /// Whether the sign-in is an addScopes flow. NO means it is a sign in flow. @property(nonatomic, readonly) BOOL addScopesFlow; -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST /// The user account details the Verify with Google flow will verify @property(nonatomic, copy, nullable, readonly) NSArray *accountDetailsToVerify; -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST /// The extra parameters used in the sign-in URL. @property(nonatomic, readonly, nullable) NSDictionary *extraParams; @@ -67,10 +67,10 @@ NS_ASSUME_NONNULL_BEGIN /// The completion block to be called at the completion of the flow. @property(nonatomic, readonly, nullable) GIDSignInCompletion completion; -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST /// The completion block to be called at the completion of the verify flow. @property(nonatomic, readonly, nullable) GIDVerifyCompletion verifyCompletion; -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST /// The scopes to be used during the flow. @property(nonatomic, copy, nullable) NSArray *scopes; @@ -79,14 +79,14 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy, nullable) NSString *loginHint; /// Creates the default options. -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration presentingViewController:(nullable UIViewController *)presentingViewController loginHint:(nullable NSString *)loginHint addScopesFlow:(BOOL)addScopesFlow accountDetailsToVerify:(NSArray *)accountDetailsToVerify verifyCompletion:(nullable GIDVerifyCompletion)completion; -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST #if TARGET_OS_IOS || TARGET_OS_MACCATALYST + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration diff --git a/GoogleSignIn/Sources/GIDSignInInternalOptions.m b/GoogleSignIn/Sources/GIDSignInInternalOptions.m index f505eadf..74b271bd 100644 --- a/GoogleSignIn/Sources/GIDSignInInternalOptions.m +++ b/GoogleSignIn/Sources/GIDSignInInternalOptions.m @@ -26,7 +26,7 @@ @implementation GIDSignInInternalOptions -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration presentingViewController:(nullable UIViewController *)presentingViewController loginHint:(nullable NSString *)loginHint @@ -46,7 +46,7 @@ + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)con } return options; } -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST #if TARGET_OS_IOS || TARGET_OS_MACCATALYST + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration diff --git a/GoogleSignIn/Tests/Unit/GIDSignInInternalOptionsTest.m b/GoogleSignIn/Tests/Unit/GIDSignInInternalOptionsTest.m index ac7d47e4..3c2e7fee 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInInternalOptionsTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInInternalOptionsTest.m @@ -33,7 +33,7 @@ @interface GIDSignInInternalOptionsTest : XCTestCase @implementation GIDSignInInternalOptionsTest -#if TARGET_OS_IOS +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - (void)testDefaultOptionsForVerificationFlow { GIDConfiguration *configuration = [[GIDConfiguration alloc] initWithClientID:kClientId serverClientID:nil @@ -59,7 +59,7 @@ - (void)testDefaultOptionsForVerificationFlow { XCTAssertEqual(options.presentingViewController, presentingViewController); XCTAssertEqual(options.accountDetailsToVerify, accountDetailsToVerify); } -#endif // TARGET_OS_IOS +#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST - (void)testDefaultOptions { id configuration = OCMStrictClassMock([GIDConfiguration class]); From 227f3e375f0a45edd1681463eb8c18e189fab8e4 Mon Sep 17 00:00:00 2001 From: brianna Date: Wed, 15 May 2024 02:39:33 -0700 Subject: [PATCH 28/28] Fix formatting. --- GoogleSignIn/Sources/GIDSignInConstants.m | 4 ---- .../Implementations/GIDVerifyAccountDetail.m | 5 ++--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignInConstants.m b/GoogleSignIn/Sources/GIDSignInConstants.m index e8055428..bb90d37a 100644 --- a/GoogleSignIn/Sources/GIDSignInConstants.m +++ b/GoogleSignIn/Sources/GIDSignInConstants.m @@ -18,14 +18,10 @@ #import "GoogleSignIn/Sources/GIDSignInConstants.h" -// The URL templates for the authorization and token endpoints. NSString *const kAuthorizationURLTemplate = @"https://%@/o/oauth2/v2/auth"; NSString *const kTokenURLTemplate = @"https://%@/token"; - -// Expected path in the URL scheme to be handled. NSString *const kBrowserCallbackPath = @"/oauth2callback"; -// Parameters for the auth and token exchange endpoints. NSString *const kAudienceParameter = @"audience"; NSString *const kOpenIDRealmParameter = @"openid.realm"; NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes"; diff --git a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m index 21c624bc..7e192768 100644 --- a/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m +++ b/GoogleSignIn/Sources/GIDVerifyAccountDetail/Implementations/GIDVerifyAccountDetail.m @@ -134,9 +134,8 @@ - (void)verifyAccountDetailsInteractivelyWithOptions:(GIDSignInInternalOptions * format:@"Your app is missing support for the following URL schemes: %@", [unsupportedSchemes componentsJoinedByString:@", "]]; } - NSString *redirectURI = [NSString stringWithFormat:@"%@:%@", - [schemes clientIdentifierScheme], - kBrowserCallbackPath]; + NSString *redirectURI = + [NSString stringWithFormat:@"%@:%@", [schemes clientIdentifierScheme], kBrowserCallbackPath]; NSURL *redirectURL = [NSURL URLWithString:redirectURI]; NSMutableDictionary *additionalParameters = [@{} mutableCopy];