Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to avoid 'Failed to retrieve access token: { "error" : "invalid_grant" }' in offline GAE cron tasks?
    text
    copied!<p>This post is a followup to <a href="https://stackoverflow.com/questions/16900919/how-to-make-access-type-offline-server-only-oauth2-operations-on-gae-python/">How to make 'access_type=offline' / server-only OAuth2 operations on GAE/Python</a>. The <code>http = credentials.authorize(httplib2.Http())</code> part no longer fails when testing, but it seems it still does when run by GAE's cron, where it's unable to refresh my <code>access_token</code> :</p> <ol> <li>I can manually run my job by calling <code>/fetch</code>, say at 11:45.</li> <li><strong>Scheduling immediately a <code>/cronfetch</code> job at 11:55 works then</strong>, without any <code>access_token</code> issue.</li> <li><p>But then, I woke up this morning seeing that the <em>same</em> <code>/cronfetch</code> task (same except the timing, which is at 01:00 for my non-test daily task) failed:</p> <pre><code>I 2013-06-10 05:53:51.324 make: Got type &lt;class 'google.appengine.api.datastore_types.Blob'&gt; I 2013-06-10 05:53:51.325 validate: Got type &lt;class 'oauth2client.client.OAuth2Credentials'&gt; I 2013-06-10 05:53:51.327 URL being requested: https://www.googleapis.com/youtube/v3/playlists?alt=json&amp;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 &lt;class 'google.appengine.api.datastore_types.Blob'&gt; I 2013-06-10 05:53:51.421 validate: Got type &lt;class 'oauth2client.client.OAuth2Credentials'&gt; 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 &lt;class 'google.appengine.api.datastore_types.Blob'&gt; I 2013-06-10 05:53:51.468 validate: Got type &lt;class 'oauth2client.client.OAuth2Credentials'&gt; I 2013-06-10 05:53:51.471 validate: Got type &lt;class 'oauth2client.client.OAuth2Credentials'&gt; I 2013-06-10 05:53:51.471 get: Got type &lt;class 'oauth2client.appengine.CredentialsModel'&gt; 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 </code></pre></li> </ol> <p>This <a href="http://code.google.com/p/google-api-python-client/issues/detail?id=90" rel="nofollow noreferrer">Getting "invalid_grant" error on token refresh</a> mailing list message (+ <a href="https://stackoverflow.com/questions/14064630/why-am-i-getting-invalid-grant-for-google-api-calls-from-app-engine">SO post 1</a>, <a href="https://stackoverflow.com/questions/8433990/when-authenticating-with-oauth-and-youtube-always-get-error-invalid-grant-on">SO post 2</a>, <a href="https://stackoverflow.com/questions/13851157/oauth2-and-google-api-access-token-expiration-time">SO post 3</a>) look similar to my problem, but it seems to be happening with a <code>access_type=online</code> token. In my case I just use the default <code>access_type=offline</code>, and I see the <em>"Perform these operations when I'm not using the application"</em> mention in the initial access request. </p> <p>I just re-scheduled a cron run at 08:25 (taking care not to launch a manual one) with debug print statements that I committed to GitHub for you. Here is what I get, it is similar but not identical (Note the few last lines seem ordered incorrectly, I definitely am not doing OAuth2 stuff in <code>create_playlist</code> until all sources are read). So ignoring the skewed order (GAE logging artifact?), it seems <a href="https://github.com/ronjouch/dailygrooves/blob/master/dailygrooves/dailygrooves.py#L144" rel="nofollow noreferrer">my <code>http = credentials.authorize(Http())</code> call in <code>create_playlist(self)</code>, currently at line 144</a> is wrong:</p> <pre><code> ... 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 &lt;class 'google.appengine.api.datastore_types.Blob'&gt; I 2013-06-10 08:26:14.020 validate: Got type &lt;class 'oauth2client.client.OAuth2Credentials'&gt; I 2013-06-10 08:26:14.022 URL being requested: https://www.googleapis.com/youtube/v3/playlists?alt=json&amp;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 &lt;class 'google.appengine.api.datastore_types.Blob'&gt; I 2013-06-10 08:26:14.106 validate: Got type &lt;class 'oauth2client.client.OAuth2Credentials'&gt; 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 </code></pre> <p>&rarr; Why does the cron job work 5min after a manual run, but fails 6hours later? I thought the refresh token never expired. What am I doing wrong? </p> <p>Note that's my first GAE work, and my second Python program at all, general code review/advice is very welcome but please be gentle :)</p> <p>The code is on <a href="https://github.com/ronjouch/dailygrooves" rel="nofollow noreferrer">GitHub</a> and my instance can be reached at <a href="http://www.dailygrooves.org/" rel="nofollow noreferrer">dailygrooves.org</a>. Thanks for your help!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload