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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@

#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/GIDAuthorizationUtil.h"
#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h"
#import "GoogleSignIn/Sources/GIDSignInPreferences.h"

#ifdef SWIFT_PACKAGE
@import AppAuth;
Expand All @@ -31,20 +27,10 @@

NS_ASSUME_NONNULL_BEGIN

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

@interface GIDAuthorizationFlowProcessor ()

/// AppAuth external user-agent session state.
@property(nonatomic, nullable)id<OIDExternalUserAgentSession> currentAuthorizationFlow;

/// AppAuth configuration object.
@property(nonatomic)OIDServiceConfiguration *appAuthConfiguration;
@property(nonatomic, nullable) id<OIDExternalUserAgentSession> currentAuthorizationFlow;

@end

Expand All @@ -60,47 +46,9 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options
emmSupport:(nullable NSString *)emmSupport
completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse,
NSError *_Nullable error))completion {
GIDSignInCallbackSchemes *schemes =
[[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID];
NSString *urlString = [NSString stringWithFormat:@"%@:%@",
[schemes clientIdentifierScheme], kBrowserCallbackPath];
NSURL *redirectURL = [NSURL URLWithString:urlString];

NSMutableDictionary<NSString *, NSString *> *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];
[GIDAuthorizationUtil authorizationRequestWithOptions:options
emmSupport:emmSupport];

_currentAuthorizationFlow = [OIDAuthorizationService
presentAuthorizationRequest:request
Expand Down
50 changes: 50 additions & 0 deletions GoogleSignIn/Sources/GIDAuthorizationUtil.h
Original file line number Diff line number Diff line change
@@ -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 <Foundation/Foundation.h>

@class OIDAuthorizationRequest;
@class GIDSignInInternalOptions;

NS_ASSUME_NONNULL_BEGIN

/// The util class for authorization process.
@interface GIDAuthorizationUtil : NSObject

/// Creates the request to AppAuth to start the authorization flow.
///
/// @param options The `GIDSignInInternalOptions` object to provide serverClientID, hostedDomain,
/// clientID, scopes, loginHint and extraParams.
/// @param emmSupport The EMM support info string.
+ (OIDAuthorizationRequest *)
authorizationRequestWithOptions:(GIDSignInInternalOptions *)options
emmSupport:(nullable NSString *)emmSupport;

/// Unions granted scopes with new scopes or returns an error if the new scopes are the subset of
/// the granted scopes.
///
/// @param scopes The existing scopes.
/// @param newScopes The new scopes to add.
/// @param error The reference to the error.
/// @return The array of all scopes or nil if there is an error.
+ (nullable NSArray<NSString *> *)
resolvedScopesFromGrantedScoped:(NSArray<NSString *> *)scopes
withNewScopes:(NSArray<NSString *> *)newScopes
error:(NSError * __autoreleasing *)error;

@end

NS_ASSUME_NONNULL_END
106 changes: 106 additions & 0 deletions GoogleSignIn/Sources/GIDAuthorizationUtil.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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/GIDAuthorizationUtil.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 <AppAuth/AppAuth.h>
#endif

NS_ASSUME_NONNULL_BEGIN

@implementation GIDAuthorizationUtil

+ (OIDAuthorizationRequest *)
authorizationRequestWithOptions:(GIDSignInInternalOptions *)options
emmSupport:(nullable NSString *)emmSupport {
GIDSignInCallbackSchemes *schemes =
[[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID];
NSString *urlString = [NSString stringWithFormat:@"%@:%@",
[schemes clientIdentifierScheme], kBrowserCallbackPath];
NSURL *redirectURL = [NSURL URLWithString:urlString];

NSMutableDictionary<NSString *, NSString *> *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];

return request;
}

+ (nullable NSArray<NSString *> *)
resolvedScopesFromGrantedScoped:(NSArray<NSString *> *)scopes
withNewScopes:(NSArray<NSString *> *)newScopes
error:(NSError * __autoreleasing *)error {
NSMutableSet<NSString *> *grantedScopes = [NSMutableSet setWithArray:scopes];
NSSet<NSString *> *requestedScopes = [NSSet setWithArray:newScopes];

if ([requestedScopes isSubsetOfSet:grantedScopes]) {
// All requested scopes have already been granted, generate an error.
*error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeScopesAlreadyGranted
userInfo:nil];
return nil;
}

// Use the union of granted and requested scopes.
[grantedScopes unionSet:requestedScopes];
return [grantedScopes allObjects];
}

@end

NS_ASSUME_NONNULL_END
2 changes: 0 additions & 2 deletions GoogleSignIn/Sources/GIDGoogleUser.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,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.
Expand Down
46 changes: 19 additions & 27 deletions GoogleSignIn/Sources/GIDSignIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h"
#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h"
#import "GoogleSignIn/Sources/GIDAuthorizationUtil.h"
#import "GoogleSignIn/Sources/GIDHTTPFetcher/API/GIDHTTPFetcher.h"
#import "GoogleSignIn/Sources/GIDHTTPFetcher/Implementations/GIDHTTPFetcher.h"
#import "GoogleSignIn/Sources/GIDEMMSupport.h"
Expand Down Expand Up @@ -75,6 +76,9 @@

NS_ASSUME_NONNULL_BEGIN

// The EMM support version
NSString *const kEMMVersion = @"1";

// The name of the query parameter used for logging the restart of auth from EMM callback.
static NSString *const kEMMRestartAuthParameter = @"emmres";

Expand All @@ -84,9 +88,6 @@
// Expected path for EMM callback.
static NSString *const kEMMCallbackPath = @"/emmcallback";

// The EMM support version
static NSString *const kEMMVersion = @"1";

// The error code for Google Identity.
NSErrorDomain const kGIDSignInErrorDomain = @"com.google.GIDSignIn";

Expand All @@ -111,8 +112,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";

Expand Down Expand Up @@ -260,35 +259,28 @@ - (void)signInWithPresentingViewController:(UIViewController *)presentingViewCon
- (void)addScopes:(NSArray<NSString *> *)scopes
presentingViewController:(UIViewController *)presentingViewController
completion:(nullable GIDSignInCompletion)completion {
GIDConfiguration *configuration = self.currentUser.configuration;
GIDSignInInternalOptions *options =
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
presentingViewController:presentingViewController
loginHint:self.currentUser.profile.email
addScopesFlow:YES
completion:completion];

NSSet<NSString *> *requestedScopes = [NSSet setWithArray:scopes];
NSMutableSet<NSString *> *grantedScopes =
[NSMutableSet setWithArray:self.currentUser.grantedScopes];

// Check to see if all requested scopes have already been granted.
if ([requestedScopes isSubsetOfSet:grantedScopes]) {
// All requested scopes have already been granted, notify callback of failure.
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeScopesAlreadyGranted
userInfo:nil];
NSError *error;
NSArray<NSString *> *allScopes =
[GIDAuthorizationUtil resolvedScopesFromGrantedScoped:self.currentUser.grantedScopes
withNewScopes:scopes
error:&error];
if (error) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, error);
});
}
return;
}

