diff --git a/GoogleSignIn/Sources/GIDConfiguration.m b/GoogleSignIn/Sources/GIDConfiguration.m index 34ba3c8d..693179c6 100644 --- a/GoogleSignIn/Sources/GIDConfiguration.m +++ b/GoogleSignIn/Sources/GIDConfiguration.m @@ -26,6 +26,9 @@ // The key for the openIDRealm property to be used with NSSecureCoding. static NSString *const kOpenIDRealmKey = @"openIDRealm"; +// The key for the nonce property to be used with NSSecureCoding. +static NSString *const kNonceKey = @"nonce"; + NS_ASSUME_NONNULL_BEGIN @implementation GIDConfiguration @@ -34,7 +37,8 @@ - (instancetype)initWithClientID:(NSString *)clientID { return [self initWithClientID:clientID serverClientID:nil hostedDomain:nil - openIDRealm:nil]; + openIDRealm:nil + nonce:nil]; } - (instancetype)initWithClientID:(NSString *)clientID @@ -42,19 +46,22 @@ - (instancetype)initWithClientID:(NSString *)clientID return [self initWithClientID:clientID serverClientID:serverClientID hostedDomain:nil - openIDRealm:nil]; + openIDRealm:nil + nonce:nil]; } - (instancetype)initWithClientID:(NSString *)clientID serverClientID:(nullable NSString *)serverClientID hostedDomain:(nullable NSString *)hostedDomain - openIDRealm:(nullable NSString *)openIDRealm { + openIDRealm:(nullable NSString *)openIDRealm + nonce:(nullable NSString *)nonce { self = [super init]; if (self) { _clientID = [clientID copy]; _serverClientID = [serverClientID copy]; _hostedDomain = [hostedDomain copy]; _openIDRealm = [openIDRealm copy]; + _nonce = [nonce copy]; } return self; } @@ -62,13 +69,14 @@ - (instancetype)initWithClientID:(NSString *)clientID // Extend NSObject's default description for easier debugging. - (NSString *)description { return [NSString stringWithFormat: - @"<%@: %p, clientID: %@, serverClientID: %@, hostedDomain: %@, openIDRealm: %@>", + @"<%@: %p, clientID: %@, serverClientID: %@, hostedDomain: %@, openIDRealm: %@, nonce: $@>", NSStringFromClass([self class]), self, _clientID, _serverClientID, _hostedDomain, - _openIDRealm]; + _openIDRealm, + _nonce]; } #pragma mark - NSCopying @@ -89,6 +97,7 @@ - (nullable instancetype)initWithCoder:(NSCoder *)coder { NSString *serverClientID = [coder decodeObjectOfClass:[NSString class] forKey:kServerClientIDKey]; NSString *hostedDomain = [coder decodeObjectOfClass:[NSString class] forKey:kHostedDomainKey]; NSString *openIDRealm = [coder decodeObjectOfClass:[NSString class] forKey:kOpenIDRealmKey]; + NSString *nonce = [coder decodeObjectOfClass:[NSString class] forKey:kNonceKey]; // We must have a client ID. if (!clientID) { @@ -98,7 +107,8 @@ - (nullable instancetype)initWithCoder:(NSCoder *)coder { return [self initWithClientID:clientID serverClientID:serverClientID hostedDomain:hostedDomain - openIDRealm:openIDRealm]; + openIDRealm:openIDRealm + nonce:nonce]; } - (void)encodeWithCoder:(NSCoder *)coder { @@ -106,6 +116,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:_serverClientID forKey:kServerClientIDKey]; [coder encodeObject:_hostedDomain forKey:kHostedDomainKey]; [coder encodeObject:_openIDRealm forKey:kOpenIDRealmKey]; + [coder encodeObject:_nonce forKey:kNonceKey]; } @end diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 828ac5b6..0ef8bc50 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -102,7 +102,8 @@ - (GIDConfiguration *)configuration { _cachedConfiguration = [[GIDConfiguration alloc] initWithClientID:clientID serverClientID:serverClientID hostedDomain:[self hostedDomain] - openIDRealm:openIDRealm]; + openIDRealm:openIDRealm + nonce:nil]; }; } return _cachedConfiguration; diff --git a/GoogleSignIn/Sources/GIDSignIn.m b/GoogleSignIn/Sources/GIDSignIn.m index 429c1666..108b8856 100644 --- a/GoogleSignIn/Sources/GIDSignIn.m +++ b/GoogleSignIn/Sources/GIDSignIn.m @@ -269,6 +269,7 @@ - (void)signInWithPresentingViewController:(UIViewController *)presentingViewCon - (void)addScopes:(NSArray *)scopes presentingViewController:(UIViewController *)presentingViewController completion:(nullable GIDSignInCompletion)completion { + GIDConfiguration *configuration = self.currentUser.configuration; GIDSignInInternalOptions *options = [GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration @@ -570,21 +571,31 @@ - (void)authenticateInteractivelyWithOptions:(GIDSignInInternalOptions *)options #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST [additionalParameters addEntriesFromDictionary: - [GIDEMMSupport parametersWithParameters:options.extraParams - emmSupport:emmSupport - isPasscodeInfoRequired:NO]]; + [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(); + NSString *codeVerifier = [OIDAuthorizationRequest generateCodeVerifier]; + NSString *codeChallenge = [OIDAuthorizationRequest codeChallengeS256ForVerifier:codeVerifier]; + NSString *nonce = options.configuration.nonce ? options.configuration.nonce : [OIDAuthorizationRequest generateState]; + OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc] initWithConfiguration:_appAuthConfiguration clientId:options.configuration.clientID - scopes:options.scopes + clientSecret:nil + scope:[OIDScopeUtilities scopesWithArray:options.scopes] redirectURL:redirectURL responseType:OIDResponseTypeCode + state:[OIDAuthorizationRequest generateState] + nonce:nonce + codeVerifier:codeVerifier + codeChallenge:codeChallenge + codeChallengeMethod:OIDOAuthorizationRequestCodeChallengeMethodS256 additionalParameters:additionalParameters]; _currentAuthorizationFlow = [OIDAuthorizationService @@ -1031,13 +1042,14 @@ + (nullable GIDConfiguration *)configurationFromBundle:(NSBundle *)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]; + openIDRealm:openIDRealm + nonce:nil]; } return configuration; diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h index 4902fa37..97b0424a 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h @@ -37,6 +37,9 @@ NS_ASSUME_NONNULL_BEGIN /// Identifier in the OpenID Connect ID token. @property(nonatomic, readonly, nullable) NSString *openIDRealm; +/// A value generated by the app that enables replay protection. +@property(nonatomic, readonly, nullable) NSString *nonce; + /// Unavailable. Please use `initWithClientID:` or one of the other initializers below. /// :nodoc: + (instancetype)new NS_UNAVAILABLE; @@ -69,7 +72,8 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithClientID:(NSString *)clientID serverClientID:(nullable NSString *)serverClientID hostedDomain:(nullable NSString *)hostedDomain - openIDRealm:(nullable NSString *)openIDRealm NS_DESIGNATED_INITIALIZER; + openIDRealm:(nullable NSString *)openIDRealm + nonce:(nullable NSString *)nonce NS_DESIGNATED_INITIALIZER; @end diff --git a/GoogleSignIn/Tests/Unit/GIDConfiguration+Testing.m b/GoogleSignIn/Tests/Unit/GIDConfiguration+Testing.m index 72bc9106..134149ac 100644 --- a/GoogleSignIn/Tests/Unit/GIDConfiguration+Testing.m +++ b/GoogleSignIn/Tests/Unit/GIDConfiguration+Testing.m @@ -56,7 +56,8 @@ + (instancetype)testInstance { return [[GIDConfiguration alloc] initWithClientID:OIDAuthorizationRequestTestingClientID serverClientID:kServerClientID hostedDomain:kHostedDomain - openIDRealm:kOpenIDRealm]; + openIDRealm:kOpenIDRealm + nonce:nil]; } @end diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 7a81ede6..f5d6050d 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -639,10 +639,11 @@ - (void)testAddScopes { } - (void)testOpenIDRealm { - _signIn.configuration = [[GIDConfiguration alloc] initWithClientID:kClientId - serverClientID:nil - hostedDomain:nil - openIDRealm:kOpenIDRealm]; + _signIn._configuration = [[GIDConfiguration alloc] initWithClientID:kClientId + serverClientID:nil + hostedDomain:nil + openIDRealm:kOpenIDRealm + nonce:nil]; [self OAuthLoginWithAddScopesFlow:NO authError:nil @@ -674,10 +675,12 @@ - (void)testOAuthLogin_LoginHint { } - (void)testOAuthLogin_HostedDomain { - _signIn.configuration = [[GIDConfiguration alloc] initWithClientID:kClientId - serverClientID:nil - hostedDomain:kHostedDomain - openIDRealm:nil]; + + _signIn._configuration = [[GIDConfiguration alloc] initWithClientID:kClientId + serverClientID:nil + hostedDomain:kHostedDomain + openIDRealm:nil + nonce:nil]; [self OAuthLoginWithAddScopesFlow:NO authError:nil