UPDATE 2015-10-28 - Release 2.4.0 of Google Sign-In for iOS appears to have resolved this problem, with both the idToken and the accessToken being refreshed as necessary by the new GIDAuthentication
methods getTokensWithHandler:
and refreshTokensWithHandler:
. GIDSignIn
method SignInSilently
also refreshes both tokens.
My problem is that the user.authentication.idToken
expires after one hour and at that point calls to AWS services fail with authentication errors. I can refresh the user.authentication.accessToken
using
[self.googleUser.authentication refreshAccessTokenWithHandler:^(NSString *accessToken, NSError *error) {...}
but this doesn't update the idToken
. I've also tried calling
[[GoogleSignIn sharedInstance] signInSilently];
which gives me a valid idToken the first time it is called in the session, but although it completes successfully it doesn't refresh the idToken on subsequent calls within the same session.
I've been checking/dumping the token contents using
https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=<idToken>
and
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=<accessToken>
I'm not sure whether the problem is that GIDSignIn is not updating idToken, or that AWS should be using the refreshToken somehow to auto-refresh the user at the backend. Either way I'm out of ideas.
Code snippets below. I've tested using GoogleSignIn 2.2.0 and 2.3.2 and experienced the same problem.
...
@interface MySignInClass <GIDSignInDelegate>
...
-(void) signInWithGoogle
{
GIDSignIn *signIn = [GIDSignIn sharedInstance];
signIn.clientID = MY_GOOGLE_CLIENT_ID;
signIn.shouldFetchBasicProfile = YES;
signIn.scopes = [NSArray arrayWithObjects:@"https://www.googleapis.com/auth/userinfo.profile", @"openid", nil];
signIn.delegate = self;
if([signIn hasAuthInKeychain]) {
[signIn signInSilently];
} else {
[signIn signIn];
}
}
...
- (void)signIn:(GIDSignIn *)signIn
didSignInForUser:(GIDGoogleUser *)user
withError:(NSError *)error
{
if (error != nil) {
[self handleSignInError:error]; // Handle error
}
else {
NSString *idToken = user.authentication.idToken;
NSDictionary* logins = @{@"accounts.google.com": idToken};
self.credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:MY_COGNITO_REGION_TYPE
identityId:nil
identityPoolId:MY_COGNITO_IDENTITY_POOL
logins:logins];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc]
initWithRegion:MY_COGNITO_REGION
credentialsProvider:self.credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
// AWSTask stuff removed for simplicity
AWSTask* task = [self.credentialsProvider getIdentityId];
...
}
}
...
- (void)signIn:(GIDSignIn *)signIn
didDisconnectWithUser:(GIDGoogleUser *)user
withError:(NSError *)error
{
[self handleGoogleSignout]; // Do signout stuff
}
...
Call the GIDSignIn's signInSilently method like so:
[[GIDSignIn sharedInstance] signInSilently];
This will end up calling your signIn:didSignInForUser:withError:
delegate method implementation with the idToken again.
I have verified that with the 2.4.0 release of Google Sign-In for iOS the above approach of using signInSilently does indeed work for giving you a new idToken that isn't expired.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With