Skip to content

Commit 25b266a

Browse files
committed
Merge branch 'refactorGSI' into pin-GIDAuthorizationFlowProcessor-fake
2 parents 3564b01 + 884b531 commit 25b266a

17 files changed

+598
-119
lines changed

GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/API/GIDAuthorizationFlowProcessor.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,35 @@
1616

1717
#import <Foundation/Foundation.h>
1818

19-
NS_ASSUME_NONNULL_BEGIN
20-
2119
@class GIDSignInInternalOptions;
2220
@class OIDAuthorizationResponse;
2321

22+
NS_ASSUME_NONNULL_BEGIN
23+
24+
/// The protocol to control the authorization flow.
2425
@protocol GIDAuthorizationFlowProcessor <NSObject>
2526

2627
/// The state of the authorization flow.
2728
@property(nonatomic, readonly, getter=isStarted) BOOL start;
2829

2930
/// Starts the authorization flow.
3031
///
31-
/// @param options The @GIDSignInInternalOptions object to provide serverClientID, hostedDomain,
32+
/// This method sends authorization request to AppAuth `OIDAuthorizationService` and gets back the
33+
/// response or an error.
34+
///
35+
/// @param options The `GIDSignInInternalOptions` object to provide serverClientID, hostedDomain,
3236
/// clientID, scopes, loginHint and extraParams.
3337
/// @param emmSupport The EMM support info string.
3438
/// @param completion The block that is called on completion asynchronously.
39+
/// authorizationResponse The response from `OIDAuthorizationService`.
40+
/// error The error from `OIDAuthorizationService`.
3541
- (void)startWithOptions:(GIDSignInInternalOptions *)options
3642
emmSupport:(nullable NSString *)emmSupport
3743
completion:(void (^)(OIDAuthorizationResponse *_Nullable authorizationResponse,
3844
NSError *_Nullable error))completion;
3945

40-
/// Handles the custom scheme URL opened by SFSafariViewController to cleanup UI on iOS 10.
46+
/// Handles the custom URL scheme opened by SFSafariViewController and returns control to the
47+
/// client on iOS 10.
4148
///
4249
/// @param url The redirect URL invoked by the server.
4350
/// @return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise.

GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
NS_ASSUME_NONNULL_BEGIN
2424

25+
/// Concrete implementation of the protocol `GIDAuthorizationFlowProcessor`.
2526
@interface GIDAuthorizationFlowProcessor : NSObject <GIDAuthorizationFlowProcessor>
2627

2728
@end

GoogleSignIn/Sources/GIDAuthorizationFlowProcessor/Implementations/GIDAuthorizationFlowProcessor.m

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,22 @@
3838
static NSString *const kLoginHintParameter = @"login_hint";
3939
static NSString *const kHostedDomainParameter = @"hd";
4040

41-
@implementation GIDAuthorizationFlowProcessor {
42-
// AppAuth external user-agent session state.
43-
id<OIDExternalUserAgentSession> _currentAuthorizationFlow;
44-
// AppAuth configuration object.
45-
OIDServiceConfiguration *_appAuthConfiguration;
46-
}
41+
@interface GIDAuthorizationFlowProcessor ()
42+
43+
/// AppAuth external user-agent session state.
44+
@property(nonatomic, nullable)id<OIDExternalUserAgentSession> currentAuthorizationFlow;
45+
46+
/// AppAuth configuration object.
47+
@property(nonatomic)OIDServiceConfiguration *appAuthConfiguration;
48+
49+
@end
50+
51+
@implementation GIDAuthorizationFlowProcessor
4752

4853
# pragma mark - Public API
4954

5055
- (BOOL)isStarted {
51-
return _currentAuthorizationFlow != nil;
56+
return self.currentAuthorizationFlow != nil;
5257
}
5358

