Skip to content

Commit 2138a3a

Browse files
authored
Add GIDAuthorizationUtil class. (#288)
1 parent af9540c commit 2138a3a

File tree

10 files changed

+415
-297
lines changed

10 files changed

+415
-297
lines changed

GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,8 @@
1616

1717
#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h"
1818

19-
#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h"
20-
21-
#import "GoogleSignIn/Sources/GIDEMMSupport.h"
22-
#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h"
19+
#import "GoogleSignIn/Sources/GIDAuthorizationUtil.h"
2320
#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h"
24-
#import "GoogleSignIn/Sources/GIDSignInPreferences.h"
2521

2622
#ifdef SWIFT_PACKAGE
2723
@import AppAuth;
@@ -31,20 +27,10 @@
3127

3228
NS_ASSUME_NONNULL_BEGIN
3329

34-
// Parameters for the auth and token exchange endpoints.
35-
static NSString *const kAudienceParameter = @"audience";
36-
37-
static NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes";
38-
static NSString *const kLoginHintParameter = @"login_hint";
39-
static NSString *const kHostedDomainParameter = @"hd";
40-
4130
@interface GIDAuthorizationFlowProcessor ()
4231

4332
/// AppAuth external user-agent session state.
44-
@property(nonatomic, nullable)id<OIDExternalUserAgentSession> currentAuthorizationFlow;
45-
46-
/// AppAuth configuration object.
47-
@property(nonatomic)OIDServiceConfiguration *appAuthConfiguration;
33+
@property(nonatomic, nullable) id<OIDExternalUserAgentSession> currentAuthorizationFlow;
4834

4935
@end
5036

@@ -60,47 +46,9 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options
6046
emmSupport:(nullable NSString *)emmSupport
6147
completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse,
6248
NSError *_Nullable error))completion {
63-
GIDSignInCallbackSchemes *schemes =
64-
[[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID];
65-
NSString *urlString = [NSString stringWithFormat:@"%@:%@",
66-
[schemes clientIdentifierScheme], kBrowserCallbackPath];
67-
NSURL *redirectURL = [NSURL URLWithString:urlString];
68-
69-
NSMutableDictionary<NSString *, NSString *> *additionalParameters = [@{} mutableCopy];
70-
additionalParameters[kIncludeGrantedScopesParameter] = @"true";
71-
if (options.configuration.serverClientID) {
72-
additionalParameters[kAudienceParameter] = options.configuration.serverClientID;
73-
}
74-
if (options.loginHint) {
75-
additionalParameters[kLoginHintParameter] = options.loginHint;
76-
}
77-
if (options.configuration.hostedDomain) {
78-
additionalParameters[kHostedDomainParameter] = options.configuration.hostedDomain;
79-
}
80-
81-
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
82-
[additionalParameters addEntriesFromDictionary:
83-
[GIDEMMSupport parametersWithParameters:options.extraParams
84-
emmSupport:emmSupport
85-
isPasscodeInfoRequired:NO]];
86-
#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST
87-
[additionalParameters addEntriesFromDictionary:options.extraParams];
88-
#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST
89-
additionalParameters[kSDKVersionLoggingParameter] = GIDVersion();
90-
additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment();
91-
92-
NSURL *authorizationEndpointURL = [GIDSignInPreferences authorizationEndpointURL];
93-
NSURL *tokenEndpointURL = [GIDSignInPreferences tokenEndpointURL];
94-
OIDServiceConfiguration *appAuthConfiguration =
95-
[[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpointURL
96-
tokenEndpoint:tokenEndpointURL];
9749
OIDAuthorizationRequest *request =
98-
[[OIDAuthorizationRequest alloc] initWithConfiguration:appAuthConfiguration
99-
clientId:options.configuration.clientID
100-
scopes:options.scopes
101-
redirectURL:redirectURL
102-
responseType:OIDResponseTypeCode
103-
additionalParameters:additionalParameters];
50+
[GIDAuthorizationUtil authorizationRequestWithOptions:options
51+
emmSupport:emmSupport];
10452

10553
_currentAuthorizationFlow = [OIDAuthorizationService
10654
presentAuthorizationRequest:request
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <Foundation/Foundation.h>
18+
19+
@class OIDAuthorizationRequest;
20+
@class GIDSignInInternalOptions;
21+
22+
NS_ASSUME_NONNULL_BEGIN
23+
24+
/// The util class for authorization process.
25+
@interface GIDAuthorizationUtil : NSObject
26+
27+
/// Creates the request to AppAuth to start the authorization flow.
28+
///
29+
/// @param options The `GIDSignInInternalOptions` object to provide serverClientID, hostedDomain,
30+
/// clientID, scopes, loginHint and extraParams.
31+
/// @param emmSupport The EMM support info string.
32+
+ (OIDAuthorizationRequest *)
33+
authorizationRequestWithOptions:(GIDSignInInternalOptions *)options
34+
emmSupport:(nullable NSString *)emmSupport;
35+
36+
/// Unions granted scopes with new scopes or returns an error if the new scopes are the subset of
37+
/// the granted scopes.
38+
///
39+
/// @param scopes The existing scopes.
40+
/// @param newScopes The new scopes to add.
41+
/// @param error The reference to the error.
42+
/// @return The array of all scopes or nil if there is an error.
43+
+ (nullable NSArray<NSString *> *)
44+
resolvedScopesFromGrantedScoped:(NSArray<NSString *> *)scopes
45+
withNewScopes:(NSArray<NSString *> *)newScopes
46+
error:(NSError * __autoreleasing *)error;
47+
48+
@end
49+
50+
NS_ASSUME_NONNULL_END
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "GoogleSignIn/Sources/GIDAuthorizationUtil.h"
18+
19+
#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h"
20+
21+
#import "GoogleSignIn/Sources/GIDEMMSupport.h"
22+
#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h"
23+
#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h"
24+
#import "GoogleSignIn/Sources/GIDSignInPreferences.h"
25+
26+
#ifdef SWIFT_PACKAGE
27+
@import AppAuth;
28+
#else
29+
#import <AppAuth/AppAuth.h>
30+
#endif
31+
32+
NS_ASSUME_NONNULL_BEGIN
33+
34+
@implementation GIDAuthorizationUtil
35+
36+
+ (OIDAuthorizationRequest *)
37+
authorizationRequestWithOptions:(GIDSignInInternalOptions *)options
38+
emmSupport:(nullable NSString *)emmSupport {
39+
GIDSignInCallbackSchemes *schemes =
40+
[[GIDSignInCallbackSchemes alloc] initWithClientIdentifier:options.configuration.clientID];
41+
NSString *urlString = [NSString stringWithFormat:@"%@:%@",
42+
[schemes clientIdentifierScheme], kBrowserCallbackPath];
43+
NSURL *redirectURL = [NSURL URLWithString:urlString];
44+
45+
NSMutableDictionary<NSString *, NSString *> *additionalParameters = [@{} mutableCopy];
46+
additionalParameters[kIncludeGrantedScopesParameter] = @"true";
47+
if (options.configuration.serverClientID) {
48+
additionalParameters[kAudienceParameter] = options.configuration.serverClientID;
49+
}
50+
if (options.loginHint) {
51+
additionalParameters[kLoginHintParameter] = options.loginHint;
52+
}
53+
if (options.configuration.hostedDomain) {
54+
additionalParameters[kHostedDomainParameter] = options.configuration.hostedDomain;
55+
}
56+
57+
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
58+
[additionalParameters addEntriesFromDictionary:
59+
[GIDEMMSupport parametersWithParameters:options.extraParams
60+
emmSupport:emmSupport
61+
isPasscodeInfoRequired:NO]];
62+
#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST
63+
[additionalParameters addEntriesFromDictionary:options.extraParams];
64+
#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST
65+
additionalParameters[kSDKVersionLoggingParameter] = GIDVersion();
66+
additionalParameters[kEnvironmentLoggingParameter] = GIDEnvironment();
67+
68+
NSURL *authorizationEndpointURL = [GIDSignInPreferences authorizationEndpointURL];
69+
NSURL *tokenEndpointURL = [GIDSignInPreferences tokenEndpointURL];
70+
OIDServiceConfiguration *appAuthConfiguration =
71+
[[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpointURL
72+
tokenEndpoint:tokenEndpointURL];
73+
OIDAuthorizationRequest *request =
74+
[[OIDAuthorizationRequest alloc] initWithConfiguration:appAuthConfiguration
75+
clientId:options.configuration.clientID
76+
scopes:options.scopes
77+
redirectURL:redirectURL
78+
responseType:OIDResponseTypeCode
79+
additionalParameters:additionalParameters];
80+
81+
return request;
82+
}
83+
84+
+ (nullable NSArray<NSString *> *)
85+
resolvedScopesFromGrantedScoped:(NSArray<NSString *> *)scopes
86+
withNewScopes:(NSArray<NSString *> *)newScopes
87+
error:(NSError * __autoreleasing *)error {
88+
NSMutableSet<NSString *> *grantedScopes = [NSMutableSet setWithArray:scopes];
89+
NSSet<NSString *> *requestedScopes = [NSSet setWithArray:newScopes];
90+
91+
if ([requestedScopes isSubsetOfSet:grantedScopes]) {
92+
// All requested scopes have already been granted, generate an error.
93+
*error = [NSError errorWithDomain:kGIDSignInErrorDomain
94+
code:kGIDSignInErrorCodeScopesAlreadyGranted
95+
userInfo:nil];
96+
return nil;
97+
}
98+
99+
// Use the union of granted and requested scopes.
100+
[grantedScopes unionSet:requestedScopes];
101+
return [grantedScopes allObjects];
102+
}
103+
104+
@end
105+
106+
NS_ASSUME_NONNULL_END

GoogleSignIn/Sources/GIDGoogleUser.m

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@
4242
static NSString *const kProfileDataKey = @"profileData";
4343
static NSString *const kAuthStateKey = @"authState";
4444

45-
// Parameters for the token exchange endpoint.
46-
static NSString *const kAudienceParameter = @"audience";
4745
static NSString *const kOpenIDRealmParameter = @"openid.realm";
4846

4947
// Additional parameter names for EMM.

GoogleSignIn/Sources/GIDSignIn.m

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h"
2525
#import "GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h"
26+
#import "GoogleSignIn/Sources/GIDAuthorizationUtil.h"
2627
#import "GoogleSignIn/Sources/GIDHTTPFetcher/API/GIDHTTPFetcher.h"
2728
#import "GoogleSignIn/Sources/GIDHTTPFetcher/Implementations/GIDHTTPFetcher.h"
2829
#import "GoogleSignIn/Sources/GIDEMMSupport.h"
@@ -75,6 +76,9 @@
7576

7677
NS_ASSUME_NONNULL_BEGIN
7778

79+
// The EMM support version
80+
NSString *const kEMMVersion = @"1";
81+
7882
// The name of the query parameter used for logging the restart of auth from EMM callback.
7983
static NSString *const kEMMRestartAuthParameter = @"emmres";
8084

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

87-
// The EMM support version
88-
static NSString *const kEMMVersion = @"1";
89-
9091
// The error code for Google Identity.
9192
NSErrorDomain const kGIDSignInErrorDomain = @"com.google.GIDSignIn";
9293

@@ -111,8 +112,6 @@
111112
// The delay before the new sign-in flow can be presented after the existing one is cancelled.
112113
static const NSTimeInterval kPresentationDelayAfterCancel = 1.0;
113114

114-
// Parameters for the auth and token exchange endpoints.
115-
static NSString *const kAudienceParameter = @"audience";
116115
// See b/11669751 .
117116
static NSString *const kOpenIDRealmParameter = @"openid.realm";
118117

@@ -260,35 +259,28 @@ - (void)signInWithPresentingViewController:(UIViewController *)presentingViewCon
260259
- (void)addScopes:(NSArray<NSString *> *)scopes
261260
presentingViewController:(UIViewController *)presentingViewController
262261
completion:(nullable GIDSignInCompletion)completion {
263-
GIDConfiguration *configuration = self.currentUser.configuration;
264-
GIDSignInInternalOptions *options =
265-
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
266-
presentingViewController:presentingViewController
267-
loginHint:self.currentUser.profile.email
268-
addScopesFlow:YES
269-
completion:completion];
270-
271-
NSSet<NSString *> *requestedScopes = [NSSet setWithArray:scopes];
272-
NSMutableSet<NSString *> *grantedScopes =
273-
[NSMutableSet setWithArray:self.currentUser.grantedScopes];
274-
275-
// Check to see if all requested scopes have already been granted.
276-
if ([requestedScopes isSubsetOfSet:grantedScopes]) {
277-
// All requested scopes have already been granted, notify callback of failure.
278-
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
279-
code:kGIDSignInErrorCodeScopesAlreadyGranted
280-
userInfo:nil];
262+
NSError *error;
263+
NSArray<NSString *> *allScopes =
264+
[GIDAuthorizationUtil resolvedScopesFromGrantedScoped:self.currentUser.grantedScopes
265+
withNewScopes:scopes
266+
error:&error];
267+
if (error) {
281268
if (completion) {
282269
dispatch_async(dispatch_get_main_queue(), ^{
283270
completion(nil, error);
284271
});
285272
}
286273
return;
287274
}
288-
289-
// Use the union of granted and requested scopes.
290-
[grantedScopes unionSet:requestedScopes];
291-
options.scopes = [grantedScopes allObjects];
275+
276+
GIDConfiguration *configuration = self.currentUser.configuration;
277+
GIDSignInInternalOptions *options =
278+
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
279+
presentingViewController:presentingViewController
280+
loginHint:self.currentUser.profile.email
281+
addScopesFlow:YES
282+
completion:completion];
283+
options.scopes = allScopes;
292284

293285
[self signInWithOptions:options];
294286
}

GoogleSignIn/Sources/GIDSignInPreferences.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ extern NSString *const kSDKVersionLoggingParameter;
2424
/// The name of the query parameter used for logging the Apple execution environment.
2525
extern NSString *const kEnvironmentLoggingParameter;
2626

27+
/// The name of the query parameter for the token exchange endpoint.
28+
extern NSString *const kAudienceParameter;
29+
30+
extern NSString *const kIncludeGrantedScopesParameter;
31+
32+
extern NSString *const kLoginHintParameter;
33+
34+
extern NSString *const kHostedDomainParameter;
35+
2736
/// Expected path in the URL scheme to be handled.
2837
extern NSString *const kBrowserCallbackPath;
2938

GoogleSignIn/Sources/GIDSignInPreferences.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@
1616

1717
NS_ASSUME_NONNULL_BEGIN
1818

19+
/// Parameters for the auth and token exchange endpoints.
20+
NSString *const kAudienceParameter = @"audience";
21+
NSString *const kIncludeGrantedScopesParameter = @"include_granted_scopes";
22+
NSString *const kLoginHintParameter = @"login_hint";
23+
NSString *const kHostedDomainParameter = @"hd";
1924
NSString *const kSDKVersionLoggingParameter = @"gpsdk";
2025
NSString *const kEnvironmentLoggingParameter = @"gidenv";
26+
2127
NSString *const kBrowserCallbackPath = @"/oauth2callback";
2228

2329
static NSString *const kLSOServer = @"accounts.google.com";

GoogleSignIn/Sources/GIDSignIn_Private.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
#import <AppKit/AppKit.h>
2525
#endif
2626

27-
NS_ASSUME_NONNULL_BEGIN
28-
2927
@class GIDGoogleUser;
3028
@class GIDSignInInternalOptions;
3129

@@ -34,6 +32,11 @@ NS_ASSUME_NONNULL_BEGIN
3432
@protocol GIDKeychainHandler;
3533
@protocol GIDProfileDataFetcher;
3634

35+
NS_ASSUME_NONNULL_BEGIN
36+
37+
/// The EMM support version.
38+
extern NSString *const kEMMVersion;
39+
3740
/// Represents a completion block that takes a `GIDSignInResult` on success or an error if the
3841
/// operation was unsuccessful.
3942
typedef void (^GIDSignInCompletion)(GIDSignInResult *_Nullable signInResult,

0 commit comments

Comments
 (0)