Search code examples
iosobjective-cgmailgoogle-oauthgmail-api

Right way to refresh Gmail API access token in objective-c


I get access token in that method:

- (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];

  }
}

So, after auth that's works fine, but after a while it stops working (I guess because token has expired). Also, if I use

[authResult refreshToken]

instead of

authResult.accessToken

it won't work.

So what's the correct way to refresh the Gmail access token, in which method should I do this?

P.S: documentation says that the

- (void) refreshTokensWithHandler:(GIDAuthenticationHandler)handler

should help, but I have not found any samples with it.


Solution

  • So, this is actually simple. To refresh the token you need to use following code:

    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"];
             }
         }];
    

    You can paste it in ViewDidLoad method for instance. So after execution of this code you will have valid access token in UserDefaults (which is USER_CAHCE in my example).