5

Dieser Beitrag ist eine Nachfolge zu How to make 'access_type=offline'/server-only OAuth2 operations on GAE/Python. Der http = credentials.authorize(httplib2.Http()) Teil schlägt nicht mehr fehl, wenn die Prüfung, aber es scheint es noch nicht, wenn sie von GAE cron, wo es nicht mehr mein aktualisieren access_token:Wie zu vermeiden 'Fehler beim Abrufen des Zugriffstokens: {"error": "invalid_grant"}' in offline GAE Cron-Aufgaben?

  1. Ich kann meinen Job laufen manuell durch /fetch aufrufen, sagen um 11:45 .
  2. Planung sofort ein /cronfetch Job um 11:55 funktioniert dann, ohne access_token Problem.
  3. Aber dann wachte ich heute morgen zu sehen, dass die gleiche/cronfetch Aufgabe (gleiche, außer dem Zeitpunkt, der um 01:00 Uhr für meine Nicht-Test täglichen Aufgabe ist) fehlgeschlagen:

    I 2013-06-10 05:53:51.324 make: Got type <class 'google.appengine.api.datastore_types.Blob'> 
    I 2013-06-10 05:53:51.325 validate: Got type <class 'oauth2client.client.OAuth2Credentials'> 
    I 2013-06-10 05:53:51.327 URL being requested: https://www.googleapis.com/youtube/v3/playlists?alt=json&part=snippet%2Cstatus 
    I 2013-06-10 05:53:51.397 Refreshing due to a 401 
    I 2013-06-10 05:53:51.420 make: Got type <class 'google.appengine.api.datastore_types.Blob'> 
    I 2013-06-10 05:53:51.421 validate: Got type <class 'oauth2client.client.OAuth2Credentials'> 
    I 2013-06-10 05:53:51.421 Refreshing access_token 
    I 2013-06-10 05:53:51.458 Failed to retrieve access token: { "error" : "invalid_grant" } 
    I 2013-06-10 05:53:51.468 make: Got type <class 'google.appengine.api.datastore_types.Blob'> 
    I 2013-06-10 05:53:51.468 validate: Got type <class 'oauth2client.client.OAuth2Credentials'> 
    I 2013-06-10 05:53:51.471 validate: Got type <class 'oauth2client.client.OAuth2Credentials'> 
    I 2013-06-10 05:53:51.471 get: Got type <class 'oauth2client.appengine.CredentialsModel'> 
    E 2013-06-10 05:53:51.480 invalid_grant Traceback (most recent call last): File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in 
    

Diese Mailingliste Nachricht Getting "invalid_grant" error on token refresh (+ SO post 1, SO post 2, SO post 3) sieht ähnlich wie mein Problem, aber es scheint mit einem Token access_type=online geschieht. In meinem Fall verwende ich einfach den Standard access_type=offline, und ich sehe die "Führen Sie diese Operationen, wenn ich nicht die Anwendung verwende" Erwähnung in der ersten Zugriffsanforderung.

Ich habe gerade einen Cron-Lauf um 08:25 umgestellt (wobei ich darauf bedacht bin, keinen manuellen zu starten) mit Debug-Print-Anweisungen, die ich für GitHub an dich übergeben habe. Hier ist, was ich bekomme, es ist ähnlich, aber nicht identisch (Beachten Sie, dass die letzten paar Zeilen falsch sortiert erscheinen, ich mache definitiv keine Sachen von OAuth2 in create_playlist, bis alle Quellen gelesen sind). So ignoriert die schiefe Ordnung (? GAE Logging-Artefakt), so scheint es my http = credentials.authorize(Http()) call in create_playlist(self), currently at line 144 falsch ist:

