如何使用 GIDSignIn 或 GIDAuthentication 刷新 authentication.idToken?
Posted
技术标签:
【中文标题】如何使用 GIDSignIn 或 GIDAuthentication 刷新 authentication.idToken?【英文标题】:How to refresh authentication.idToken with GIDSignIn or GIDAuthentication? 【发布时间】:2016-01-21 15:23:01 【问题描述】:2015 年 10 月 28 日更新 - Release 2.4.0 of Google Sign-In for ios 似乎已经解决了这个问题,新的 GIDAuthentication
方法 getTokensWithHandler:
和 refreshTokensWithHandler:
根据需要刷新了 idToken 和 accessToken。 GIDSignIn
方法 SignInSilently
也刷新两个令牌。
我正在使用适用于 iOS 的 AWS 移动开发工具包,并且我使用 AWS Cognito Sync sample code 作为基础实现了 Google 登录作为 Cognito 凭证提供程序。登录(以及随后的静默登录)流程正常运行,登录用户可以按预期访问 DynamoDB 等 AWS 资源。
我的问题是user.authentication.idToken
在一小时后过期,此时对 AWS 服务的调用失败并出现身份验证错误。我可以使用
user.authentication.accessToken
[self.googleUser.authentication refreshAccessTokenWithHandler:^(NSString *accessToken, NSError *error) ...
但这不会更新idToken
。我也试过打电话
[[GoogleSignIn sharedInstance] signInSilently];
它在会话中第一次被调用时给了我一个有效的 idToken,但是虽然它成功完成它不会在同一会话中的后续调用中刷新 idToken。
我一直在使用
检查/转储令牌内容https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=<idToken>
和
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=<accessToken>
我不确定问题是 GIDSignIn 没有更新 idToken,还是 AWS 应该以某种方式使用 refreshToken 在后端自动刷新用户。无论哪种方式,我都没有想法。
下面的代码 sn-ps。我使用 GoogleSignIn 2.2.0 和 2.3.2 进行了测试,遇到了同样的问题。
...
@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
...
【问题讨论】:
链接到the discussion on AWS forums,以防那边有进展。 我刚刚更新到 iOS 2.4.0 的 Google 登录,它似乎已经修复。如果 idToken 和 accessToken 已过期且身份验证仍然有效,则它们现在都会刷新。这是release notes。我会更新主帖。 【参考方案1】:像这样拨打GIDSignIn's signInSilently method:
[[GIDSignIn sharedInstance] signInSilently];
这最终将再次使用 idToken 调用您的 signIn:didSignInForUser:withError:
委托方法实现。
我已经验证,通过2.4.0 release of Google Sign-In for iOS,上述使用 signInSilently 的方法确实可以为您提供一个未过期的新 idToken。
【讨论】:
我在测试时在回调中收到令牌。我猜你是说当它过期时,它会发送相同的过期令牌。我会看看我今天是否能找到耐心等待它结束并玩它。如果这不起作用,我有另一个想法...... 我说的是 idToken,而不是访问令牌。 signIn 方法将令牌保存在钥匙串中,因此 signInSilently 应该做同样的事情,但调用 [[GIDSignIn sharedInstance] signInSilently].currentUser.authentication.idToken 返回相同的值。 是的,我明白了,在我的快速测试中,IDToken 被返回给了委托人,但是等了一个小时后,我确实看到它继续返回旧的、现在过期的令牌.我认为实现这一点的唯一方法是再次点击谷歌的令牌端点,但目前尚不清楚如何在使用 GIDSignIn 时做到这一点,因为 GIDSignIn 似乎没有公开原始身份验证代码。【参考方案2】:我也有这个问题。尽了一切可能,G+ iOS SDK 根本没有更新该令牌。
我们这边的解决方案是将 refresh_token 发送到我们的服务器,他们能够通过访问一个 Google API 来正确更新他们这边的令牌,然后将新令牌发送回我的应用程序。不幸的是,我现在无法访问那里,只能在明天告诉您确切的 API。
【讨论】:
谢谢贝尼。不幸的是,就我而言,后端是 Amazon Cognito,所以我也无法控制它。 我真的希望您能找到正确的解决方案。如果您成功了,请告诉我们。【参考方案3】:如何在 30 分钟时使用计时器,然后静默调用 signInIn?
【讨论】:
这是一个已修复的错误。 我刚刚发现自己。感谢您的回复,并对过时的帖子表示抱歉。以上是关于如何使用 GIDSignIn 或 GIDAuthentication 刷新 authentication.idToken?的主要内容,如果未能解决你的问题,请参考以下文章
您必须指定 |clientID|对于 |GIDSignIn|尝试使用 Google 登录时出错
使用 GIDSignIn.sharedInstance.clientID 时的错误代码 =
“GIDSignIn”类型的值没有成员“presentingViewController”
使用 GIDSignIn 登录时出现“没有 URL 方案 com-google-gidconsent 的注册处理程序”错误