From 613ca949f49f2194754ef5bdc8ded03ff0c56a98 Mon Sep 17 00:00:00 2001 From: pinlu Date: Thu, 7 Jul 2022 10:42:01 -0700 Subject: [PATCH 1/6] Replace GIDSignInCallback Replace GIDSignInCallback with block void (^)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error) --- GoogleSignIn/Sources/GIDSignInInternalOptions.m | 1 + GoogleSignIn/Tests/Unit/GIDSignInTest.m | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/GoogleSignIn/Sources/GIDSignInInternalOptions.m b/GoogleSignIn/Sources/GIDSignInInternalOptions.m index 617c0291..53215d2a 100644 --- a/GoogleSignIn/Sources/GIDSignInInternalOptions.m +++ b/GoogleSignIn/Sources/GIDSignInInternalOptions.m @@ -41,6 +41,7 @@ + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)con scopes:(nullable NSArray *)scopes callback:(nullable void (^)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error))callback { + #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 46e4d36e..f7cab2df 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -1290,7 +1290,7 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow [[[_authState expect] andReturn:authResponse] lastAuthorizationResponse]; [[[_authState expect] andReturn:authResponse] lastAuthorizationResponse]; } - + // Simulate auth endpoint response if (modalCancel) { NSError *error = [NSError errorWithDomain:OIDGeneralErrorDomain @@ -1323,6 +1323,9 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow // OIDTokenCallback if (tokenError) { [[_authState expect] updateWithTokenResponse:nil error:tokenError]; + + // CompletionCallback + [[[_authState expect] andReturn:nil] lastTokenResponse]; } else { [[_authState expect] updateWithTokenResponse:[OCMArg any] error:nil]; } From 372a61e9b21387bec0ed2f29aa4ae1f0b8b5d89b Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 11 Jul 2022 23:00:47 -0700 Subject: [PATCH 2/6] Change GIDSignInCallback in sample apps. --- Samples/ObjC/SignInSample/Source/AppDelegate.m | 2 +- .../Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Samples/ObjC/SignInSample/Source/AppDelegate.m b/Samples/ObjC/SignInSample/Source/AppDelegate.m index 45927392..a458ff4a 100644 --- a/Samples/ObjC/SignInSample/Source/AppDelegate.m +++ b/Samples/ObjC/SignInSample/Source/AppDelegate.m @@ -30,7 +30,7 @@ - (BOOL)application:(UIApplication *)application // succeeds, we'll have a currentUser and the view will be able to draw its UI for the signed-in // state. If the restore fails, currentUser will be nil and we'll draw the signed-out state // prompting the user to sign in. - [GIDSignIn.sharedInstance restorePreviousSignInWithCallback:^(GIDGoogleUser * _Nullable user, + [GIDSignIn.sharedInstance restorePreviousSignInWithCallback:^(GIDUserAuth * _Nullable userAuth, NSError * _Nullable error) { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; SignInViewController *masterViewController = diff --git a/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift b/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift index afa3083f..2d648d02 100644 --- a/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift +++ b/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift @@ -26,9 +26,9 @@ struct DaysUntilBirthday: App { ContentView() .environmentObject(authViewModel) .onAppear { - GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in - if let user = user { - self.authViewModel.state = .signedIn(user) + GIDSignIn.sharedInstance.restorePreviousSignIn { userAuth, error in + if let userAuth = userAuth { + self.authViewModel.state = .signedIn(userAuth.user) } else if let error = error { self.authViewModel.state = .signedOut print("There was an error restoring the previous sign-in: \(error)") From 26241b76fa8fcc03c5b01b1789f0491c67a0777e Mon Sep 17 00:00:00 2001 From: pinlu Date: Tue, 12 Jul 2022 18:45:19 -0700 Subject: [PATCH 3/6] Minor improvements 1. Resolve comments 2. Make sure in clients callback one of userAuth and error is nil. --- GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h | 6 +++--- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h index 27367565..25ad9ea9 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h @@ -115,7 +115,7 @@ typedef void (^GIDDisconnectCallback)(NSError *_Nullable error); /// @param presentingViewController The view controller used to present `SFSafariViewContoller` on /// iOS 9 and 10 and to supply `presentationContextProvider` for `ASWebAuthenticationSession` on /// iOS 13+. -/// @param callback The block that is called on completion. This block will be called asynchronously on +/// @param callback The block that is called on completion. This block will be called asynchronously on /// the main queue. - (void)signInWithConfiguration:(GIDConfiguration *)configuration presentingViewController:(UIViewController *)presentingViewController @@ -136,7 +136,7 @@ typedef void (^GIDDisconnectCallback)(NSError *_Nullable error); /// iOS 13+. /// @param hint An optional hint for the authorization server, for example the user's ID or email /// address, to be prefilled if possible. -/// @param callback The block that is called on completion. This block will be called asynchronously on +/// @param callback The block that is called on completion. This block will be called asynchronously on /// the main queue. - (void)signInWithConfiguration:(GIDConfiguration *)configuration presentingViewController:(UIViewController *)presentingViewController @@ -176,7 +176,7 @@ typedef void (^GIDDisconnectCallback)(NSError *_Nullable error); /// @param presentingViewController The view controller used to present `SFSafariViewContoller` on /// iOS 9 and 10 and to supply `presentationContextProvider` for `ASWebAuthenticationSession` on /// iOS 13+. -/// @param callback The block that is called on completion. This block will be called asynchronously on +/// @param callback The block that is called on completion. This block will be called asynchronously on /// the main queue. - (void)addScopes:(NSArray *)scopes presentingViewController:(UIViewController *)presentingViewController diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index f7cab2df..46e4d36e 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -1290,7 +1290,7 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow [[[_authState expect] andReturn:authResponse] lastAuthorizationResponse]; [[[_authState expect] andReturn:authResponse] lastAuthorizationResponse]; } - + // Simulate auth endpoint response if (modalCancel) { NSError *error = [NSError errorWithDomain:OIDGeneralErrorDomain @@ -1323,9 +1323,6 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow // OIDTokenCallback if (tokenError) { [[_authState expect] updateWithTokenResponse:nil error:tokenError]; - - // CompletionCallback - [[[_authState expect] andReturn:nil] lastTokenResponse]; } else { [[_authState expect] updateWithTokenResponse:[OCMArg any] error:nil]; } From c2a8240b1966aa4b7699bb80d512bf43286114ce Mon Sep 17 00:00:00 2001 From: pinlu Date: Wed, 13 Jul 2022 15:16:27 -0700 Subject: [PATCH 4/6] Change the restorePreviousSignIn callback --- Samples/ObjC/SignInSample/Source/AppDelegate.m | 2 +- .../Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Samples/ObjC/SignInSample/Source/AppDelegate.m b/Samples/ObjC/SignInSample/Source/AppDelegate.m index a458ff4a..45927392 100644 --- a/Samples/ObjC/SignInSample/Source/AppDelegate.m +++ b/Samples/ObjC/SignInSample/Source/AppDelegate.m @@ -30,7 +30,7 @@ - (BOOL)application:(UIApplication *)application // succeeds, we'll have a currentUser and the view will be able to draw its UI for the signed-in // state. If the restore fails, currentUser will be nil and we'll draw the signed-out state // prompting the user to sign in. - [GIDSignIn.sharedInstance restorePreviousSignInWithCallback:^(GIDUserAuth * _Nullable userAuth, + [GIDSignIn.sharedInstance restorePreviousSignInWithCallback:^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; SignInViewController *masterViewController = diff --git a/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift b/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift index 2d648d02..afa3083f 100644 --- a/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift +++ b/Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift @@ -26,9 +26,9 @@ struct DaysUntilBirthday: App { ContentView() .environmentObject(authViewModel) .onAppear { - GIDSignIn.sharedInstance.restorePreviousSignIn { userAuth, error in - if let userAuth = userAuth { - self.authViewModel.state = .signedIn(userAuth.user) + GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in + if let user = user { + self.authViewModel.state = .signedIn(user) } else if let error = error { self.authViewModel.state = .signedOut print("There was an error restoring the previous sign-in: \(error)") From 596e5b1c7a3f17dd28697291684c4b9450e47df2 Mon Sep 17 00:00:00 2001 From: pinlu Date: Thu, 14 Jul 2022 17:08:22 -0700 Subject: [PATCH 5/6] Style improvement. --- GoogleSignIn/Sources/GIDSignInInternalOptions.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/GoogleSignIn/Sources/GIDSignInInternalOptions.m b/GoogleSignIn/Sources/GIDSignInInternalOptions.m index 53215d2a..b08f6662 100644 --- a/GoogleSignIn/Sources/GIDSignInInternalOptions.m +++ b/GoogleSignIn/Sources/GIDSignInInternalOptions.m @@ -41,9 +41,7 @@ + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)con scopes:(nullable NSArray *)scopes callback:(nullable void (^)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error))callback { - #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST - GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init]; if (options) { options->_interactive = YES; From b20eabb7aa81580058ea6485ce355679dcd2e1b5 Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 18 Jul 2022 11:45:18 -0700 Subject: [PATCH 6/6] Add GIDToken class --- GoogleSignIn/Sources/GIDToken.m | 58 +++++++++++++++++++ GoogleSignIn/Sources/GIDToken_Private.h | 32 ++++++++++ .../Sources/Public/GoogleSignIn/GIDToken.h | 38 ++++++++++++ .../Public/GoogleSignIn/GoogleSignIn.h | 1 + GoogleSignIn/Tests/Unit/GIDTokenTest.m | 56 ++++++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 GoogleSignIn/Sources/GIDToken.m create mode 100644 GoogleSignIn/Sources/GIDToken_Private.h create mode 100644 GoogleSignIn/Sources/Public/GoogleSignIn/GIDToken.h create mode 100644 GoogleSignIn/Tests/Unit/GIDTokenTest.m diff --git a/GoogleSignIn/Sources/GIDToken.m b/GoogleSignIn/Sources/GIDToken.m new file mode 100644 index 00000000..05d3f1dc --- /dev/null +++ b/GoogleSignIn/Sources/GIDToken.m @@ -0,0 +1,58 @@ +/* + * Copyright 2022 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/Public/GoogleSignIn/GIDToken.h" + +#import "GoogleSignIn/Sources/GIDToken_Private.h" + +// Key constants used for encode and decode. +static NSString *const kTokenStringKey = @"tokenString"; +static NSString *const kExpirationDateKey = @"expirationDate"; + +@implementation GIDToken + +- (instancetype)initWithTokenString:(NSString *)tokenString + expirationDate:(NSDate *)expirationDate { + self = [super init]; + if (self) { + _tokenString = tokenString; + _expirationDate = expirationDate; + } + + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)decoder { + self = [super init]; + if (self) { + _tokenString = [decoder decodeObjectOfClass:[NSString class] forKey:kTokenStringKey]; + _expirationDate = [decoder decodeObjectOfClass:[NSDate class] forKey:kExpirationDateKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)encoder { + [encoder encodeObject:_tokenString forKey:kTokenStringKey]; + [encoder encodeObject:_expirationDate forKey:kExpirationDateKey]; +} + +@end diff --git a/GoogleSignIn/Sources/GIDToken_Private.h b/GoogleSignIn/Sources/GIDToken_Private.h new file mode 100644 index 00000000..b078cb5a --- /dev/null +++ b/GoogleSignIn/Sources/GIDToken_Private.h @@ -0,0 +1,32 @@ +/* + * Copyright 2022 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/Public/GoogleSignIn/GIDUserAuth.h" + +NS_ASSUME_NONNULL_BEGIN + +// Private |GIDToken| methods that are used in this SDK. +@interface GIDToken () + +// Private initializer for |GIDToken|. +// @param token The token String. +// @param expirationDate The expiration date of the token. +- (instancetype)initWithTokenString:(NSString *)tokenString + expirationDate:(NSDate *)expirationDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDToken.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDToken.h new file mode 100644 index 00000000..29f5d3b9 --- /dev/null +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDToken.h @@ -0,0 +1,38 @@ +/* + * Copyright 2022 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 + +NS_ASSUME_NONNULL_BEGIN + +/// This class represents the basic information of a token. +@interface GIDToken : NSObject + +/// The token string. +@property(nonatomic, copy, readonly) NSString *tokenString; + +/// The estimated expiration date of the token. +@property(nonatomic, readonly, nullable) NSDate *expirationDate; + +/// Unsupported. ++ (instancetype)new NS_UNAVAILABLE; + +/// Unsupported. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h index df002612..d1b7afda 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h @@ -20,6 +20,7 @@ #import "GIDGoogleUser.h" #import "GIDProfileData.h" #import "GIDSignIn.h" +#import "GIDToken.h" #import "GIDUserAuth.h" #if TARGET_OS_IOS || TARGET_OS_MACCATALYST #import "GIDSignInButton.h" diff --git a/GoogleSignIn/Tests/Unit/GIDTokenTest.m b/GoogleSignIn/Tests/Unit/GIDTokenTest.m new file mode 100644 index 00000000..aa9d1b1a --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDTokenTest.m @@ -0,0 +1,56 @@ +// Copyright 2022 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 +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDToken.h" + +#import "GoogleSignIn/Sources/GIDToken_Private.h" + +static NSString * const tokenString = @"tokenString"; + +@interface GIDTokenTest : XCTestCase { + NSDate *_date; +} +@end + +@implementation GIDTokenTest + +- (void)setUP { + [super setUp]; + _date = [[NSDate alloc]initWithTimeIntervalSince1970:1000]; +} + +- (void)testInitializer { + GIDToken *token = [[GIDToken alloc]initWithTokenString:tokenString expirationDate:_date]; + XCTAssertEqualObjects(token.tokenString, tokenString); + XCTAssertEqualObjects(token.expirationDate, _date); +} + +- (void)testCoding { + if (@available(iOS 11, macOS 10.13, *)) { + GIDToken *token = [[GIDToken alloc]initWithTokenString:tokenString expirationDate:_date]; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:token requiringSecureCoding:YES error:nil]; + GIDToken *newToken = [NSKeyedUnarchiver unarchivedObjectOfClass:[GIDToken class] + fromData:data + error:nil]; + XCTAssertEqualObjects(token.tokenString, newToken.tokenString); + XCTAssertEqualObjects(token.expirationDate, newToken.expirationDate); + + XCTAssertTrue([GIDToken supportsSecureCoding]); + } else { + XCTSkip(@"Required API is not available for this test."); + } +} + +@end