如何在iOS中使用GIDSignIn和GTMOAuth2Authentication获取刷新令牌?

时间:2015-05-29 06:24:48

标签: ios oauth-2.0 youtube-api google-plus

我正在编写一个iOS应用程序,它使用Google的GIDSignIn [1]登录用户,GTLServiceYoutube对Youtube执行查询(上传视频和检索Youtube视频列表)。

当用户首次登录时,此工作正常,但大约一小时后,访问令牌过期,并且由于401错误(凭据无效),用户无法再使用GTLServiceYoutube执行查询。

成功登录后,我使用以下代码设置GTMOAuth2Authentication:

- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user withError:(NSError *)error {

    if (error == nil) {
        [self setAuthorizerForSignIn:signIn user:user];
    }
    [super signIn:signIn didSignInForUser:user withError:error];
}

- (void)setAuthorizerForSignIn:(GIDSignIn *)signIn user:(GIDGoogleUser *)user {
     GTMOAuth2Authentication *auth = [[GTMOAuth2Authentication alloc] init];

    [auth setClientID:signIn.clientID];
    [auth setClientSecret:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"GoogleClientSecret"]];
    [auth setUserEmail:user.profile.email];
    [auth setUserID:user.userID];
    [auth setAccessToken:user.authentication.accessToken];
    [auth setRefreshToken:user.authentication.refreshToken];
    [auth setExpirationDate: user.authentication.accessTokenExpirationDate];
    [[UserManager sharedInstance].youTubeService setAuthorizer:auth];
}

其中[[UserManager sharedInstance].youTubeService是GTLServiceYouTube的一个实例。

唯一的问题是GTLServiceYouTube。 GIDSignIn似乎处理刷新令牌,因此用户始终在首次登录后登录。但是GTLOAuth2Authentication仅在首次登录时有效,并在一小时后被破坏。

所以我的问题是:我在这里做错了吗?或者我在刷新后遗漏了一些东西以获得GTMOAuth2Authentication中的正确访问令牌?

[1] https://developers.google.com/identity/sign-in/ios/api/interface_g_i_d_sign_in

3 个答案:

答案 0 :(得分:3)

我认为正确的方法是在重新打开应用程序或需要刷新令牌时将用户重新签名。这可以通过调用[[GIDSignIn sharedInstance] signInSilently]来完成,然后在完成使用新的身份验证令牌更新钥匙串或数据存储区时完成。

答案 1 :(得分:2)

GoogleSignIn 2.1.0起,拨打[GIDSignIn sharedInstance].signInSilently;即可更新[GIDSignIn sharedInstance].currentUser.authentication中存储的凭据。

如果您正在使用Cocoapods,请在项目上运行pod update以更新到2.1.0 SDK。

答案 2 :(得分:0)

使用GTMOAuth2Authentication,您可以使用authorizeRequest:方法强制刷新身份验证令牌。

来自GTMOAuth2Authentication.h

// The request argument may be nil to just force a refresh of the access token,
// if needed.

- (void)authorizeRequest:(NSMutableURLRequest *)request
       completionHandler:(void (^)(NSError *error))handler;

实现:

// In your sign in method
[[GPPSignIn sharedInstance] setKeychainName:@"googleAuth"];

// ...

// Retrieving auth and refreshing token
GTMOAuth2Authentication *auth;
auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:@"googleAuth"
                                                             clientID:@"kYourGoogleClientId"
                                                         clientSecret:@"kYourGoogleClientSecret"];

NSLog(@"old auth: %@", auth);

[auth authorizeRequest:nil completionHandler:^(NSError *error) {
    if (error) {
        // no auth data or refresh failed
        NSLog(@"Error: %@", error);
    } else {
        // Auth token refresh successful
        NSLog(@"new auth: %@", auth);
    }
}];