Browse Source

Replace GIDSignInCallback (#179)

Replace GIDSignInCallback with block
void (^)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error)
pinlu 3 years ago
parent
commit
3ba23d08bc

+ 32 - 14
GoogleSignIn/Sources/GIDSignIn.m

@@ -20,6 +20,7 @@
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h"
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h"
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDProfileData.h"
+#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDUserAuth.h"
 
 #import "GoogleSignIn/Sources/GIDSignInInternalOptions.h"
 #import "GoogleSignIn/Sources/GIDSignInPreferences.h"
@@ -34,6 +35,7 @@
 #import "GoogleSignIn/Sources/GIDAuthentication_Private.h"
 #import "GoogleSignIn/Sources/GIDGoogleUser_Private.h"
 #import "GoogleSignIn/Sources/GIDProfileData_Private.h"
+#import "GoogleSignIn/Sources/GIDUserAuth_Private.h"
 
 #ifdef SWIFT_PACKAGE
 @import AppAuth;
@@ -187,8 +189,16 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
   return [authState isAuthorized];
 }
 
-- (void)restorePreviousSignInWithCompletion:(nullable GIDSignInCompletion)completion {
-  [self signInWithOptions:[GIDSignInInternalOptions silentOptionsWithCompletion:completion]];
+- (void)restorePreviousSignInWithCompletion:(nullable void (^)(GIDGoogleUser *_Nullable user,
+                                                               NSError *_Nullable error))completion {
+  [self signInWithOptions:[GIDSignInInternalOptions silentOptionsWithCallback:
+                           ^(GIDUserAuth *userAuth, NSError *error) {
+    if (userAuth) {
+      callback(userAuth.user, nil);
+    } else {
+      callback(nil, error);
+    }
+  }]];
 }
 
 - (BOOL)restorePreviousSignInNoRefresh {
@@ -217,7 +227,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
        presentingViewController:(UIViewController *)presentingViewController
                            hint:(nullable NSString *)hint
-                     completion:(nullable GIDSignInCompletion)completion {
+                     completion:(nullable GIDUserAuthCompletion)completion {
   GIDSignInInternalOptions *options =
       [GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
                                        presentingViewController:presentingViewController
@@ -231,7 +241,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
        presentingViewController:(UIViewController *)presentingViewController
                            hint:(nullable NSString *)hint
                additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
-                     completion:(nullable GIDSignInCompletion)completion {
+                     completion:(nullable GIDUserAuthCompletion)completion {
   GIDSignInInternalOptions *options =
     [GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
                                      presentingViewController:presentingViewController
@@ -244,7 +254,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
 
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
        presentingViewController:(UIViewController *)presentingViewController
-                     completion:(nullable GIDSignInCompletion)completion {
+                     completion:(nullable GIDUserAuthCompletion)completion {
   [self signInWithConfiguration:configuration
        presentingViewController:presentingViewController
                            hint:nil
@@ -253,7 +263,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
 
 - (void)addScopes:(NSArray<NSString *> *)scopes
     presentingViewController:(UIViewController *)presentingViewController
-                  completion:(nullable GIDSignInCompletion)completion {
+                  completion:(nullable GIDUserAuthCompletion)completion {
   // A currentUser must be available in order to complete this flow.
   if (!self.currentUser) {
     // No currentUser is set, notify callback of failure.
@@ -310,7 +320,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
                presentingWindow:(NSWindow *)presentingWindow
                            hint:(nullable NSString *)hint
-                     completion:(nullable GIDSignInCompletion)completion {
+                     completion:(nullable GIDUserAuthCompletion)completion {
   GIDSignInInternalOptions *options =
       [GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
                                                presentingWindow:presentingWindow
@@ -322,7 +332,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
 
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
                presentingWindow:(NSWindow *)presentingWindow
-                     completion:(nullable GIDSignInCompletion)completion {
+                     completion:(nullable GIDUserAuthCompletion)completion {
   [self signInWithConfiguration:configuration
                presentingWindow:presentingWindow
                            hint:nil
@@ -333,7 +343,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
                presentingWindow:(NSWindow *)presentingWindow
                            hint:(nullable NSString *)hint
                additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
-                     completion:(nullable GIDSignInCompletion)completion {
+                     completion:(nullable GIDUserAuthCompletion)completion {
   GIDSignInInternalOptions *options =
     [GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
                                              presentingWindow:presentingWindow
@@ -346,7 +356,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
 
 - (void)addScopes:(NSArray<NSString *> *)scopes
  presentingWindow:(NSWindow *)presentingWindow
-       completion:(nullable GIDSignInCompletion)completion {
+       completion:(nullable GIDUserAuthCompletion)completion {
   // A currentUser must be available in order to complete this flow.
   if (!self.currentUser) {
     // No currentUser is set, notify callback of failure.
@@ -541,7 +551,8 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
         if (options.completion) {
           self->_currentOptions = nil;
           dispatch_async(dispatch_get_main_queue(), ^{
-            options.completion(self->_currentUser, nil);
+            GIDUserAuth *userAuth = [[GIDUserAuth alloc] initWithGoogleUser:self->_currentUser serverAuthCode:nil];
+            options.completion(userAuth, nil);
           });
         }
       }
@@ -601,7 +612,7 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
   _currentAuthorizationFlow = [OIDAuthorizationService
       presentAuthorizationRequest:request
          presentingViewController:options.presentingViewController
-                        callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse,
+                         callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse,
                                    NSError *_Nullable error) {
     [self processAuthorizationResponse:authorizationResponse
                                  error:error
@@ -882,10 +893,17 @@ static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;
   [authFlow addCallback:^() {
     GIDAuthFlow *handlerAuthFlow = weakAuthFlow;
     if (self->_currentOptions.completion) {
-      GIDSignInCompletion completion = self->_currentOptions.completion;
+      GIDUserAuthCompletion completion = self->_currentOptions.completion;
       self->_currentOptions = nil;
       dispatch_async(dispatch_get_main_queue(), ^{
-        completion(self->_currentUser, handlerAuthFlow.error);
+        if (handlerAuthFlow.error) {
+          completion(nil, handlerAuthFlow.error);
+        } else {
+          OIDAuthState *authState = handlerAuthFlow.authState;
+          NSString *_Nullable serverAuthCode = [authState.lastTokenResponse.additionalParameters[@"server_code"] copy];
+          GIDUserAuth *userAuth = [[GIDUserAuth alloc] initWithGoogleUser:self->_currentUser serverAuthCode:serverAuthCode];
+          completion(userAuth, nil);
+        }
       });
     }
   }];

+ 13 - 8
GoogleSignIn/Sources/GIDSignInInternalOptions.h

@@ -22,9 +22,8 @@
 #import <AppKit/AppKit.h>
 #endif
 
-#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h"
-
 @class GIDConfiguration;
+@class GIDUserAuth;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -55,7 +54,8 @@ NS_ASSUME_NONNULL_BEGIN
 #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
 
 /// The completion block to be called at the completion of the flow.
-@property(nonatomic, readonly, nullable) GIDSignInCompletion completion;
+@property(nonatomic, readonly, nullable) void (^completion)(GIDUserAuth *_Nullable userAuth,
+                                                            NSError *_Nullable error);
 
 /// The scopes to be used during the flow.
 @property(nonatomic, copy, nullable) NSArray<NSString *> *scopes;
@@ -69,32 +69,37 @@ NS_ASSUME_NONNULL_BEGIN
                        presentingViewController:(nullable UIViewController *)presentingViewController
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
-                                     completion:(nullable GIDSignInCompletion)completion;
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion;
 
 + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration
                        presentingViewController:(nullable UIViewController *)presentingViewController
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
                                          scopes:(nullable NSArray *)scopes
-                                     completion:(nullable GIDSignInCompletion)completion;
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion;
 
 #elif TARGET_OS_OSX
 + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration
                                presentingWindow:(nullable NSWindow *)presentingWindow
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
-                                     completion:(nullable GIDSignInCompletion)completion;
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion;
 
 + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration
                                presentingWindow:(nullable NSWindow *)presentingWindow
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
                                          scopes:(nullable NSArray *)scopes
-                                     completion:(nullable GIDSignInCompletion)completion;
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion;
 #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
 
 /// Creates the options to sign in silently.
-+ (instancetype)silentOptionsWithCompletion:(GIDSignInCompletion)completion;
++ (instancetype)silentOptionsWithCompletion:(void (^)(GIDUserAuth *_Nullable userAuth,
+                                                      NSError *_Nullable error))completion;
 
 /// Creates options with the same values as the receiver, except for the "extra parameters", and
 /// continuation flag, which are replaced by the arguments passed to this method.

+ 10 - 5
GoogleSignIn/Sources/GIDSignInInternalOptions.m

@@ -31,14 +31,16 @@ NS_ASSUME_NONNULL_BEGIN
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
                                          scopes:(nullable NSArray *)scopes
-                                     completion:(nullable GIDSignInCompletion)completion {
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion {
 #elif TARGET_OS_OSX
 + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration
                                presentingWindow:(nullable NSWindow *)presentingWindow
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
                                          scopes:(nullable NSArray *)scopes
-                                     completion:(nullable GIDSignInCompletion)completion {
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion {
 #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
   
   GIDSignInInternalOptions *options = [[GIDSignInInternalOptions alloc] init];
@@ -64,13 +66,15 @@ NS_ASSUME_NONNULL_BEGIN
                        presentingViewController:(nullable UIViewController *)presentingViewController
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
-                                     completion:(nullable GIDSignInCompletion)completion {
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion {
 #elif TARGET_OS_OSX
 + (instancetype)defaultOptionsWithConfiguration:(nullable GIDConfiguration *)configuration
                                presentingWindow:(nullable NSWindow *)presentingWindow
                                       loginHint:(nullable NSString *)loginHint
                                   addScopesFlow:(BOOL)addScopesFlow
-                                     completion:(nullable GIDSignInCompletion)completion {
+                                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                                   NSError *_Nullable error))completion {
 #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
     GIDSignInInternalOptions *options = [self defaultOptionsWithConfiguration:configuration
 #if TARGET_OS_IOS || TARGET_OS_MACCATALYST
@@ -85,7 +89,8 @@ NS_ASSUME_NONNULL_BEGIN
   return options;
 }
 
-+ (instancetype)silentOptionsWithCompletion:(GIDSignInCompletion)completion {
++ (instancetype)silentOptionsWithCompletion:(void (^)(GIDUserAuth *_Nullable userAuth,
+                                                      NSError *_Nullable error))completion {
   GIDSignInInternalOptions *options = [self defaultOptionsWithConfiguration:nil
 #if TARGET_OS_IOS || TARGET_OS_MACCATALYST
                                                    presentingViewController:nil

+ 4 - 0
GoogleSignIn/Sources/GIDSignIn_Private.h

@@ -21,6 +21,10 @@ NS_ASSUME_NONNULL_BEGIN
 @class GIDGoogleUser;
 @class GIDSignInInternalOptions;
 
+// Represents a completion block that takes a `GIDUserAuth` on success or an error if the operation
+// was unsuccessful.
+typedef void (^GIDUserAuthCompletion)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error);
+
 // Private |GIDSignIn| methods that are used internally in this SDK and other Google SDKs.
 @interface GIDSignIn ()
 

+ 37 - 33
GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h

@@ -25,6 +25,7 @@
 
 @class GIDConfiguration;
 @class GIDGoogleUser;
+@class GIDUserAuth;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -50,10 +51,6 @@ typedef NS_ERROR_ENUM(kGIDSignInErrorDomain, GIDSignInErrorCode) {
   kGIDSignInErrorCodeScopesAlreadyGranted = -8,
 };
 
-/// Represents a completion block that takes a `GIDGoogleUser` on success or an error if the operation
-/// was unsuccessful.
-typedef void (^GIDSignInCompletion)(GIDGoogleUser *_Nullable user, NSError *_Nullable error);
-
 /// Represents a completion block that takes an error if the operation was unsuccessful.
 typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
 
@@ -91,9 +88,10 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
 
 /// Attempts to restore a previously authenticated user without interaction.
 ///
-/// @param completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
-- (void)restorePreviousSignInWithCompletion:(nullable GIDSignInCompletion)completion;
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
+- (void)restorePreviousSignInWithCompletion:(nullable void (^)(GIDGoogleUser *_Nullable user,
+                                                               NSError *_Nullable error))completion;
 
 /// Marks current user as being in the signed out state.
 - (void)signOut;
@@ -117,11 +115,12 @@ typedef void (^GIDDisconnectCompletion)(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 completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
        presentingViewController:(UIViewController *)presentingViewController
-                     completion:(nullable GIDSignInCompletion)completion
+                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                   NSError *_Nullable error))completion
     NS_EXTENSION_UNAVAILABLE("The sign-in flow is not supported in App Extensions.");
 
 /// Starts an interactive sign-in flow on iOS using the provided configuration and a login hint.
@@ -137,12 +136,13 @@ typedef void (^GIDDisconnectCompletion)(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 completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
        presentingViewController:(UIViewController *)presentingViewController
                            hint:(nullable NSString *)hint
-                     completion:(nullable GIDSignInCompletion)completion
+                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                   NSError *_Nullable error))completion
     NS_EXTENSION_UNAVAILABLE("The sign-in flow is not supported in App Extensions.");
 
 /// Starts an interactive sign-in flow on iOS using the provided configuration and a login hint.
@@ -158,14 +158,14 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
 /// @param hint An optional hint for the authorization server, for example the user's ID or email
 ///     address, to be prefilled if possible.
 /// @param additionalScopes An optional array of scopes to request in addition to the basic profile scopes.
-/// @param completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
-
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
        presentingViewController:(UIViewController *)presentingViewController
                            hint:(nullable NSString *)hint
                additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
-                     completion:(nullable GIDSignInCompletion)completion;
+                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                   NSError *_Nullable error))completion;
 
 /// Starts an interactive consent flow on iOS to add scopes to the current user's grants.
 ///
@@ -176,11 +176,12 @@ typedef void (^GIDDisconnectCompletion)(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 completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)addScopes:(NSArray<NSString *> *)scopes
     presentingViewController:(UIViewController *)presentingViewController
-                  completion:(nullable GIDSignInCompletion)completion
+                  completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                NSError *_Nullable error))completion
     NS_EXTENSION_UNAVAILABLE("The add scopes flow is not supported in App Extensions."); 
 
 #elif TARGET_OS_OSX
@@ -193,11 +194,12 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
 ///
 /// @param configuration The configuration properties to be used for this flow.
 /// @param presentingWindow The window used to supply `presentationContextProvider` for `ASWebAuthenticationSession`.
-/// @param completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
                presentingWindow:(NSWindow *)presentingWindow
-                     completion:(nullable GIDSignInCompletion)completion;
+                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                   NSError *_Nullable error))completion;
 
 /// Starts an interactive sign-in flow on macOS using the provided configuration and a login hint.
 ///
@@ -210,12 +212,13 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
 /// @param presentingWindow The window used to supply `presentationContextProvider` for `ASWebAuthenticationSession`.
 /// @param hint An optional hint for the authorization server, for example the user's ID or email
 ///     address, to be prefilled if possible.
-/// @param completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
                presentingWindow:(NSWindow *)presentingWindow
                            hint:(nullable NSString *)hint
-                     completion:(nullable GIDSignInCompletion)completion;
+                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                   NSError *_Nullable error))completion;
 
 /// Starts an interactive sign-in flow on macOS using the provided configuration and a login hint.
 ///
@@ -229,14 +232,14 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
 /// @param hint An optional hint for the authorization server, for example the user's ID or email
 ///     address, to be prefilled if possible.
 /// @param additionalScopes An optional array of scopes to request in addition to the basic profile scopes.
-/// @param completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
-
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)signInWithConfiguration:(GIDConfiguration *)configuration
                presentingWindow:(NSWindow *)presentingWindow
                            hint:(nullable NSString *)hint
                additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
-                     completion:(nullable GIDSignInCompletion)completion;
+                     completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                                   NSError *_Nullable error))completion;
 
 /// Starts an interactive consent flow on macOS to add scopes to the current user's grants.
 ///
@@ -245,11 +248,12 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
 ///
 /// @param scopes An array of scopes to ask the user to consent to.
 /// @param presentingWindow The window used to supply `presentationContextProvider` for `ASWebAuthenticationSession`.
-/// @param completion The `GIDSignInCompletion` block that is called on completion.  This block will
-///     be called asynchronously on the main queue.
+/// @param completion The block that is called on completion.  This block will be called asynchronously
+///     on the main queue.
 - (void)addScopes:(NSArray<NSString *> *)scopes
  presentingWindow:(NSWindow *)presentingWindow
-       completion:(nullable GIDSignInCompletion)completion;
+       completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                     NSError *_Nullable error))completion;
 
 #endif
 

+ 1 - 0
GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h

@@ -20,6 +20,7 @@
 #import "GIDGoogleUser.h"
 #import "GIDProfileData.h"
 #import "GIDSignIn.h"
+#import "GIDUserAuth.h"
 #if TARGET_OS_IOS || TARGET_OS_MACCATALYST
 #import "GIDSignInButton.h"
 #endif

+ 5 - 5
GoogleSignIn/Tests/Unit/GIDSignInInternalOptionsTest.m

@@ -37,8 +37,8 @@
   id presentingWindow = OCMStrictClassMock([NSWindow class]);
 #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
   NSString *loginHint = @"login_hint";
-  GIDSignInCompletion completion = ^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) {};
-  
+  void (^completion)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error) =
+      ^(GIDUserAuth *_Nullable userAuth, NSError * _Nullable error) {};
   GIDSignInInternalOptions *options =
       [GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
 #if TARGET_OS_IOS || TARGET_OS_MACCATALYST
@@ -63,9 +63,9 @@
 }
 
 - (void)testSilentOptions {
-  GIDSignInCompletion completion = ^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) {};
-  GIDSignInInternalOptions *options = [GIDSignInInternalOptions
-                                       silentOptionsWithCompletion:completion];
+  void (^completion)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error) =
+      ^(GIDUserAuth *_Nullable userAuth, NSError * _Nullable error) {};
+  GIDSignInInternalOptions *options = [GIDSignInInternalOptions silentOptionsWithCompletion:completion];
   XCTAssertFalse(options.interactive);
   XCTAssertFalse(options.continuation);
   XCTAssertNil(options.extraParams);

+ 20 - 9
GoogleSignIn/Tests/Unit/GIDSignInTest.m

@@ -241,7 +241,7 @@ static void *kTestObserverContext = &kTestObserverContext;
   NSString *_hint;
 
   // The completion to be used when testing |GIDSignIn|.
-  GIDSignInCompletion _completion;
+  GIDUserAuthCompletion _completion;
 
   // The saved authorization request.
   OIDAuthorizationRequest *_savedAuthorizationRequest;
@@ -346,10 +346,10 @@ static void *kTestObserverContext = &kTestObserverContext;
   _hint = nil;
 
   __weak GIDSignInTest *weakSelf = self;
-  _completion = ^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) {
+  _completion = ^(GIDUserAuth *_Nullable userAuth, NSError * _Nullable error) {
     GIDSignInTest *strongSelf = weakSelf;
-    if (!user) {
-      XCTAssertNotNil(error, @"should have an error if user is nil");
+    if (!userAuth) {
+      XCTAssertNotNil(error, @"should have an error if the userAuth is nil");
     }
     XCTAssertFalse(strongSelf->_completionCalled, @"callback already called");
     strongSelf->_completionCalled = YES;
@@ -456,7 +456,7 @@ static void *kTestObserverContext = &kTestObserverContext;
 
   XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called."];
 
-  [_signIn restorePreviousSignInWithCompletion:^(GIDGoogleUser * _Nullable user,
+  [_signIn restorePreviousSignInWithCompletion:^(GIDGoogleUser *_Nullable user,
                                                  NSError * _Nullable error) {
     [expectation fulfill];
     XCTAssertNotNil(error, @"error should not have been nil");
@@ -1073,6 +1073,7 @@ static void *kTestObserverContext = &kTestObserverContext;
   NSError *handledError = [NSError errorWithDomain:kGIDSignInErrorDomain
                                               code:kGIDSignInErrorCodeEMM
                                           userInfo:emmError.userInfo];
+  
   completion(handledError);
 
   [self waitForExpectationsWithTimeout:1 handler:nil];
@@ -1220,10 +1221,13 @@ static void *kTestObserverContext = &kTestObserverContext;
     }
   } else {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Callback called"];
-    GIDSignInCompletion completion = ^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) {
+    void (^completion)(GIDUserAuth *_Nullable userAuth, NSError *_Nullable error) =
+    ^(GIDUserAuth *_Nullable userAuth, NSError * _Nullable error) {
       [expectation fulfill];
-      if (!user) {
-        XCTAssertNotNil(error, @"should have an error if user is nil");
+      if (userAuth) {
+          XCTAssertEqualObjects(userAuth.serverAuthCode, kServerAuthCode);
+      } else {
+        XCTAssertNotNil(error, @"Should have an error if the userAuth is nil");
       }
       XCTAssertFalse(self->_completionCalled, @"callback already called");
       self->_completionCalled = YES;
@@ -1348,6 +1352,11 @@ static void *kTestObserverContext = &kTestObserverContext;
                                                     profileData:SAVE_TO_ARG_BLOCK(profileData)];
     }
   }
+  
+  // CompletionCallback - mock server auth code parsing
+  if (!keychainError) {
+    [[[_authState expect] andReturn:tokenResponse] lastTokenResponse];
+  }
 
   if (restoredSignIn && !oldAccessToken) {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called"];
@@ -1361,11 +1370,13 @@ static void *kTestObserverContext = &kTestObserverContext;
     _savedTokenCallback(tokenResponse, nil);
   }
 
-  [_authState verify];
   if (keychainError) {
     return;
   }
   [self waitForExpectationsWithTimeout:1 handler:nil];
+  
+  [_authState verify];
+  
   XCTAssertTrue(_keychainSaved, @"should save to keychain");
   XCTAssertNotNil(authState);
   // Check fat ID token decoding

+ 5 - 5
Samples/ObjC/SignInSample/Source/SignInViewController.m

@@ -259,8 +259,8 @@ static NSString * const kClientID =
 - (IBAction)signIn:(id)sender {
   [GIDSignIn.sharedInstance signInWithConfiguration:_configuration
                            presentingViewController:self
-                                           callback:^(GIDGoogleUser * _Nullable user,
-                                                      NSError * _Nullable error) {
+                                           callback:^(GIDUserAuth *_Nullable userAuth,
+                                                      NSError *_Nullable error) {
     if (error) {
       self->_signInAuthStatus.text =
           [NSString stringWithFormat:@"Status: Authentication error: %@", error];
@@ -278,7 +278,7 @@ static NSString * const kClientID =
 }
 
 - (IBAction)disconnect:(id)sender {
-  [GIDSignIn.sharedInstance disconnectWithCallback:^(NSError * _Nullable error) {
+  [GIDSignIn.sharedInstance disconnectWithCallback:^(NSError *_Nullable error) {
     if (error) {
       self->_signInAuthStatus.text = [NSString stringWithFormat:@"Status: Failed to disconnect: %@",
                                       error];
@@ -293,8 +293,8 @@ static NSString * const kClientID =
 - (IBAction)addScopes:(id)sender {
   [GIDSignIn.sharedInstance addScopes:@[ @"https://www.googleapis.com/auth/user.birthday.read" ]
              presentingViewController:self
-                             callback:^(GIDGoogleUser * _Nullable user,
-                                        NSError * _Nullable error) {
+                             callback:^(GIDUserAuth *_Nullable userAuth,
+                                        NSError *_Nullable error) {
     if (error) {
       self->_signInAuthStatus.text = [NSString stringWithFormat:@"Status: Failed to add scopes: %@",
                                       error];

+ 12 - 12
Samples/Swift/DaysUntilBirthday/Shared/Services/GoogleSignInAuthenticator.swift

@@ -48,12 +48,12 @@ final class GoogleSignInAuthenticator: ObservableObject {
     }
 
     GIDSignIn.sharedInstance.signIn(with: configuration,
-                                    presenting: rootViewController) { user, error in
-      guard let user = user else {
+                                    presenting: rootViewController) { userAuth, error in
+      guard let userAuth = userAuth else {
         print("Error! \(String(describing: error))")
         return
       }
-      self.authViewModel.state = .signedIn(user)
+      self.authViewModel.state = .signedIn(userAuth.user)
     }
 
 #elseif os(macOS)
@@ -63,12 +63,12 @@ final class GoogleSignInAuthenticator: ObservableObject {
     }
 
     GIDSignIn.sharedInstance.signIn(with: configuration,
-                                    presenting: presentingWindow) { user, error in
-      guard let user = user else {
+                                    presenting: presentingWindow) { userAuth, error in
+      guard let userAuth = userAuth else {
         print("Error! \(String(describing: error))")
         return
       }
-      self.authViewModel.state = .signedIn(user)
+      self.authViewModel.state = .signedIn(userAuth.user)
     }
 #endif
   }
@@ -102,14 +102,14 @@ final class GoogleSignInAuthenticator: ObservableObject {
     }
 
     GIDSignIn.sharedInstance.addScopes([BirthdayLoader.birthdayReadScope],
-                                       presenting: rootViewController) { user, error in
+                                       presenting: rootViewController) { userAuth, error in
       if let error = error {
         print("Found error while adding birthday read scope: \(error).")
         return
       }
 
-      guard let currentUser = user else { return }
-      self.authViewModel.state = .signedIn(currentUser)
+      guard let userAuth = userAuth else { return }
+      self.authViewModel.state = .signedIn(userAuth.user)
       completion()
     }
 
@@ -119,14 +119,14 @@ final class GoogleSignInAuthenticator: ObservableObject {
     }
 
     GIDSignIn.sharedInstance.addScopes([BirthdayLoader.birthdayReadScope],
-                                       presenting: presentingWindow) { user, error in
+                                       presenting: presentingWindow) { userAuth, error in
       if let error = error {
         print("Found error while adding birthday read scope: \(error).")
         return
       }
 
-      guard let currentUser = user else { return }
-      self.authViewModel.state = .signedIn(currentUser)
+      guard let userAuth = userAuth else { return }
+      self.authViewModel.state = .signedIn(userAuth.user)
       completion()
     }