2015-01-04 25 views
11

Używam google o oficjalnym oauth2client.client, aby uzyskać dostęp do google plus api. Mam odświeżony token (który nie wygasa) przechowywany w bazie danych i potrzebuję , aby odtworzyć tymczasowe "Poświadczenia" (token dostępu) z tego.Google API: uzyskiwanie referencji z odświeżającego tokena za pomocą oauth2client.client

Ale nie mogłem znaleźć sposobu na zrobienie tego z oficjalną biblioteką dostarczoną przez google.

Więc włamałem się do niego: użyłem urllib, aby uzyskać dostęp do interfejsu API, który daje mi nowy dostęp access_token z refresh_token. Korzystając z access_token, mogę użyć biblioteki.

Pewnie brakuje mi czegoś!

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) 
+3

Witam, czy znalazłeś rozwiązanie, aby odświeżyć token podczas korzystania z AccessTokenCredentials? Próbuję dowiedzieć się, jak to zrobić, ale nie ma widocznej dokumentacji wokół ... – xavier

+1

Wystarczy, aby zrobić krzywdę w historii, na wypadek, gdyby ktoś uderzył głową w ścianę: Dokumentacja Google'a jest skomplikowana (lub niekompletne) tutaj. 'AccessTokenCredentials' nie zapewnia sposobu na odświeżenie tokena. Więc musisz użyć innych typów poświadczeń, jak wyjaśniono w odpowiedziach poniżej dwie możliwe opcje były dla mnie wykonalne: "OAuth2Credentials' i" GoogleCredentials' ('GoogleCredentials' rozszerza' OAuth2Credentials'). – cmertayak

Odpowiedz

1

Można przechowywać całą poświadczeń zamiast tylko tokena odświeżania:

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

Spójrz na Storage object który robi to w ten sposób.

+0

jak to pomoże mi uzyskać dostęp do tokena w późniejszym czasie? znacznik dostępu zawarty w poświadczeniach wygasa, podczas gdy token odświeżania nie; więc muszę dostać nowy token dostępu później. – bjelli

+2

Wierzę, że credentials.authorize (http) będzie obsługiwać odświeżanie tokena automatycznie przy odpowiedzi 401. – tjsar

+0

Mam odpowiedź '403',' niewystarczającePermissions \t Wskazuje, że użytkownik nie ma wystarczających uprawnień dla podmiot określony w kwerendzie ", które moim zdaniem potrzebuje token dostępu do generowania. Dowolny pomysł? Pracuję nad nim obecnie – swdev

6

Rozwiązałem to dość łatwo (na pewno brakuje Ci this documentation). Jest to fragment mojego kodu, który próbuje użyć programu Picasa API, aby uzyskać wszystkie płyty z aktywnego użytkownika:

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

Użyj metody refresh pochodzących z oauth2client.client.OAuth2Credentials. Myślę, że można nawet użyć if response['status'] != '200'. Muszę to sprawdzić!

+0

Łącze jest zepsute, czy możesz go odświeżyć? –

+1

Gotowe. Możesz to teraz sprawdzić @ RomanLuštrik – swdev

10

używam: 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) 
+0

Chcę użyć ** refresh_token ** (zapisanego w bazie danych), aby pobrać nowy ** access_token ** później. Jeśli używam 'oauth2client.client.GoogleCredentials', jak zasugerowałeś tutaj, czy powinienem zapisać ** kod_zakresu ** również wraz z ** kodem odświeżania ** w mojej bazie danych do wykorzystania w przyszłości? – user2436428

+0

możesz ustawić 'access_token' na' None' (ponieważ i tak odnawiasz token), a 'expires_at' może być również' None' – hansaplast

1

Można konstruować wystąpienie OAuth2Credentials bezpośrednio tak:

import httplib2 
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) 

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

Wow .. 2 lat pytanie, a nie dobrej odpowiedzi .. Nic dziwnego, zważywszy, że Dokumentacja Google to bzdura na ten temat.

Poprawny sposób to zrobić, rozszerzając klasę pamięci oauth2client.client.Storage

przykładową implementację (używając MongoDB zbiórki _google_credentials) byłoby coś takiego:

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) 

Wtedy, kiedy początkowo uzyskać referencje po step2_exchange, należy je zapisać, używając Storage().put:

np .:

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

Kiedy znowu trzeba poświadczenia, po prostu zrobić:

credentials = Storage(user_id).get() 
0

polecam tej metody.

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

Nawet jeśli token dostępu wygasł, poświadczenie nadal jest autoryzowane z powodu tokena odświeżania.