Google API: получение учетных данных из токена обновления с помощью oauth2client.client

Я использую googles официальный oauth2client.client для доступа к google plus api. У меня есть токен обновления (который не истекает), хранящийся в базе данных, и ему нужно воссоздать временные «Учетные данные» (токен доступа).

Но я не мог найти способ сделать это с официальной библиотекой, поставляемой Google.

Поэтому я взломал его: использовал urllib для доступа к API, который дает мне новый access_token из refresh_token. Используя access_token, я могу использовать библиотеку.

Я, должно быть, скучаю!

from apiclient import discovery from oauth2client.client import AccessTokenCredentials from urllib import urlencode from urllib2 import Request , urlopen, HTTPError import json # ========================================== def access_token_from_refresh_token(client_id, client_secret, refresh_token): request = Request('https://accounts.google.com/o/oauth2/token', data=urlencode({ 'grant_type': 'refresh_token', 'client_id': client_id, 'client_secret': client_secret, 'refresh_token': refresh_token }), headers={ 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' } ) response = json.load(urlopen(request)) return response['access_token'] # ========================================== access_token = access_token_from_refresh_token(CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN) # now I can use the library properly credentials = AccessTokenCredentials(access_token, "MyAgent/1.0", None) http = credentials.authorize(httplib2.Http()) service = discovery.build('plus', 'v1', http=http) google_request = service.people().get(userId='me') result = google_request.execute(http=http) 

Я использую: oauth2client.client.GoogleCredentials

  cred = oauth2client.client.GoogleCredentials(access_token,client_id,client_secret, refresh_token,expires_at,"https://accounts.google.com/o/oauth2/token",some_user_agent) http = cred.authorize(httplib2.Http()) cred.refresh(http) self.gmail_service = discovery.build('gmail', 'v1', credentials=cred) 

Я решил это довольно легко (вы, конечно, пропустите эту документацию ). Это фрагмент моего кода, который пытается использовать API Picasa для получения всего альбома от активного пользователя:

  http = httplib2.Http(ca_certs=os.environ['REQUESTS_CA_BUNDLE']) try: http = self.oauth.credentials.authorize(http) response, album_list = http.request(Picasa.PHOTOS_URL, 'GET') if response['status'] == '403': self.oauth.credentials.refresh(http) response, album_list = http.request(Picasa.PHOTOS_URL, 'GET') album_list = json.load(StringIO(album_list)) except Exception as ex: Logger.debug('Picasa: error %s' % ex) return {} 

Используйте метод refresh исходящий из oauth2client.client.OAuth2Credentials . Я думаю, что даже нормально использовать, if response['status'] != '200' . Надо проверить это!

Я рекомендую этот метод.

 from oauth2client import client, GOOGLE_TOKEN_URI CLIENT_ID = "client_id" CLIENT_SECRET = "client_secret" REFRESH_TOKEN = "refresh_token" credentials = client.OAuth2Credentials( access_token = None, client_id = CLIENT_ID, client_secret = CLIENT_SECRET, refresh_token = REFRESH_TOKEN, token_expiry = None, token_uri = GOOGLE_TOKEN_URI, token_ id = None, revoke_uri= None) http = credentials.authorize(httplib2.Http()) 

Даже если токен доступа истек, учетные данные все еще авторизуются из-за токена обновления.

Вы можете хранить все учетные данные, а не только токен обновления:

 json = credentials.to_json() credentials = Credentials.new_from_json(json) 

Посмотрите на объект Storage, который делает это таким образом.

Вы можете OAuth2Credentials экземпляр OAuth2Credentials прямо следующим образом:

 from oauth2client import client, GOOGLE_TOKEN_URI, GOOGLE_REVOKE_URI CLIENT_ID = "<client identifier>" CLIENT_SECRET = "<client secret>" REFRESH_TOKEN = "<refresh_token>" credentials = client.OAuth2Credentials( None, CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN, None, GOOGLE_TOKEN_URI, None, revoke_uri=GOOGLE_REVOKE_URI) # refresh the access token (or just try using the service) credentials.refresh(httplib2.Http()) print(credentials.to_json()) 

Ух ты .. 2-х летный вопрос и не очень хороший ответ. Неудивительно, что документация Google – это дерьмо.

Правильный способ сделать это – расширить класс хранения oauth2client.client.Storage

Пример реализации (с использованием коллекции _google_credentials ) будет выглядеть примерно так:

 class Storage(oauth2client.client.Storage): def __init__(self, key): super(Storage, self).__init__() self._key = key def locked_get(self): if not self._key: return None data = _google_credentials.find_one({'_id': self._key}) if not data: return None credentials = oauth2client.client.Credentials.new_from_json(json.dumps(data)) credentials.set_store(self) return credentials def locked_put(self, credentials): data = json.loads(credentials.to_json()) _google_credentials.update_one({'_id': self._key}, {'$set': data}, upsert=True) credentials.set_store(self) def locked_delete(self): bucket.delete(self._key) 

Затем, когда вы сначала получаете учетные данные после step2_exchange , вам необходимо сохранить их с помощью Storage().put step2_exchange :

например:

 credentials = flow.step2_exchange(code) Storage(user_id).put(credentials) 

Когда вам снова потребуются учетные данные, просто выполните:

 credentials = Storage(user_id).get()