Skip to content

Commit

Permalink
Start the incremental authorization flow by creating `OIDAuthorizatio…
Browse files Browse the repository at this point in the history
…nRequest`. (#406)
  • Loading branch information
brnnmrls authored May 17, 2024
1 parent 4b7802d commit 6e081f4
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 42 deletions.
5 changes: 1 addition & 4 deletions GoogleSignIn/Sources/GIDGoogleUser.m
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -43,10 +44,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";

Expand Down
18 changes: 1 addition & 17 deletions GoogleSignIn/Sources/GIDSignIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -69,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";

Expand Down Expand Up @@ -124,14 +116,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;

Expand Down
41 changes: 41 additions & 0 deletions GoogleSignIn/Sources/GIDSignInConstants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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 <Foundation/Foundation.h>

/// 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;

/// 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;
29 changes: 29 additions & 0 deletions GoogleSignIn/Sources/GIDSignInConstants.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 <Foundation/Foundation.h>

#import "GoogleSignIn/Sources/GIDSignInConstants.h"

NSString *const kAuthorizationURLTemplate = @"https://%@/o/oauth2/v2/auth";
NSString *const kTokenURLTemplate = @"https://%@/token";
NSString *const kBrowserCallbackPath = @"/oauth2callback";

NSString *const kAudienceParameter = @"audience";
NSString *const kOpenIDRealmParameter = @"openid.realm";
NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes";
NSString *const kLoginHintParameter = @"login_hint";
NSString *const kHostedDomainParameter = @"hd";
16 changes: 8 additions & 8 deletions GoogleSignIn/Sources/GIDSignInInternalOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<GIDVerifiableAccountDetail *> *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;
Expand All @@ -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<NSString *> *scopes;
Expand All @@ -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<GIDVerifiableAccountDetail *> *)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
Expand Down
4 changes: 2 additions & 2 deletions GoogleSignIn/Sources/GIDSignInInternalOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,39 @@

#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h"
#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h"
#import "GoogleSignIn/Sources/GIDSignInConstants.h"
#import "GoogleSignIn/Sources/GIDSignInPreferences.h"

#if TARGET_OS_IOS
@import GTMAppAuth;

@implementation GIDVerifyAccountDetail
#ifdef SWIFT_PACKAGE
@import AppAuth;
@import GTMSessionFetcherCore;
#else
#import <AppAuth/OIDAuthorizationRequest.h>
#import <AppAuth/OIDResponseTypes.h>
#import <AppAuth/OIDServiceConfiguration.h>
#endif

#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST

@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;
}
Expand Down Expand Up @@ -102,15 +126,47 @@ - (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<NSString *> *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.
NSString *redirectURI =
[NSString stringWithFormat:@"%@:%@", [schemes clientIdentifierScheme], kBrowserCallbackPath];
NSURL *redirectURL = [NSURL URLWithString:redirectURI];

NSMutableDictionary<NSString *, NSString *> *additionalParameters = [@{} mutableCopy];
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[kSDKVersionLoggingParameter] = GIDVersion();
additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment();

NSMutableArray *scopes;
for (GIDVerifiableAccountDetail *detail in options.accountDetailsToVerify) {
NSString *scopeString = [detail scope];
if (scopeString) {
[scopes addObject:scopeString];
}
}

// 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
Expand Down Expand Up @@ -144,4 +200,4 @@ - (void)assertValidPresentingViewController:(GIDSignInInternalOptions *)options

@end

#endif // TARGET_OS_IOS
#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#import <TargetConditionals.h>

#if TARGET_OS_IOS
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST

#import <Foundation/Foundation.h>

Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
* @brief Initializes a GIDFakeMainBundle object with `nil` to all of the designated initializer's parameters.
*/
- (instancetype)init;

/**
* @fn startFaking:
* @brief Starts faking [NSBundle mainBundle]
Expand Down
4 changes: 2 additions & 2 deletions GoogleSignIn/Tests/Unit/GIDSignInInternalOptionsTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]);
Expand Down
6 changes: 4 additions & 2 deletions GoogleSignIn/Tests/Unit/GIDVerifyAccountDetailTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#import <XCTest/XCTest.h>

#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"
Expand Down Expand Up @@ -159,6 +159,8 @@ - (void)testCurrentUserException {
}
}

// TODO(#405): Write tests for request and response handling.

- (void)testPresentingViewControllerException {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull"
Expand Down Expand Up @@ -221,4 +223,4 @@ - (void)testSchemesNotSupportedException {

@end

#endif // TARGET_OS_IOS
#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST

0 comments on commit 6e081f4

Please sign in to comment.