5459
- (void)startWithOptions:(GIDSignInInternalOptions *)options
@@ -72,6 +77,7 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options
7277
if (options.configuration.hostedDomain) {
7378
additionalParameters[kHostedDomainParameter] = options.configuration.hostedDomain;
7479
}
80+
7581
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
7682
[additionalParameters addEntriesFromDictionary:
7783
[GIDEMMSupport parametersWithParameters:options.extraParams
@@ -110,17 +116,17 @@ - (void)startWithOptions:(GIDSignInInternalOptions *)options
110116
}
111117

112118
- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url {
113-
if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
114-
_currentAuthorizationFlow = nil;
119+
if ([self.currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
120+
self.currentAuthorizationFlow = nil;
115121
return YES;
116122
} else {
117123
return NO;
118124
}
119125
}
120126

121127
- (void)cancelAuthenticationFlow {
122-
[_currentAuthorizationFlow cancel];
123-
_currentAuthorizationFlow = nil;
128+
[self.currentAuthorizationFlow cancel];
129+
self.currentAuthorizationFlow = nil;
124130
}
125131

126132
@end

GoogleSignIn/Sources/GIDProfileData.m

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

1717
#import "GoogleSignIn/Sources/GIDProfileData_Private.h"
1818

19+
#ifdef SWIFT_PACKAGE
20+
@import AppAuth;
21+
#else
22+
#import <AppAuth/AppAuth.h>
23+
#endif
24+
1925
NS_ASSUME_NONNULL_BEGIN
2026

2127
// Key constants used for encode and decode.
@@ -109,21 +115,23 @@ + (BOOL)supportsSecureCoding {
109115
}
110116

111117
- (nullable instancetype)initWithCoder:(NSCoder *)decoder {
112-
self = [super init];
113-
if (self) {
114-
_email = [decoder decodeObjectOfClass:[NSString class] forKey:kEmailKey];
115-
_name = [decoder decodeObjectOfClass:[NSString class] forKey:kNameKey];
116-
_givenName = [decoder decodeObjectOfClass:[NSString class] forKey:kGivenNameKey];
117-
_familyName = [decoder decodeObjectOfClass:[NSString class] forKey:kFamilyNameKey];
118-
_imageURL = [decoder decodeObjectOfClass:[NSURL class] forKey:kImageURLKey];
119-
120-
// Check to see if this is an old archive, if so, try decoding the old image URL string key.
121-
if ([decoder containsValueForKey:kOldImageURLStringKey]) {
122-
_imageURL = [NSURL URLWithString:[decoder decodeObjectOfClass:[NSString class]
123-
forKey:kOldImageURLStringKey]];
124-
}
118+
NSString *email = [decoder decodeObjectOfClass:[NSString class] forKey:kEmailKey];
119+
NSString *name = [decoder decodeObjectOfClass:[NSString class] forKey:kNameKey];
120+
NSString *givenName = [decoder decodeObjectOfClass:[NSString class] forKey:kGivenNameKey];
121+
NSString *familyName = [decoder decodeObjectOfClass:[NSString class] forKey:kFamilyNameKey];
122+
NSURL *imageURL = [decoder decodeObjectOfClass:[NSURL class] forKey:kImageURLKey];
123+
124+
// Check to see if this is an old archive, if so, try decoding the old image URL string key.
125+
if ([decoder containsValueForKey:kOldImageURLStringKey]) {
126+
imageURL = [NSURL URLWithString:[decoder decodeObjectOfClass:[NSString class]
127+
forKey:kOldImageURLStringKey]];
125128
}
126-
return self;
129+
130+
return [self initWithEmail:email
131+
name:name
132+
givenName:givenName
133+
familyName:familyName
134+
imageURL:imageURL];
127135
}
128136

129137
- (void)encodeWithCoder:(NSCoder *)encoder {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 OIDAuthState;
20+
@class OIDIDToken;
21+
@class GIDProfileData;
22+
23+
NS_ASSUME_NONNULL_BEGIN
24+
25+
@protocol GIDProfileDataFetcher <NSObject>
26+
27+
/// Fetches the latest `GIDProfileData` object.
28+
///
29+
/// This method either extracts profile data from `OIDIDToken` in `OIDAuthState` or fetches it
30+
/// from the UserInfo endpoint.
31+
///
32+
/// @param authState The state of the current OAuth session.
33+
/// @param completion The block that is called on completion asynchronously.
34+
- (void)fetchProfileDataWithAuthState:(OIDAuthState *)authState
35+
completion:(void (^)(GIDProfileData *_Nullable profileData,
36+
NSError *_Nullable error))completion;
37+
38+
/// Fetches a `GIDProfileData` object from an ID token.
39+
///
40+
/// This method returns a `GIDProfileData` object if the ID token is a fat one. Otherwise, returns
41+
/// nil.
42+
///
43+
/// @param idToken The ID token.
44+
- (nullable GIDProfileData *)fetchProfileDataWithIDToken:(OIDIDToken *)idToken;
45+
46+
@end
47+
48+
NS_ASSUME_NONNULL_END
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
#import "GoogleSignIn/Sources/GIDProfileDataFetcher/API/GIDProfileDataFetcher.h"
20+
21+
@protocol GIDHTTPFetcher;
22+
23+
NS_ASSUME_NONNULL_BEGIN
24+
25+
@interface GIDProfileDataFetcher : NSObject <GIDProfileDataFetcher>
26+
27+
/// The convenience initializer.
28+
- (instancetype)init;
29+
30+
/// The initializer for unit test.
31+
- (instancetype)initWithHTTPFetcher:(id<GIDHTTPFetcher>)httpFetcher NS_DESIGNATED_INITIALIZER;
32+
33+
@end
34+
35+
NS_ASSUME_NONNULL_END
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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/GIDProfileDataFetcher/Implementations/GIDProfileDataFetcher.h"
18+
19+
#import "GoogleSignIn/Sources/GIDHTTPFetcher/API/GIDHTTPFetcher.h"
20+
#import "GoogleSignIn/Sources/GIDHTTPFetcher/Implementations/GIDHTTPFetcher.h"
21+
#import "GoogleSignIn/Sources/GIDProfileData_Private.h"
22+
#import "GoogleSignIn/Sources/GIDSignInPreferences.h"
23+
24+
#ifdef SWIFT_PACKAGE
25+
@import AppAuth;
26+
@import GTMAppAuth;
27+
#else
28+
#import <AppAuth/AppAuth.h>
29+
#import <GTMAppAuth/GTMAppAuth.h>
30+
#endif
31+
32+
NS_ASSUME_NONNULL_BEGIN
33+
34+
// The URL template for the URL to get user info.
35+
static NSString *const kUserInfoURLTemplate = @"https://%@/oauth2/v3/userinfo";
36+
37+
// Basic profile (Fat ID Token / userinfo endpoint) keys
38+
static NSString *const kBasicProfileEmailKey = @"email";
39+
static NSString *const kBasicProfilePictureKey = @"picture";
40+
static NSString *const kBasicProfileNameKey = @"name";
41+
static NSString *const kBasicProfileGivenNameKey = @"given_name";
42+
static NSString *const kBasicProfileFamilyNameKey = @"family_name";
43+
44+
@implementation GIDProfileDataFetcher {
45+
id<GIDHTTPFetcher> _httpFetcher;
46+
}
47+
48+
- (instancetype)init {
49+
GIDHTTPFetcher *httpFetcher = [[GIDHTTPFetcher alloc] init];
50+
return [self initWithHTTPFetcher:httpFetcher];
51+
}
52+
53+
- (instancetype)initWithHTTPFetcher:(id<GIDHTTPFetcher>)httpFetcher {
54+
self = [super init];
55+
if (self) {
56+
_httpFetcher = httpFetcher;
57+
}
58+
return self;
59+
}
60+
61+
- (void)fetchProfileDataWithAuthState:(OIDAuthState *)authState
62+
completion:(void (^)(GIDProfileData *_Nullable profileData,
63+
NSError *_Nullable error))completion {
64+
OIDIDToken *idToken =
65+
[[OIDIDToken alloc] initWithIDTokenString:authState.lastTokenResponse.idToken];
66+
if (idToken) {
67+
// If we have an ID token, try to extract profile data from it.
68+
GIDProfileData *profileData = [self fetchProfileDataWithIDToken:idToken];
69+
if (profileData) {
70+
completion(profileData, nil);
71+
return;
72+
}
73+
}
74+
75+
// If we can't retrieve profile data from the ID token, make a UserInfo endpoint request to
76+
// fetch it.
77+
NSString *infoString = [NSString stringWithFormat:kUserInfoURLTemplate,
78+
[GIDSignInPreferences googleUserInfoServer]];
79+
NSURL *infoURL = [NSURL URLWithString:infoString];
80+
NSMutableURLRequest *infoRequest = [NSMutableURLRequest requestWithURL:infoURL];
81+
GTMAppAuthFetcherAuthorization *authorization =
82+
[[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState];
83+
84+
[_httpFetcher fetchURLRequest:infoRequest
85+
withAuthorizer:authorization
86+
withComment:@"GIDSignIn: fetch basic profile info"
87+
completion:^(NSData *data, NSError *error) {
88+
if (error) {
89+
completion(nil, error);
90+
return;
91+
}
92+
NSError *jsonDeserializationError;
93+
NSDictionary<NSString *, NSString *> *profileDict =
94+
[NSJSONSerialization JSONObjectWithData:data
95+
options:NSJSONReadingMutableContainers
96+
error:&jsonDeserializationError];
97+
if (jsonDeserializationError) {
98+
completion(nil, jsonDeserializationError);
99+
return;
100+
}
101+
GIDProfileData *profileData = [[GIDProfileData alloc]
102+
initWithEmail:idToken.claims[kBasicProfileEmailKey]
103+
name:profileDict[kBasicProfileNameKey]
104+
givenName:profileDict[kBasicProfileGivenNameKey]
105+
familyName:profileDict[kBasicProfileFamilyNameKey]
106+
imageURL:[NSURL URLWithString:profileDict[kBasicProfilePictureKey]]];
107+
completion(profileData, nil);
108+
}];
109+
}
110+
111+
- (nullable GIDProfileData*)fetchProfileDataWithIDToken:(OIDIDToken *)idToken {
112+
if (!idToken ||
113+
!idToken.claims[kBasicProfilePictureKey] ||
114+
!idToken.claims[kBasicProfileNameKey] ||
115+
!idToken.claims[kBasicProfileGivenNameKey] ||
116+
!idToken.claims[kBasicProfileFamilyNameKey]) {
117+
return nil;
118+
}
119+
120+
return [[GIDProfileData alloc]
121+
initWithEmail:idToken.claims[kBasicProfileEmailKey]
122+
name:idToken.claims[kBasicProfileNameKey]
123+
givenName:idToken.claims[kBasicProfileGivenNameKey]
124+
familyName:idToken.claims[kBasicProfileFamilyNameKey]
125+
imageURL:[NSURL URLWithString:idToken.claims[kBasicProfilePictureKey]]];
126+
}
127+
128+
@end
129+
130+
NS_ASSUME_NONNULL_END

GoogleSignIn/Sources/GIDProfileData_Private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
2626
name:(NSString *)name
2727
givenName:(nullable NSString *)givenName
2828
familyName:(nullable NSString *)familyName
29-
imageURL:(nullable NSURL *)imageURL;
29+
imageURL:(nullable NSURL *)imageURL NS_DESIGNATED_INITIALIZER;
3030

3131
@end
3232

0 commit comments

Comments
 (0)