在objective-c中刷新Gmail API访问令牌的正确方法

时间:2016-08-20 12:07:57

标签: ios objective-c gmail google-oauth gmail-api

我在该方法中获得访问令牌:

- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
  finishedWithAuth:(GTMOAuth2Authentication *)authResult
             error:(NSError *)error {
if (error != nil) {
    [self showAlert:@"Authentication Error" message:error.localizedDescription];
    self.service.authorizer = nil;
}
else {
    self.service.authorizer = authResult;

    NSLog(@"Token: %@ id: %@", authResult.accessToken, authResult.userID);
    [self makeGmailLabelVisibleWithToken:authResult.accessToken]; //make an authorized request to gmailAPI with the access token

    [self dismissViewControllerAnimated:YES completion:nil];

  }
}

所以,在auth之后,它运行正常,但过了一段时间它停止工作(我想因为令牌已经过期)。另外,如果我使用

[authResult refreshToken]

而不是

authResult.accessToken

它不起作用。

那么刷新Gmail访问令牌的正确方法是什么,我应该采用哪种方法?

P.S:documentation

- (void) refreshTokensWithHandler:(GIDAuthenticationHandler)handler

应该有所帮助,但我没有找到任何样品。

2 个答案:

答案 0 :(得分:1)

要获取刷新令牌,您必须为您的应用enable server-side APIA access。 “要获取服务器的访问令牌和刷新令牌,您可以请求服务器为这两个令牌交换的一次性授权码。您可以通过指定服务器的客户端ID以及其他GIDSignIn参数来请求一次性代码。成功连接用户后,您将找到一次性代码作为auth参数server_code,可通过finishedWithAuth:错误处理程序访问。“

  1. 按照开始集成。
  2. 中的说明配置iOS应用项目
  3. 定义您的app delegate的应用程序:didFinishLaunchingWithOptions:方法,如上面启用登录中所述,但是对于此实现,您将设置serverClientID属性,如下所示。
  4. library(dplyr)
    library(ggplot2)    
    
    entitites = LETTERS[1:10]
    # create some sample data
    df_foo = bind_cols(
      data_frame(Group1 = rep(c("A", "B"), each = 100)),
      bind_rows(
        expand.grid(
          Left = entitites, Right = entitites,
          stringsAsFactors = FALSE
        ),
        expand.grid(
          Left = entitites, Right = entitites,
          stringsAsFactors = FALSE
        )
      ),
      data_frame(Value = rpois(200, 15))
    )
    
    # create the summary row & column
    df_foo_aug = bind_rows(
      df_foo,
      df_foo %>% 
        group_by(Left, Group1) %>% 
        summarize(
          Value = sum(Value),
          Right = "Total"
        ),
      df_foo %>% 
        group_by(Right, Group1) %>% 
        summarize(
          Value = sum(Value),
          Left = "Total"
        )
    )
    
    # create the plot
    df_foo_aug %>% 
      ggplot(aes(x = Right, y = Left, fill = Value)) + 
      geom_tile() + 
      facet_wrap(~ Group1) + 
      theme_bw()
    
    1. 用户登录后,检索一次性授权码:
    2. -(BOOL)application:(UIApplication *)application
          didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      
        [GIDSignIn sharedInstance].clientID = @"APP_CLIENT_ID";
        [GIDSignIn sharedInstance].serverClientID = @"SERVER_CLIENT_ID";
      
        // Additional scopes, if any
        // [GIDSignIn sharedInstance].scopes = @[ @"other_scope" ];
      
        return YES;
      }
      
      1. 使用HTTPS POST安全地将serverAuthCode字符串传递给您的服务器。
      2. 在您应用的后端服务器上,交换授权码以进行访问并刷新令牌。使用访问令牌代表用户调用Google API,并且可选地,存储刷新令牌以在访问令牌过期时获取新的访问令牌。
      3. 您可以使用HTTP/REST来电。

        这是Python中的HTTP调用,只需使用Objective-C等效。

        -(void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
            withError:(NSError *)error {
          // Perform any operations on signed in user here.
          // user.serverAuthCode now has a server authorization code!
        }
        

答案 1 :(得分:0)

所以,这实际上很简单。要刷新令牌,您需要使用以下代码:

self.service = [[GTLServiceGmail alloc] init];
self.service.authorizer =
[GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
                                                      clientID:kClientID
                                                  clientSecret:nil];

[[GIDSignIn sharedInstance] setScopes:[NSArray arrayWithObject: @"https://www.googleapis.com/auth/plus.me"]];
[GIDSignIn sharedInstance].clientID = kClientID;

GTMOAuth2Authentication *auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
                                                                                      clientID:kClientID
                                                                                  clientSecret:nil];

NSLog(@"accessToken: %@", auth.accessToken); //If the token is expired, this will be nil

// authorizeRequest will refresh the token, even though the NSURLRequest passed is nil
[auth authorizeRequest:nil
     completionHandler:^(NSError *error) {
         if (error) {
             NSLog(@"error: %@", error);
         }
         else {
             [USER_CACHE setValue:auth.accessToken forKey:@"googleAccessToken"];
         }
     }];

例如,您可以将其粘贴到ViewDidLoad方法中。因此,执行此代码后,您将在UserDefaults中拥有有效的访问令牌(在我的示例中为USER_CAHCE)。