Правильный способ обновить токен доступа Gmail API в target-c

ios objective-c gmail google-oauth gmail-api

662 просмотра

2 ответа

Я получаю токен доступа в этом методе:

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

  }
}

Итак, после аутентификации это работает нормально, но через некоторое время перестает работать (наверное, из-за истечения срока действия токена). Кроме того, если я использую

[authResult refreshToken]

вместо

authResult.accessToken

это не сработает.

Итак, как правильно обновить токен доступа Gmail, каким способом я должен это сделать?

PS: в документации сказано что

- (void) refreshTokensWithHandler:(GIDAuthenticationHandler)handler

должно помочь, но я не нашел никаких образцов с ним.

Автор: ArtStyle Источник Размещён: 08.11.2019 11:17

Ответы (2)


1 плюс

Чтобы получить токен обновления, вы должны разрешить доступ APIA на стороне сервера для вашего приложения. «Чтобы получить токен доступа и обновить токен для вашего сервера, вы можете запросить одноразовый код авторизации, который ваш сервер обменивает на эти два токена. Вы запрашиваете одноразовый код, указав идентификатор клиента вашего сервера вместе с другими параметрами GIDSignIn. . После успешного подключения пользователя вы найдете одноразовый код в качестве параметра аутентификации server_code, доступный с помощью FinishWithAuth: обработчик ошибок. "

  1. Настройте проект приложения для iOS, как описано в разделе «Начните интеграцию».
  2. Определите приложение делегата приложения: didFinishLaunchingWithOptions: метод, как описано выше в разделе «Включить вход в систему», но для этой реализации вы установите свойство serverClientID, как показано ниже.
-(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. После входа пользователя получите одноразовый код авторизации:
-(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. Безопасно передайте строку serverAuthCode на ваш сервер, используя HTTPS POST.
  2. На внутреннем сервере вашего приложения обменяйте код авторизации на доступ и обновите токены. Используйте токен доступа для вызова API Google от имени пользователя и, при необходимости, сохраните токен обновления, чтобы получить новый токен доступа по истечении срока действия токена доступа.

Вы можете использовать вызовы HTTP / REST .

Вот HTTP-вызов в Python, просто используйте эквивалент Objective-C.

import json
import flask
import requests


app = flask.Flask(__name__)

CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly'
REDIRECT_URI = 'http://example.com/oauth2callback'


@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))
  credentials = json.loads(flask.session['credentials'])
  if credentials['expires_in'] <= 0:
    return flask.redirect(flask.url_for('oauth2callback'))
  else:
    headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
    req_uri = 'https://www.googleapis.com/drive/v2/files'
    r = requests.get(req_uri, headers=headers)
    return r.text


@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
    return flask.redirect(auth_uri)
  else:
    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}
    r = requests.post('https://www.googleapis.com/oauth2/v4/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))


if __name__ == '__main__':
  import uuid
  app.secret_key = str(uuid.uuid4())
  app.debug = False
  app.run()
Автор: noogui Размещён: 24.08.2016 07:20

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).

Автор: ArtStyle Размещён: 03.09.2016 09:42
Вопросы из категории :
32x32