... 
    E 2013-06-10 08:26:12.817 http://www.onedayonemusic.com/page/2/ : found embeds ['80wWl_s-HuQ', 'kb1Nu75l1vA', 'kb1Nu75l1vA', 'RTWcNRQtkwE', 'RTWcNRQtkwE', 'ZtDXezAhes8', 'ZtDXezAhes8', 'cFGxNJhKK9c', 'cFGxNJhKK9c' 
    I 2013-06-10 08:26:14.019 make: Got type <class 'google.appengine.api.datastore_types.Blob'> 
    I 2013-06-10 08:26:14.020 validate: Got type <class 'oauth2client.client.OAuth2Credentials'> 
    I 2013-06-10 08:26:14.022 URL being requested: https://www.googleapis.com/youtube/v3/playlists?alt=json&part=snippet%2Cstatus 
    I 2013-06-10 08:26:14.100 Refreshing due to a 401 
    I 2013-06-10 08:26:14.105 make: Got type <class 'google.appengine.api.datastore_types.Blob'> 
    I 2013-06-10 08:26:14.106 validate: Got type <class 'oauth2client.client.OAuth2Credentials'> 
    I 2013-06-10 08:26:14.106 Refreshing access_token 
    E 2013-06-10 08:26:18.994 Deadline exceeded while waiting for HTTP response from URL: https://accounts.google.com/o/oauth2/token Traceback (most recent call last): File "/pyt 
    E 2013-06-10 08:26:18.996 http://www.onedayonemusic.com/page/3/ : found embeds ['80wWl_s-HuQ', '6VNu2MLdE0c', '6VNu2MLdE0c', 'YwQilKbK9Mk', 'YwQilKbK9Mk', 'KYdB3rectmc', 'KYdB3 
    E 2013-06-10 08:26:18.996 crawl_videos end 
    E 2013-06-10 08:26:18.996 create_playlist start 
    E 2013-06-10 08:26:18.996 create_playlist got creds 
    E 2013-06-10 08:26:18.996 create_playlist authorized creds 

→ Warum hat die Cron-Job Arbeit 5min nach einem manuellen laufen, aber 6 Stunden nicht später? Ich dachte, das Refresh-Token ist nie abgelaufen. Was mache ich falsch?

Beachten Sie, dass meine erste GAE Arbeit ist, und mein zweites Python-Programm überhaupt, allgemeinen Code-Review/Beratung ist sehr willkommen, aber bitte sanft sein :)

Der Code ist auf GitHub und meine Instanz kann bei dailygrooves.org erreicht werden . Danke für Ihre Hilfe!

Antwort

3

Eine invalid_grant wird zurückgegeben, wenn das Aktualisierungstoken nicht zum Abrufen eines neuen Zugriffstokens vom aktuellen Benutzer verwendet werden kann. Dies wird Ihnen geschieht, weil die gespeicherte Credentials Objekt ein Null-Aktualisierungs-Token hat, das heißt

>>> credentials.refresh_token is None 
True 

Wie in der HINWEIS in How to make 'access_type=offline'/server-only OAuth2 operations on GAE/Python? erwähnt:

Wenn ein Benutzer bereits hat Ihre Client-ID autorisiert, In den nachfolgenden Zeiten, in denen Sie OAuth für diese Benutzer ausführen, sehen sie das OAuth-Dialogfeld nicht und Sie erhalten kein Aktualisierungstoken.

Sie müssen sicherstellen, Ihre Credentials mit einem gültigen Aktualisierungs gespeichert sind Token und der einfachste Weg, dies zu tun, wie sie in Ihrer letzten Frage sowie in allen drei genannten Fragen Sie verknüpft ist approval_prompt=force zu verwenden, bei der Erstellung von Ihr OAuth2WebServerFlow oder OAuth2Decorator Objekt (je nachdem, was Sie verwenden).

+0

OK gut, ich dachte ich brauchte das nicht, weil meine Cron-Aufgabe einmal funktioniert hat! Wie kann die gleiche Cron-Aufgabe ein paar Minuten nach einer manuellen Aufgabe funktionieren, aber 6 Stunden später fehlschlagen? Und eine zweite Frage: Da ich 'OAuth2DecoratorFromClientSecrets' verwende, das zusätzliche' ** kwargs' nicht an 'OAuth2Decorator' weiterleitet, wie empfiehlt es sich, meinen zusätzlichen' approval_prompt = force' Parameter zu setzen? Muss es bei der Init-Zeit gemacht werden, oder ist es in Ordnung, wenn ich meinen 'decorator = OAuth2DecoratorFromClientSecrets ...' anlege und 'decorator.params.update ({approval_prompt = 'force'})' danach mache? Vielen Dank. –

+1

Die Cron-Task funktioniert, wenn "credentials.access_token" gültig ist, das Zugriffstoken jedoch nach 1 Stunde abläuft. Nach dem Ablauf wird 'credentials.refresh_token' benötigt, um ein neues Zugriffstoken zu erhalten. Sie würden 'decorator.params.update ({'approval_prompt': 'force'})' wollen, aber es gibt keinen guten Grund, es nicht einfach an den Konstruktor zu übergeben. – bossylobster

+0

OK, wusste nicht über die 1-Stunden-Grenze, danke. Bezüglich * "gibt es keinen guten Grund, es nicht einfach an den Konstrukteur zu übergeben" *, nun möchte ich! Aber 'OAuth2DecoratorFromClientSecrets' scheint keine zusätzlichen' ** kwargs' zu beachten (das ist, was ich von der Quelle verstehe und die Ausnahme, die es wirft, wenn ich es versuche), also meine Frage. Fehle ich etwas? –

Verwandte Themen