// Use the union of granted and requested scopes.
[grantedScopes unionSet:requestedScopes];
options.scopes = [grantedScopes allObjects];

GIDConfiguration *configuration = self.currentUser.configuration;
GIDSignInInternalOptions *options =
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
presentingViewController:presentingViewController
loginHint:self.currentUser.profile.email
addScopesFlow:YES
completion:completion];
options.scopes = allScopes;

[self signInWithOptions:options];
}
Expand Down
9 changes: 9 additions & 0 deletions GoogleSignIn/Sources/GIDSignInPreferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ extern NSString *const kSDKVersionLoggingParameter;
/// The name of the query parameter used for logging the Apple execution environment.
extern NSString *const kEnvironmentLoggingParameter;

/// The name of the query parameter for the token exchange endpoint.
extern NSString *const kAudienceParameter;

extern NSString *const kIncludeGrantedScopesParameter;

extern NSString *const kLoginHintParameter;

extern NSString *const kHostedDomainParameter;

/// Expected path in the URL scheme to be handled.
extern NSString *const kBrowserCallbackPath;

Expand Down
6 changes: 6 additions & 0 deletions GoogleSignIn/Sources/GIDSignInPreferences.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@

NS_ASSUME_NONNULL_BEGIN

/// Parameters for the auth and token exchange endpoints.
NSString *const kAudienceParameter = @"audience";
NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes";
NSString *const kLoginHintParameter = @"login_hint";
NSString *const kHostedDomainParameter = @"hd";
NSString *const kSDKVersionLoggingParameter = @"gpsdk";
NSString *const kEnvironmentLoggingParameter = @"gidenv";

NSString *const kBrowserCallbackPath = @"/oauth2callback";

static NSString *const kLSOServer = @"accounts.google.com";
Expand Down
7 changes: 5 additions & 2 deletions GoogleSignIn/Sources/GIDSignIn_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#import <AppKit/AppKit.h>
#endif

NS_ASSUME_NONNULL_BEGIN

@class GIDGoogleUser;
@class GIDSignInInternalOptions;

Expand All @@ -34,6 +32,11 @@ NS_ASSUME_NONNULL_BEGIN
@protocol GIDKeychainHandler;
@protocol GIDProfileDataFetcher;

NS_ASSUME_NONNULL_BEGIN

/// The EMM support version.
extern NSString *const kEMMVersion;

/// Represents a completion block that takes a `GIDSignInResult` on success or an error if the
/// operation was unsuccessful.
typedef void (^GIDSignInCompletion)(GIDSignInResult *_Nullable signInResult,
Expand Down
Loading