web-dev-qa-db-fra.com

API Google: obtention des informations d'identification à partir du jeton d'actualisation avec oauth2client.client

J'utilise google officiel oauth2client.client pour accéder à l'API googleplus. J'ai un jeton d'actualisation (qui n'expire pas) stocké dans une base de données et j'ai besoin de recréer les "informations d'identification" temporaires (jeton d'accès) à partir de cela.

Mais je ne pouvais pas trouver un moyen de faire cela avec la bibliothèque officielle fournie par Google.

J'ai donc corrigé le problème: j'ai utilisé urllib pour accéder à l'API qui me donne un nouveau fichier Access_token à partir de refresh_token. En utilisant access_token, je peux ensuite utiliser la bibliothèque.

Je dois manquer quelque chose!

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)
15
bjelli

J'utilise: 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)
17
leah

Je l'ai résolu assez facilement (vous manquez certainement cette documentation ). Ceci est un extrait de mon code qui tente d'utiliser l'API de Picasa pour obtenir tout l'album de l'utilisateur actif:

    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 {}

Utilisez la méthode refresh provenant de oauth2client.client.OAuth2Credentials . Je pense que c'est même correct d'utiliser if response['status'] != '200'. Je dois vérifier ça!

5
swdev

Vous pouvez construire un OAuth2Credentials instance directement comme ceci:

import httplib2
from oauth2client import GOOGLE_REVOKE_URI, GOOGLE_TOKEN_URI, client

CLIENT_ID = '<client_id>'
CLIENT_SECRET = '<client_secret>'
REFRESH_TOKEN = '<refresh_token>'

credentials = client.OAuth2Credentials(
    access_token=None,  # set access_token to None since we use a refresh token
    client_id=CLIENT_ID,
    client_secret=CLIENT_SECRET,
    refresh_token=REFRESH_TOKEN,
    token_expiry=None,
    token_uri=GOOGLE_TOKEN_URI,
    user_agent=None,
    revoke_uri=GOOGLE_REVOKE_URI)

credentials.refresh(httplib2.Http())  # refresh the access token (optional)
print(credentials.to_json())
http = credentials.authorize(httplib2.Http())  # apply the credentials
3
Eugene Yarmash

Je recommande cette méthode.

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

Même si le jeton d'accès a expiré, les informations d'identification sont toujours autorisées en raison du jeton d'actualisation.

2
KiHyun Nam

Vous pouvez stocker les informations d'identification complètes plutôt que le seul jeton d'actualisation:

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

Regardez l'objet Objet de stockage qui le fait de cette façon.

1
tjsar

Si vous utilisez l'application de démonstration 2018 Youtube Python Quickstart à l'aide de google-auth, vous ne pouvez pas utiliser le stockage de oauth2client.

Alors, voici la bonne façon de stocker les informations d'identification

Voici une solution partiellement efficace pour google-auth, manquant le traitement correct du cas où le jeton expire:

import os
import json
import os.path
import google.oauth2.credentials
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google_auth_oauthlib.flow import InstalledAppFlow

CLIENT_SECRETS_FILE = "client_secret.json"
SCOPES = ['https://www.googleapis.com/auth/youtube.force-ssl']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'

def get_authenticated_service():

  if os.path.isfile("credentials.json"):
    with open("credentials.json", 'r') as f:
      creds_data = json.load(f)
    creds = Credentials(creds_data['token'])

  else:
    flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
    creds = flow.run_console()
    creds_data = {
          'token': creds.token,
          'refresh_token': creds.refresh_token,
          'token_uri': creds.token_uri,
          'client_id': creds.client_id,
          'client_secret': creds.client_secret,
          'scopes': creds.scopes
      }
    print(creds_data)
    with open("credentials.json", 'w') as outfile:
      json.dump(creds_data, outfile)
  return build(API_SERVICE_NAME, API_VERSION, credentials = creds)

def channels_list_by_username(service, **kwargs):
  results = service.channels().list(**kwargs).execute()
  print('This channel\'s ID is %s. Its title is %s, and it has %s views.' %
       (results['items'][0]['id'],
        results['items'][0]['snippet']['title'],
        results['items'][0]['statistics']['viewCount']))

if __== '__main__':
  os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
  service = get_authenticated_service()
  channels_list_by_username(service, part='snippet,contentDetails,statistics', forUsername='GoogleDevelopers')
1
Ray Hulha

Wow .. 2 ans question et pas une bonne réponse .. Pas de surprise étant donné que la documentation de Google est la merde à ce sujet.

Pour ce faire, vous devez étendre la classe de stockage oauth2client.client.Storage

Un exemple d'implémentation (en utilisant mongodb collection _google_credentials) serait quelque chose comme:

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)

Ensuite, lorsque vous obtenez initialement les informations d'identification après step2_exchange, vous devez les stocker à l'aide de Storage().put:

par exemple:

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

Lorsque vous avez à nouveau besoin des informations d'identification, procédez comme suit:

credentials = Storage(user_id).get()
0
599644