This post is a followup to How to make 'access_type=offline' / server-only OAuth2 operations on GAE/Python. The http = credentials.authorize(httplib2.Http())
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 access_token
:
- I can manually run my job by calling
/fetch
, say at 11:45. - Scheduling immediately a
/cronfetch
job at 11:55 works then, without anyaccess_token
issue. But then, I woke up this morning seeing that the same
/cronfetch
task (same except the timing, which is at 01:00 for my non-test daily task) failed: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
This Getting "invalid_grant" error on token refresh mailing list message (+ SO post 1, SO post 2, SO post 3) look similar to my problem, but it seems to be happening with a access_type=online
token. In my case I just use the default access_type=offline
, and I see the "Perform these operations when I'm not using the application" mention in the initial access request.
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 create_playlist
until all sources are read). So ignoring the skewed order (GAE logging artifact?), it seems my http = credentials.authorize(Http())
call in create_playlist(self)
, currently at line 144 is wrong:
...
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
→ 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?
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 :)
The code is on GitHub and my instance can be reached at dailygrooves.org. Thanks for your help!