From 1463c4a206f6ec1d34bd7e691222875a7b90c5a9 Mon Sep 17 00:00:00 2001 From: pinlu Date: Wed, 4 Jan 2023 09:54:14 -0800 Subject: [PATCH 1/9] Add GIDAuthorizationProcessor API and implementation. --- .../API/GIDAuthorizationFlowProcessor.h | 50 +++++++ .../GIDAuthorizationFlowProcessor.h | 32 +++++ .../GIDAuthorizationFlowProcessor.m | 130 ++++++++++++++++++ GoogleSignIn/Sources/GIDSignIn.m | 13 +- GoogleSignIn/Sources/GIDSignIn_Private.h | 2 + 5 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h create mode 100644 GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h create mode 100644 GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h new file mode 100644 index 00000000..a970d71e --- /dev/null +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h @@ -0,0 +1,50 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class GIDSignInInternalOptions; +@class OIDAuthorizationResponse; + +@protocol GIDAuthorizationFlowProcessor + +/// The state of the authorization flow. +@property(nonatomic, readonly, getter=isStarted) BOOL start; + +/// Starts the authorization flow. +/// +/// @param options The @GIDSignInInternalOptions object to provide serverClientID, hostedDomain, +/// clientID, scopes, loginHint and extraParams. +/// @param completion The block that is called on completion asynchronously. +- (void)startWithOptions:(GIDSignInInternalOptions *)options + completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse, + NSError *_Nullable error))completion; + +/// Handles the custom scheme URL opened by SFSafariViewController to cleanup UI on iOS 10. +/// +/// @param URL The redirect URL invoked by the server. +/// @return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise. +- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url; + +/// Cancels the authorization flow. +- (void)cancelAuthenticationFlow; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h new file mode 100644 index 00000000..7d399669 --- /dev/null +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h @@ -0,0 +1,32 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h" + +@class OIDServiceConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +@interface GIDAuthorizationFlowProcessor : NSObject + +- (instancetype)initWithAppAuthConfiguration:(OIDServiceConfiguration *)appAuthConfiguration; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m new file mode 100644 index 00000000..55cdf653 --- /dev/null +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m @@ -0,0 +1,130 @@ +#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h" + +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" + +#import "GoogleSignIn/Sources/GIDEMMSupport.h" +#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h" +#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" +#import "GoogleSignIn/Sources/GIDSignInPreferences.h" + +#ifdef SWIFT_PACKAGE +@import AppAuth; +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +// 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 GIDAuthorizationFlowProcessor { + // AppAuth external user-agent session state. + id _currentAuthorizationFlow; + // AppAuth configuration object. + OIDServiceConfiguration *_appAuthConfiguration; +} + +@synthesize start; + +# pragma mark - Public API + +- (BOOL)isStarted { + return _currentAuthorizationFlow != nil; +} + +- (instancetype)initWithAppAuthConfiguration:(OIDServiceConfiguration *)appAuthConfiguration { + self = [super self]; + if (self) { + _appAuthConfiguration = appAuthConfiguration; + } + return self; +} + +- (void)startWithOptions:(GIDSignInInternalOptions *)options + completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse, + NSError *_Nullable error))completion { + GIDSignInCallbackSchemes *schemes = + [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; + NSURL *redirectURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", + [schemes clientIdentifierScheme], + kBrowserCallbackPath]]; + NSString *emmSupport; +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST + emmSupport = [[self class] isOperatingSystemAtLeast9] ? kEMMVersion : nil; +#elif TARGET_OS_MACCATALYST || TARGET_OS_OSX + emmSupport = nil; +#endif // TARGET_OS_MACCATALYST || TARGET_OS_OSX + + 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; + } + +#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST + [additionalParameters addEntriesFromDictionary: + [GIDEMMSupport parametersWithParameters:options.extraParams + emmSupport:emmSupport + isPasscodeInfoRequired:NO]]; +#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST + [additionalParameters addEntriesFromDictionary:options.extraParams]; +#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST + additionalParameters[kSDKVersionLoggingParameter] = GIDVersion(); + additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment(); + + OIDAuthorizationRequest *request = + [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration + clientId:options.configuration.clientID + scopes:options.scopes + redirectURL:redirectURL + responseType:OIDResponseTypeCode + additionalParameters:additionalParameters]; + _currentAuthorizationFlow = [OIDAuthorizationService + presentAuthorizationRequest:request +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + presentingViewController:options.presentingViewController +#elif TARGET_OS_OSX + presentingWindow:options.presentingWindow +#endif // TARGET_OS_OSX + callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, + NSError *_Nullable error) { + completion(authorizationResponse, error); + }]; +} + +- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url { + return [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]; +} + +- (void)cancelAuthenticationFlow { + [_currentAuthorizationFlow cancel]; +} + +# pragma mark - Helpers + +- (BOOL)isOperatingSystemAtLeast9 { + NSProcessInfo *processInfo = [NSProcessInfo processInfo]; + return [processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && + [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 9}]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 7904608d..0bd680d9 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -21,6 +21,8 @@ #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDProfileData.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignInResult.h" +#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h" +#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h" #import "GoogleSignIn/Sources/GIDHTTPFetcher/API/GIDHTTPFetcher.h" #import "GoogleSignIn/Sources/GIDHTTPFetcher/Implementations/GIDHTTPFetcher.h" #import "GoogleSignIn/Sources/GIDEMMSupport.h" @@ -462,12 +464,19 @@ + (GIDSignIn *)sharedInstance { - (id)initPrivate { id keychainHandler = [[GIDKeychainHandler alloc] init]; id httpFetcher = [[GIDHTTPFetcher alloc] init]; + + + // Start from here after taking GIDAppAuthConfiguration out of GIDSignIn.m. + id authorizationFlowProcessor = + [[GIDAuthorizationFlowProcessor alloc] init]; return [self initWithKeychainHandler:keychainHandler - httpFetcher:httpFetcher]; + httpFetcher:httpFetcher + authorizationFlowProcessor:authorizationFlowProcessor]; } - (instancetype)initWithKeychainHandler:(id)keychainHandler - httpFetcher:(id)httpFetcher{ + httpFetcher:(id)httpFetcher + authorizationFlowProcessor:(id)authorizationFlowProcessor { self = [super init]; if (self) { // Get the bundle of the current executable. diff --git a/GoogleSignIn/Sources/GIDSignIn_Private.h b/GoogleSignIn/Sources/GIDSignIn_Private.h index 287e8cbd..0e7e53fa 100644 --- a/GoogleSignIn/Sources/GIDSignIn_Private.h +++ b/GoogleSignIn/Sources/GIDSignIn_Private.h @@ -31,6 +31,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol GIDHTTPFetcher; @protocol GIDKeychainHandler; +@protocol GIDAuthorizationFlowProcessor; /// Represents a completion block that takes a `GIDSignInResult` on success or an error if the /// operation was unsuccessful. @@ -52,6 +53,7 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error); /// The designated initializer. - (instancetype)initWithKeychainHandler:(id)keychainHandler httpFetcher:(id)HTTPFetcher + authorizationFlowProcessor:(id)authorizationFlowProcessor NS_DESIGNATED_INITIALIZER; /// Authenticates with extra options. From 7003139fc495ddc3b370ad3ab88e6e1c7ddd64a7 Mon Sep 17 00:00:00 2001 From: pinlu Date: Thu, 5 Jan 2023 13:44:59 -0800 Subject: [PATCH 2/9] Use GIDAuthorizationFlowProcessor in GIDSignIn --- .../API/GIDAuthorizationFlowProcessor.h | 2 +- .../GIDAuthorizationFlowProcessor.h | 2 - .../GIDAuthorizationFlowProcessor.m | 45 +++----- GoogleSignIn/Sources/GIDSignIn.m | 106 ++++-------------- GoogleSignIn/Sources/GIDSignInPreferences.h | 6 + GoogleSignIn/Sources/GIDSignInPreferences.m | 10 +- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 7 +- 7 files changed, 56 insertions(+), 122 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h index a970d71e..bad65188 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h @@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN /// clientID, scopes, loginHint and extraParams. /// @param completion The block that is called on completion asynchronously. - (void)startWithOptions:(GIDSignInInternalOptions *)options + emmSupport:(NSString *)emmSupport completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error))completion; @@ -47,4 +48,3 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END - diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h index 7d399669..9320e72a 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h @@ -24,8 +24,6 @@ NS_ASSUME_NONNULL_BEGIN @interface GIDAuthorizationFlowProcessor : NSObject -- (instancetype)initWithAppAuthConfiguration:(OIDServiceConfiguration *)appAuthConfiguration; - @end NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m index 55cdf653..055a9a73 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m @@ -15,12 +15,6 @@ NS_ASSUME_NONNULL_BEGIN -// 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"; @@ -43,15 +37,8 @@ - (BOOL)isStarted { return _currentAuthorizationFlow != nil; } -- (instancetype)initWithAppAuthConfiguration:(OIDServiceConfiguration *)appAuthConfiguration { - self = [super self]; - if (self) { - _appAuthConfiguration = appAuthConfiguration; - } - return self; -} - - (void)startWithOptions:(GIDSignInInternalOptions *)options + emmSupport:(NSString *)emmSupport completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error))completion { GIDSignInCallbackSchemes *schemes = @@ -59,12 +46,6 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options NSURL *redirectURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", [schemes clientIdentifierScheme], kBrowserCallbackPath]]; - NSString *emmSupport; -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - emmSupport = [[self class] isOperatingSystemAtLeast9] ? kEMMVersion : nil; -#elif TARGET_OS_MACCATALYST || TARGET_OS_OSX - emmSupport = nil; -#endif // TARGET_OS_MACCATALYST || TARGET_OS_OSX NSMutableDictionary *additionalParameters = [@{} mutableCopy]; additionalParameters[kIncludeGrantedScopesParameter] = @"true"; @@ -88,9 +69,15 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options #endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST additionalParameters[kSDKVersionLoggingParameter] = GIDVersion(); additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment(); + + NSURL *authorizationEndpointURL = [GIDSignInPreferences authorizationEndpointURL]; + NSURL *tokenEndpointURL = [GIDSignInPreferences tokenEndpointURL]; + OIDServiceConfiguration *appAuthConfiguration = + [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpointURL + tokenEndpoint:tokenEndpointURL]; OIDAuthorizationRequest *request = - [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration + [[OIDAuthorizationRequest alloc] initWithConfiguration:appAuthConfiguration clientId:options.configuration.clientID scopes:options.scopes redirectURL:redirectURL @@ -110,19 +97,17 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options } - (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url { - return [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]; + if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) { + _currentAuthorizationFlow = nil; + return YES; + } else { + return NO; + } } - (void)cancelAuthenticationFlow { [_currentAuthorizationFlow cancel]; -} - -# pragma mark - Helpers - -- (BOOL)isOperatingSystemAtLeast9 { - NSProcessInfo *processInfo = [NSProcessInfo processInfo]; - return [processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && - [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 9}]; + _currentAuthorizationFlow = nil; } @end diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 3502b325..b5a3e0e0 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -82,9 +82,6 @@ // The URL template for the URL to revoke the token. static NSString *const kRevokeTokenURLTemplate = @"https://%@/o/oauth2/revoke"; -// Expected path in the URL scheme to be handled. -static NSString *const kBrowserCallbackPath = @"/oauth2callback"; - // Expected path for EMM callback. static NSString *const kEMMCallbackPath = @"/emmcallback"; @@ -126,9 +123,6 @@ 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; @@ -158,8 +152,6 @@ @implementation GIDSignIn { // represent a sign in continuation. GIDSignInInternalOptions *_currentOptions; - // AppAuth external user-agent session state. - id _currentAuthorizationFlow; // Flag to indicate that the auth flow is restarting. BOOL _restarting; @@ -167,6 +159,9 @@ @implementation GIDSignIn { // The class to fetches data from a url end point. id _httpFetcher; + + // The class to control the authorization flow. + id _authorizationFlowProcessor; } #pragma mark - Public methods @@ -178,8 +173,7 @@ @implementation GIDSignIn { - (BOOL)handleURL:(NSURL *)url { // Check if the callback path matches the expected one for a URL from Safari/Chrome/SafariVC. if ([url.path isEqual:kBrowserCallbackPath]) { - if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) { - _currentAuthorizationFlow = nil; + if ([_authorizationFlowProcessor resumeExternalUserAgentFlowWithURL:url]) { return YES; } return NO; @@ -251,12 +245,12 @@ - (void)signInWithPresentingViewController:(UIViewController *)presentingViewCon additionalScopes:(nullable NSArray *)additionalScopes completion:(nullable GIDSignInCompletion)completion { GIDSignInInternalOptions *options = - [GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration - presentingViewController:presentingViewController - loginHint:hint - addScopesFlow:NO - scopes:additionalScopes - completion:completion]; + [GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration + presentingViewController:presentingViewController + loginHint:hint + addScopesFlow:NO + scopes:additionalScopes + completion:completion]; [self signInWithOptions:options]; } @@ -329,12 +323,12 @@ - (void)signInWithPresentingWindow:(NSWindow *)presentingWindow additionalScopes:(nullable NSArray *)additionalScopes completion:(nullable GIDSignInCompletion)completion { GIDSignInInternalOptions *options = - [GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration - presentingWindow:presentingWindow - loginHint:hint - addScopesFlow:NO - scopes:additionalScopes - completion:completion]; + [GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration + presentingWindow:presentingWindow + loginHint:hint + addScopesFlow:NO + scopes:additionalScopes + completion:completion]; [self signInWithOptions:options]; } @@ -457,11 +451,8 @@ + (GIDSignIn *)sharedInstance { - (id)initPrivate { id keychainHandler = [[GIDKeychainHandler alloc] init]; id httpFetcher = [[GIDHTTPFetcher alloc] init]; - - - // Start from here after taking GIDAppAuthConfiguration out of GIDSignIn.m. id authorizationFlowProcessor = - [[GIDAuthorizationFlowProcessor alloc] init]; + [[GIDAuthorizationFlowProcessor alloc] init]; return [self initWithKeychainHandler:keychainHandler httpFetcher:httpFetcher authorizationFlowProcessor:authorizationFlowProcessor]; @@ -499,6 +490,7 @@ - (instancetype)initWithKeychainHandler:(id)keychainHandler _keychainHandler = keychainHandler; _httpFetcher = httpFetcher; + _authorizationFlowProcessor = authorizationFlowProcessor; } return self; } @@ -524,7 +516,6 @@ - (void)signInWithOptions:(GIDSignInInternalOptions *)options { // Explicitly throw exception for missing client ID here. This must come before // scheme check because schemes rely on reverse client IDs. [self assertValidParameters]; - [self assertValidPresentingViewController]; // If the application does not support the required URL schemes tell the developer so. @@ -563,64 +554,17 @@ - (void)signInWithOptions:(GIDSignInInternalOptions *)options { #pragma mark - Authentication flow - (void)authenticateInteractivelyWithOptions:(GIDSignInInternalOptions *)options { - GIDSignInCallbackSchemes *schemes = - [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; - NSURL *redirectURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", - [schemes clientIdentifierScheme], - kBrowserCallbackPath]]; NSString *emmSupport; #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST emmSupport = [[self class] isOperatingSystemAtLeast9] ? kEMMVersion : nil; #elif TARGET_OS_MACCATALYST || TARGET_OS_OSX emmSupport = nil; #endif // TARGET_OS_MACCATALYST || TARGET_OS_OSX - - 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; - } - -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - [additionalParameters addEntriesFromDictionary: - [GIDEMMSupport parametersWithParameters:options.extraParams - emmSupport:emmSupport - isPasscodeInfoRequired:NO]]; -#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST - [additionalParameters addEntriesFromDictionary:options.extraParams]; -#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST - additionalParameters[kSDKVersionLoggingParameter] = GIDVersion(); - additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment(); - NSURL *authorizationEndpointURL = [GIDSignInPreferences authorizationEndpointURL]; - NSURL *tokenEndpointURL = [GIDSignInPreferences tokenEndpointURL]; - OIDServiceConfiguration *appAuthConfiguration = - [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpointURL - tokenEndpoint:tokenEndpointURL]; - - OIDAuthorizationRequest *request = - [[OIDAuthorizationRequest alloc] initWithConfiguration:appAuthConfiguration - clientId:options.configuration.clientID - scopes:options.scopes - redirectURL:redirectURL - responseType:OIDResponseTypeCode - additionalParameters:additionalParameters]; - - _currentAuthorizationFlow = [OIDAuthorizationService - presentAuthorizationRequest:request -#if TARGET_OS_IOS || TARGET_OS_MACCATALYST - presentingViewController:options.presentingViewController -#elif TARGET_OS_OSX - presentingWindow:options.presentingWindow -#endif // TARGET_OS_OSX - callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, - NSError *_Nullable error) { + [_authorizationFlowProcessor startWithOptions:options + emmSupport:(NSString *)emmSupport + completion:^(OIDAuthorizationResponse *authorizationResponse, + NSError *error) { [self processAuthorizationResponse:authorizationResponse error:error emmSupport:emmSupport]; @@ -689,7 +633,6 @@ - (void)processAuthorizationResponse:(OIDAuthorizationResponse *)authorizationRe // Perform authentication with the provided options. - (void)authenticateWithOptions:(GIDSignInInternalOptions *)options { - // If this is an interactive flow, we're not going to try to restore any saved auth state. if (options.interactive) { [self authenticateInteractivelyWithOptions:options]; @@ -910,12 +853,11 @@ - (BOOL)handleDevicePolicyAppURL:(NSURL *)url { return NO; } #endif // TARGET_OS_OSX - if (!_currentAuthorizationFlow) { + if (!_authorizationFlowProcessor.isStarted) { return NO; } _restarting = YES; - [_currentAuthorizationFlow cancel]; - _currentAuthorizationFlow = nil; + [_authorizationFlowProcessor cancelAuthenticationFlow]; _restarting = NO; NSDictionary *extraParameters = @{ kEMMRestartAuthParameter : @"1" }; // In iOS 13 the presentation of ASWebAuthenticationSession needs an anchor window, diff --git a/GoogleSignIn/Sources/GIDSignInPreferences.h b/GoogleSignIn/Sources/GIDSignInPreferences.h index 3d630f77..5a7654eb 100644 --- a/GoogleSignIn/Sources/GIDSignInPreferences.h +++ b/GoogleSignIn/Sources/GIDSignInPreferences.h @@ -18,9 +18,15 @@ NS_ASSUME_NONNULL_BEGIN +// The name of the query parameter used for logging the SDK version. extern NSString *const kSDKVersionLoggingParameter; + +// The name of the query parameter used for logging the Apple execution environment. extern NSString *const kEnvironmentLoggingParameter; +// Expected path in the URL scheme to be handled. +extern NSString *const kBrowserCallbackPath; + NSString* GIDVersion(void); NSString* GIDEnvironment(void); diff --git a/GoogleSignIn/Sources/GIDSignInPreferences.m b/GoogleSignIn/Sources/GIDSignInPreferences.m index 7c4aa159..366f3bbb 100644 --- a/GoogleSignIn/Sources/GIDSignInPreferences.m +++ b/GoogleSignIn/Sources/GIDSignInPreferences.m @@ -16,16 +16,14 @@ NS_ASSUME_NONNULL_BEGIN +NSString *const kSDKVersionLoggingParameter = @"gpsdk"; +NSString *const kEnvironmentLoggingParameter = @"gidenv"; +NSString *const kBrowserCallbackPath = @"/oauth2callback"; + static NSString *const kLSOServer = @"accounts.google.com"; static NSString *const kTokenServer = @"oauth2.googleapis.com"; static NSString *const kUserInfoServer = @"www.googleapis.com"; -// The name of the query parameter used for logging the SDK version. -NSString *const kSDKVersionLoggingParameter = @"gpsdk"; - -// The name of the query parameter used for logging the Apple execution environment. -NSString *const kEnvironmentLoggingParameter = @"gidenv"; - // Supported Apple execution environments static NSString *const kAppleEnvironmentUnknown = @"unknown"; static NSString *const kAppleEnvironmentIOS = @"ios"; diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index fd13de71..7cb5fee1 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -26,6 +26,7 @@ // Test module imports @import GoogleSignIn; +#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h" #import "GoogleSignIn/Sources/GIDEMMSupport.h" #import "GoogleSignIn/Sources/GIDGoogleUser_Private.h" #import "GoogleSignIn/Sources/GIDSignIn_Private.h" @@ -311,8 +312,12 @@ - (void)setUp { _httpFetcher = [[GIDFakeHTTPFetcher alloc] init]; + GIDAuthorizationFlowProcessor * authorizationFlowProcessor = + [[GIDAuthorizationFlowProcessor alloc] init]; + _signIn = [[GIDSignIn alloc] initWithKeychainHandler:_keychainHandler - httpFetcher:_httpFetcher]; + httpFetcher:_httpFetcher + authorizationFlowProcessor:authorizationFlowProcessor]; _hint = nil; __weak GIDSignInTest *weakSelf = self; From 0e80a9db3826b9b3c937eded1865b4528d64d4a2 Mon Sep 17 00:00:00 2001 From: pinlu Date: Thu, 5 Jan 2023 17:07:45 -0800 Subject: [PATCH 3/9] Add test for GIDAuthorizationFlowProcessor. --- .../API/GIDAuthorizationFlowProcessor.h | 4 +- .../GIDAuthorizationFlowProcessor.m | 28 +++- .../Unit/GIDAuthorizationFlowProcessorTest.m | 123 ++++++++++++++++++ 3 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h index bad65188..365270f9 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h @@ -32,13 +32,13 @@ NS_ASSUME_NONNULL_BEGIN /// clientID, scopes, loginHint and extraParams. /// @param completion The block that is called on completion asynchronously. - (void)startWithOptions:(GIDSignInInternalOptions *)options - emmSupport:(NSString *)emmSupport + emmSupport:(nullable NSString *)emmSupport completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error))completion; /// Handles the custom scheme URL opened by SFSafariViewController to cleanup UI on iOS 10. /// -/// @param URL The redirect URL invoked by the server. +/// @param url The redirect URL invoked by the server. /// @return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise. - (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url; diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m index 055a9a73..e8cecee6 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h" #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h" @@ -38,14 +54,14 @@ - (BOOL)isStarted { } - (void)startWithOptions:(GIDSignInInternalOptions *)options - emmSupport:(NSString *)emmSupport + emmSupport:(nullable NSString *)emmSupport completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error))completion { GIDSignInCallbackSchemes *schemes = [[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID]; - NSURL *redirectURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", - [schemes clientIdentifierScheme], - kBrowserCallbackPath]]; + NSString *urlString = [NSString stringWithFormat:@"%@:%@", + [schemes clientIdentifierScheme], kBrowserCallbackPath]; + NSURL *redirectURL = [NSURL URLWithString:urlString]; NSMutableDictionary *additionalParameters = [@{} mutableCopy]; additionalParameters[kIncludeGrantedScopesParameter] = @"true"; @@ -90,8 +106,8 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options #elif TARGET_OS_OSX presentingWindow:options.presentingWindow #endif // TARGET_OS_OSX - callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, - NSError *_Nullable error) { + callback:^(OIDAuthorizationResponse *authorizationResponse, + NSError *error) { completion(authorizationResponse, error); }]; } diff --git a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m new file mode 100644 index 00000000..cd7f945b --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m @@ -0,0 +1,123 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h" + +#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" +#import "GoogleSignIn/Tests/Unit/OIDAuthorizationResponse+Testing.h" + +#import + +#ifdef SWIFT_PACKAGE +@import AppAuth; +@import OCMock; +#else +#import +#import +#endif + +static NSString *const kFakeURL = @"www.fakeURL.com"; +static NSString *const kErrorDomain = @"ERROR_DOMAIN"; +static NSInteger const kErrorCode = 400; + +@interface GIDAuthorizationFlowProcessorTest : XCTestCase { + GIDAuthorizationFlowProcessor *_authorizationFlowProcessor; + id _authorizationServiceMock; + id _externalUserAgentSession; +} + +@end + +@implementation GIDAuthorizationFlowProcessorTest + +- (void)setUp { + [super setUp]; + + _authorizationFlowProcessor = [[GIDAuthorizationFlowProcessor alloc] init]; + _externalUserAgentSession = OCMProtocolMock(@protocol(OIDExternalUserAgentSession)); + _authorizationServiceMock = OCMClassMock([OIDAuthorizationService class]); + OIDAuthorizationResponse *response = [OIDAuthorizationResponse testInstance]; + NSError *error = [self error]; + OCMStub([_authorizationServiceMock + presentAuthorizationRequest:[OCMArg any] +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + presentingViewController:[OCMArg any] +#elif TARGET_OS_OSX + presentingWindow:[OCMArg any] +#endif // TARGET_OS_OSX + callback:([OCMArg invokeBlockWithArgs:response, error, nil]) + ]).andReturn(_externalUserAgentSession); +} + +- (void)testStartAndCancelAuthorizationFlow { + XCTestExpectation *expectation = [self expectationWithDescription:@"completion is invoked."]; + GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; + [_authorizationFlowProcessor startWithOptions:options + emmSupport:nil + completion:^(OIDAuthorizationResponse *authorizationResponse, + NSError *error) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1 handler:nil]; + XCTAssertTrue(_authorizationFlowProcessor.isStarted); + + [_authorizationFlowProcessor cancelAuthenticationFlow]; + XCTAssertFalse(_authorizationFlowProcessor.isStarted); +} + +- (void)testStartAndResumeAuthorizationFlow_success { + OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) + .andReturn(YES); + XCTestExpectation *expectation = [self expectationWithDescription:@"completion is invoked."]; + GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; + [_authorizationFlowProcessor startWithOptions:options + emmSupport:nil + completion:^(OIDAuthorizationResponse *authorizationResponse, + NSError *error) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1 handler:nil]; + XCTAssertTrue(_authorizationFlowProcessor.isStarted); + + NSURL *url = [[NSURL alloc] initWithString:kFakeURL]; + [_authorizationFlowProcessor resumeExternalUserAgentFlowWithURL:url]; + XCTAssertFalse(_authorizationFlowProcessor.isStarted); +} + +- (void)testStartAndResumeAuthorizationFlow_fail { + OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) + .andReturn(NO); + XCTestExpectation *expectation = [self expectationWithDescription:@"completion is invoked."]; + GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; + [_authorizationFlowProcessor startWithOptions:options + emmSupport:nil + completion:^(OIDAuthorizationResponse *authorizationResponse, + NSError *error) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1 handler:nil]; + XCTAssertTrue(_authorizationFlowProcessor.isStarted); + + NSURL *url = [[NSURL alloc] initWithString:kFakeURL]; + [_authorizationFlowProcessor resumeExternalUserAgentFlowWithURL:url]; + XCTAssertTrue(_authorizationFlowProcessor.isStarted); +} + +#pragma mark - Helpers + +- (NSError *)error { + return [NSError errorWithDomain:kErrorDomain code:kErrorCode userInfo:nil]; +} + +@end From ec80960856cc51e0894d2bc6c17052d3b8f54c04 Mon Sep 17 00:00:00 2001 From: pinlu Date: Fri, 6 Jan 2023 10:22:38 -0800 Subject: [PATCH 4/9] Improve style. --- .../API/GIDAuthorizationFlowProcessor.h | 1 + .../GIDAuthorizationFlowProcessor.m | 5 +---- GoogleSignIn/Sources/GIDSignIn.m | 2 +- .../Tests/Unit/GIDAuthorizationFlowProcessorTest.m | 14 +++++++------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h index 365270f9..e68367b2 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h @@ -30,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN /// /// @param options The @GIDSignInInternalOptions object to provide serverClientID, hostedDomain, /// clientID, scopes, loginHint and extraParams. +/// @param emmSupport The EMM support info string. /// @param completion The block that is called on completion asynchronously. - (void)startWithOptions:(GIDSignInInternalOptions *)options emmSupport:(nullable NSString *)emmSupport diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m index e8cecee6..dff26169 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m @@ -45,8 +45,6 @@ @implementation GIDAuthorizationFlowProcessor { OIDServiceConfiguration *_appAuthConfiguration; } -@synthesize start; - # pragma mark - Public API - (BOOL)isStarted { @@ -74,7 +72,6 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options if (options.configuration.hostedDomain) { additionalParameters[kHostedDomainParameter] = options.configuration.hostedDomain; } - #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST [additionalParameters addEntriesFromDictionary: [GIDEMMSupport parametersWithParameters:options.extraParams @@ -91,7 +88,6 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options OIDServiceConfiguration *appAuthConfiguration = [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpointURL tokenEndpoint:tokenEndpointURL]; - OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc] initWithConfiguration:appAuthConfiguration clientId:options.configuration.clientID @@ -99,6 +95,7 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options redirectURL:redirectURL responseType:OIDResponseTypeCode additionalParameters:additionalParameters]; + _currentAuthorizationFlow = [OIDAuthorizationService presentAuthorizationRequest:request #if TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index b5a3e0e0..8fddd8e4 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -452,7 +452,7 @@ - (id)initPrivate { id keychainHandler = [[GIDKeychainHandler alloc] init]; id httpFetcher = [[GIDHTTPFetcher alloc] init]; id authorizationFlowProcessor = - [[GIDAuthorizationFlowProcessor alloc] init]; + [[GIDAuthorizationFlowProcessor alloc] init]; return [self initWithKeychainHandler:keychainHandler httpFetcher:httpFetcher authorizationFlowProcessor:authorizationFlowProcessor]; diff --git a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m index cd7f945b..ffa9dc61 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m @@ -60,7 +60,7 @@ - (void)setUp { ]).andReturn(_externalUserAgentSession); } -- (void)testStartAndCancelAuthorizationFlow { +- (void)testStartAndCancelAuthorizationFlow_success { XCTestExpectation *expectation = [self expectationWithDescription:@"completion is invoked."]; GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; [_authorizationFlowProcessor startWithOptions:options @@ -77,8 +77,6 @@ - (void)testStartAndCancelAuthorizationFlow { } - (void)testStartAndResumeAuthorizationFlow_success { - OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) - .andReturn(YES); XCTestExpectation *expectation = [self expectationWithDescription:@"completion is invoked."]; GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; [_authorizationFlowProcessor startWithOptions:options @@ -90,14 +88,14 @@ - (void)testStartAndResumeAuthorizationFlow_success { [self waitForExpectationsWithTimeout:1 handler:nil]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); + OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) + .andReturn(YES); NSURL *url = [[NSURL alloc] initWithString:kFakeURL]; [_authorizationFlowProcessor resumeExternalUserAgentFlowWithURL:url]; XCTAssertFalse(_authorizationFlowProcessor.isStarted); } -- (void)testStartAndResumeAuthorizationFlow_fail { - OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) - .andReturn(NO); +- (void)testStartAndFailToResumeAuthorizationFlow { XCTestExpectation *expectation = [self expectationWithDescription:@"completion is invoked."]; GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; [_authorizationFlowProcessor startWithOptions:options @@ -108,7 +106,9 @@ - (void)testStartAndResumeAuthorizationFlow_fail { }]; [self waitForExpectationsWithTimeout:1 handler:nil]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); - + + OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) + .andReturn(NO); NSURL *url = [[NSURL alloc] initWithString:kFakeURL]; [_authorizationFlowProcessor resumeExternalUserAgentFlowWithURL:url]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); From b674379ec27300b42b1e490f1902ae9e2f06e59d Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 9 Jan 2023 11:03:48 -0800 Subject: [PATCH 5/9] Improve documentation and style. --- .../xcschemes/GoogleSignIn-UnitTests.xcscheme | 52 +++++++++++++++++++ .../API/GIDAuthorizationFlowProcessor.h | 2 + .../GIDAuthorizationFlowProcessor.h | 1 + .../GIDAuthorizationFlowProcessor.m | 28 ++++++---- GoogleSignIn/Sources/GIDSignInPreferences.h | 6 +-- .../Unit/GIDAuthorizationFlowProcessorTest.m | 5 +- 6 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme new file mode 100644 index 00000000..f12a4208 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h index e68367b2..eda3dcbd 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h @@ -21,12 +21,14 @@ NS_ASSUME_NONNULL_BEGIN @class GIDSignInInternalOptions; @class OIDAuthorizationResponse; +/// The protocol to control the authorization flow. @protocol GIDAuthorizationFlowProcessor /// The state of the authorization flow. @property(nonatomic, readonly, getter=isStarted) BOOL start; /// Starts the authorization flow. +/// This method sends authorization request to AppAuth OIDAuthorizationService and gets back the response or an error. /// /// @param options The @GIDSignInInternalOptions object to provide serverClientID, hostedDomain, /// clientID, scopes, loginHint and extraParams. diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h index 9320e72a..b416e38f 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h @@ -22,6 +22,7 @@ NS_ASSUME_NONNULL_BEGIN +/// Concrete implementation of the protocol GIDAuthorizationFlowProcessor. @interface GIDAuthorizationFlowProcessor : NSObject @end diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m index dff26169..eb361ad8 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m @@ -38,17 +38,22 @@ static NSString *const kLoginHintParameter = @"login_hint"; static NSString *const kHostedDomainParameter = @"hd"; -@implementation GIDAuthorizationFlowProcessor { - // AppAuth external user-agent session state. - id _currentAuthorizationFlow; - // AppAuth configuration object. - OIDServiceConfiguration *_appAuthConfiguration; -} +@interface GIDAuthorizationFlowProcessor () + +// AppAuth external user-agent session state. +@property(nonatomic, nullable)id currentAuthorizationFlow; + +// AppAuth configuration object. +@property(nonatomic)OIDServiceConfiguration *appAuthConfiguration; + +@end + +@implementation GIDAuthorizationFlowProcessor # pragma mark - Public API - (BOOL)isStarted { - return _currentAuthorizationFlow != nil; + return self.currentAuthorizationFlow != nil; } - (void)startWithOptions:(GIDSignInInternalOptions *)options @@ -72,6 +77,7 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options if (options.configuration.hostedDomain) { additionalParameters[kHostedDomainParameter] = options.configuration.hostedDomain; } + #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST [additionalParameters addEntriesFromDictionary: [GIDEMMSupport parametersWithParameters:options.extraParams @@ -110,8 +116,8 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options } - (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url { - if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) { - _currentAuthorizationFlow = nil; + if ([self.currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) { + self.currentAuthorizationFlow = nil; return YES; } else { return NO; @@ -119,8 +125,8 @@ - (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url { } - (void)cancelAuthenticationFlow { - [_currentAuthorizationFlow cancel]; - _currentAuthorizationFlow = nil; + [self.currentAuthorizationFlow cancel]; + self.currentAuthorizationFlow = nil; } @end diff --git a/GoogleSignIn/Sources/GIDSignInPreferences.h b/GoogleSignIn/Sources/GIDSignInPreferences.h index 5a7654eb..f7f0a637 100644 --- a/GoogleSignIn/Sources/GIDSignInPreferences.h +++ b/GoogleSignIn/Sources/GIDSignInPreferences.h @@ -18,13 +18,13 @@ NS_ASSUME_NONNULL_BEGIN -// The name of the query parameter used for logging the SDK version. +/// The name of the query parameter used for logging the SDK version. extern NSString *const kSDKVersionLoggingParameter; -// The name of the query parameter used for logging the Apple execution environment. +/// The name of the query parameter used for logging the Apple execution environment. extern NSString *const kEnvironmentLoggingParameter; -// Expected path in the URL scheme to be handled. +/// Expected path in the URL scheme to be handled. extern NSString *const kBrowserCallbackPath; NSString* GIDVersion(void); diff --git a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m index ffa9dc61..b6410988 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m @@ -30,6 +30,7 @@ static NSString *const kFakeURL = @"www.fakeURL.com"; static NSString *const kErrorDomain = @"ERROR_DOMAIN"; static NSInteger const kErrorCode = 400; +static NSInteger const kTimeout = 1; @interface GIDAuthorizationFlowProcessorTest : XCTestCase { GIDAuthorizationFlowProcessor *_authorizationFlowProcessor; @@ -69,7 +70,7 @@ - (void)testStartAndCancelAuthorizationFlow_success { NSError *error) { [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self waitForExpectationsWithTimeout:kTimeout handler:nil]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); [_authorizationFlowProcessor cancelAuthenticationFlow]; @@ -104,7 +105,7 @@ - (void)testStartAndFailToResumeAuthorizationFlow { NSError *error) { [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self waitForExpectationsWithTimeout:kTimeout handler:nil]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) From 0c9a202403ed969bc0d751f016f232ce465b1eec Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 9 Jan 2023 16:49:30 -0800 Subject: [PATCH 6/9] Add OIDFakeExternalUserAgentSession for testing. --- .../GIDAuthorizationFlowProcessor.m | 4 +- .../Unit/GIDAuthorizationFlowProcessorTest.m | 22 +++++++--- .../Unit/OIDFakeExternalUserAgentSession.h | 32 ++++++++++++++ .../Unit/OIDFakeExternalUserAgentSession.m | 44 +++++++++++++++++++ 4 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.h create mode 100644 GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.m diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m index eb361ad8..b8b62d2d 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m @@ -40,10 +40,10 @@ @interface GIDAuthorizationFlowProcessor () -// AppAuth external user-agent session state. +/// AppAuth external user-agent session state. @property(nonatomic, nullable)id currentAuthorizationFlow; -// AppAuth configuration object. +/// AppAuth configuration object. @property(nonatomic)OIDServiceConfiguration *appAuthConfiguration; @end diff --git a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m index b6410988..d53adf08 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m @@ -15,7 +15,9 @@ #import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h" #import "GoogleSignIn/Sources/GIDSignInInternalOptions.h" +#import "GoogleSignIn/Tests/Unit/OIDAuthorizationRequest+Testing.h" #import "GoogleSignIn/Tests/Unit/OIDAuthorizationResponse+Testing.h" +#import "GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.h" #import @@ -34,8 +36,8 @@ @interface GIDAuthorizationFlowProcessorTest : XCTestCase { GIDAuthorizationFlowProcessor *_authorizationFlowProcessor; + OIDFakeExternalUserAgentSession *_fakeExternalUserAgentSession; id _authorizationServiceMock; - id _externalUserAgentSession; } @end @@ -46,7 +48,8 @@ - (void)setUp { [super setUp]; _authorizationFlowProcessor = [[GIDAuthorizationFlowProcessor alloc] init]; - _externalUserAgentSession = OCMProtocolMock(@protocol(OIDExternalUserAgentSession)); + _fakeExternalUserAgentSession= [[OIDFakeExternalUserAgentSession alloc] init]; + _authorizationServiceMock = OCMClassMock([OIDAuthorizationService class]); OIDAuthorizationResponse *response = [OIDAuthorizationResponse testInstance]; NSError *error = [self error]; @@ -58,7 +61,7 @@ - (void)setUp { presentingWindow:[OCMArg any] #endif // TARGET_OS_OSX callback:([OCMArg invokeBlockWithArgs:response, error, nil]) - ]).andReturn(_externalUserAgentSession); + ]).andReturn(_fakeExternalUserAgentSession); } - (void)testStartAndCancelAuthorizationFlow_success { @@ -68,6 +71,8 @@ - (void)testStartAndCancelAuthorizationFlow_success { emmSupport:nil completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { + XCTAssertEqualObjects(authorizationResponse.request.clientID, + OIDAuthorizationRequestTestingClientID); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:kTimeout handler:nil]; @@ -84,13 +89,15 @@ - (void)testStartAndResumeAuthorizationFlow_success { emmSupport:nil completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { + XCTAssertEqualObjects(authorizationResponse.request.clientID, + OIDAuthorizationRequestTestingClientID); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:1 handler:nil]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); - OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) - .andReturn(YES); + _fakeExternalUserAgentSession.resumeExternalUserAgentFlow = YES; + NSURL *url = [[NSURL alloc] initWithString:kFakeURL]; [_authorizationFlowProcessor resumeExternalUserAgentFlowWithURL:url]; XCTAssertFalse(_authorizationFlowProcessor.isStarted); @@ -103,13 +110,14 @@ - (void)testStartAndFailToResumeAuthorizationFlow { emmSupport:nil completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { + XCTAssertEqualObjects(authorizationResponse.request.clientID, + OIDAuthorizationRequestTestingClientID); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:kTimeout handler:nil]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); - OCMStub([_externalUserAgentSession resumeExternalUserAgentFlowWithURL:[OCMArg any]]) - .andReturn(NO); + _fakeExternalUserAgentSession.resumeExternalUserAgentFlow = NO; NSURL *url = [[NSURL alloc] initWithString:kFakeURL]; [_authorizationFlowProcessor resumeExternalUserAgentFlowWithURL:url]; XCTAssertTrue(_authorizationFlowProcessor.isStarted); diff --git a/GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.h b/GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.h new file mode 100644 index 00000000..868bd25b --- /dev/null +++ b/GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.h @@ -0,0 +1,32 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#ifdef SWIFT_PACKAGE +@import AppAuth; +#else +#import +#endif + +/// The fake OIDExternalUserAgentSession. +@interface OIDFakeExternalUserAgentSession : NSObject + +/// Set the return value for the method `resumeExternalUserAgentFlowWithURL:`. +/// The defualt value is YES. +@property(nonatomic) BOOL resumeExternalUserAgentFlow; + +@end diff --git a/GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.m b/GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.m new file mode 100644 index 00000000..d3268e61 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.m @@ -0,0 +1,44 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleSignIn/Tests/Unit/OIDFakeExternalUserAgentSession.h" + +@implementation OIDFakeExternalUserAgentSession + +- (instancetype)init { + self = [super init]; + if (self) { + self.resumeExternalUserAgentFlow = YES; + } + return self; +} + +- (void)cancel { + // no op. +} + +- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL { + return self.resumeExternalUserAgentFlow; +} + +- (void)cancelWithCompletion:(nullable void (^)(void))completion { + NSAssert(NO, @"Not implemented."); +} + + +- (void)failExternalUserAgentFlowWithError:(nonnull NSError *)error { + NSAssert(NO, @"Not implemented."); +} + +@end From 17d20bbee4b5db98fa3a16e7c129c29a043c5e32 Mon Sep 17 00:00:00 2001 From: pinlu Date: Tue, 10 Jan 2023 16:50:53 -0800 Subject: [PATCH 7/9] Improve documentation and tests. --- .../API/GIDAuthorizationFlowProcessor.h | 14 +++++++---- .../Unit/GIDAuthorizationFlowProcessorTest.m | 23 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h index eda3dcbd..453b5072 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h @@ -16,11 +16,11 @@ #import -NS_ASSUME_NONNULL_BEGIN - @class GIDSignInInternalOptions; @class OIDAuthorizationResponse; +NS_ASSUME_NONNULL_BEGIN + /// The protocol to control the authorization flow. @protocol GIDAuthorizationFlowProcessor @@ -28,18 +28,22 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly, getter=isStarted) BOOL start; /// Starts the authorization flow. -/// This method sends authorization request to AppAuth OIDAuthorizationService and gets back the response or an error. +/// This method sends authorization request to AppAuth `OIDAuthorizationService` and gets back the +/// response or an error. /// -/// @param options The @GIDSignInInternalOptions object to provide serverClientID, hostedDomain, +/// @param options The `GIDSignInInternalOptions` object to provide serverClientID, hostedDomain, /// clientID, scopes, loginHint and extraParams. /// @param emmSupport The EMM support info string. /// @param completion The block that is called on completion asynchronously. +/// authorizationResponse The response from `OIDAuthorizationService`. +/// error The error from `OIDAuthorizationService`. - (void)startWithOptions:(GIDSignInInternalOptions *)options emmSupport:(nullable NSString *)emmSupport completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error))completion; -/// Handles the custom scheme URL opened by SFSafariViewController to cleanup UI on iOS 10. +/// Handles the custom URL scheme opened by SFSafariViewController and returns control to the +/// client on iOS 10. /// /// @param url The redirect URL invoked by the server. /// @return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise. diff --git a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m index d53adf08..47142075 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m @@ -38,6 +38,7 @@ @interface GIDAuthorizationFlowProcessorTest : XCTestCase { GIDAuthorizationFlowProcessor *_authorizationFlowProcessor; OIDFakeExternalUserAgentSession *_fakeExternalUserAgentSession; id _authorizationServiceMock; + OIDAuthorizationResponse *_fakeResponse; } @end @@ -51,7 +52,7 @@ - (void)setUp { _fakeExternalUserAgentSession= [[OIDFakeExternalUserAgentSession alloc] init]; _authorizationServiceMock = OCMClassMock([OIDAuthorizationService class]); - OIDAuthorizationResponse *response = [OIDAuthorizationResponse testInstance]; + _fakeResponse = [OIDAuthorizationResponse testInstance]; NSError *error = [self error]; OCMStub([_authorizationServiceMock presentAuthorizationRequest:[OCMArg any] @@ -60,7 +61,7 @@ - (void)setUp { #elif TARGET_OS_OSX presentingWindow:[OCMArg any] #endif // TARGET_OS_OSX - callback:([OCMArg invokeBlockWithArgs:response, error, nil]) + callback:([OCMArg invokeBlockWithArgs:_fakeResponse, error, nil]) ]).andReturn(_fakeExternalUserAgentSession); } @@ -71,8 +72,10 @@ - (void)testStartAndCancelAuthorizationFlow_success { emmSupport:nil completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { - XCTAssertEqualObjects(authorizationResponse.request.clientID, - OIDAuthorizationRequestTestingClientID); + XCTAssertEqualObjects(authorizationResponse.accessToken, + _fakeResponse.accessToken); + XCTAssertEqualObjects(authorizationResponse.authorizationCode, + _fakeResponse.authorizationCode); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:kTimeout handler:nil]; @@ -89,8 +92,10 @@ - (void)testStartAndResumeAuthorizationFlow_success { emmSupport:nil completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { - XCTAssertEqualObjects(authorizationResponse.request.clientID, - OIDAuthorizationRequestTestingClientID); + XCTAssertEqualObjects(authorizationResponse.accessToken, + _fakeResponse.accessToken); + XCTAssertEqualObjects(authorizationResponse.authorizationCode, + _fakeResponse.authorizationCode); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -110,8 +115,10 @@ - (void)testStartAndFailToResumeAuthorizationFlow { emmSupport:nil completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { - XCTAssertEqualObjects(authorizationResponse.request.clientID, - OIDAuthorizationRequestTestingClientID); + XCTAssertEqualObjects(authorizationResponse.accessToken, + _fakeResponse.accessToken); + XCTAssertEqualObjects(authorizationResponse.authorizationCode, + _fakeResponse.authorizationCode); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:kTimeout handler:nil]; From 3a8b8d130525370116eb52ebc16de56d78f05300 Mon Sep 17 00:00:00 2001 From: pinlu Date: Wed, 11 Jan 2023 10:27:07 -0800 Subject: [PATCH 8/9] Add self in block --- .../Tests/Unit/GIDAuthorizationFlowProcessorTest.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m index 47142075..b1c5c756 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthorizationFlowProcessorTest.m @@ -73,9 +73,9 @@ - (void)testStartAndCancelAuthorizationFlow_success { completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { XCTAssertEqualObjects(authorizationResponse.accessToken, - _fakeResponse.accessToken); + self->_fakeResponse.accessToken); XCTAssertEqualObjects(authorizationResponse.authorizationCode, - _fakeResponse.authorizationCode); + self->_fakeResponse.authorizationCode); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:kTimeout handler:nil]; @@ -93,9 +93,9 @@ - (void)testStartAndResumeAuthorizationFlow_success { completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { XCTAssertEqualObjects(authorizationResponse.accessToken, - _fakeResponse.accessToken); + self->_fakeResponse.accessToken); XCTAssertEqualObjects(authorizationResponse.authorizationCode, - _fakeResponse.authorizationCode); + self->_fakeResponse.authorizationCode); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -116,9 +116,9 @@ - (void)testStartAndFailToResumeAuthorizationFlow { completion:^(OIDAuthorizationResponse *authorizationResponse, NSError *error) { XCTAssertEqualObjects(authorizationResponse.accessToken, - _fakeResponse.accessToken); + self->_fakeResponse.accessToken); XCTAssertEqualObjects(authorizationResponse.authorizationCode, - _fakeResponse.authorizationCode); + self->_fakeResponse.authorizationCode); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:kTimeout handler:nil]; From 44c50b7d6185e9f4e2ccfca1a0b57e17180b799f Mon Sep 17 00:00:00 2001 From: pinlu Date: Wed, 11 Jan 2023 11:32:34 -0800 Subject: [PATCH 9/9] Remove scheme file. --- .../xcschemes/GoogleSignIn-UnitTests.xcscheme | 52 ------------------- .../API/GIDAuthorizationFlowProcessor.h | 1 + .../GIDAuthorizationFlowProcessor.h | 2 +- 3 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme deleted file mode 100644 index f12a4208..00000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/GoogleSignIn-UnitTests.xcscheme +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h index 453b5072..0fa96065 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly, getter=isStarted) BOOL start; /// Starts the authorization flow. +/// /// This method sends authorization request to AppAuth `OIDAuthorizationService` and gets back the /// response or an error. /// diff --git a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h index b416e38f..e8703314 100644 --- a/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h +++ b/GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN -/// Concrete implementation of the protocol GIDAuthorizationFlowProcessor. +/// Concrete implementation of the protocol `GIDAuthorizationFlowProcessor`. @interface GIDAuthorizationFlowProcessor : NSObject @end