5

This post is a followup to How to do OAuth-requiring operations in a GAE Task Queue?. As suggested by bossylobster in this post, I did try to hardcode the user_id in my script, but the cron task always fails:

  • I can see it being triggered in the logs...

    2013-05-31 14:20:00.879 /update 302 5ms 0kb AppEngine-Google; (+http://code.google.com/appengine)
    0.1.0.1 - - [31/May/2013:11:20:00 -0700] "GET /update HTTP/1.1" 302 385 - "AppEngine-Google; (+http://code.google.com/appengine)" "myapp.appspot.com" ms=6 cpu_ms=0 cpm_usd=0.000043 queue_name=__cron task_name=... app_engine_release=1.8.0 instance=...
    
  • ... however, it always fails (shows up as red "Failed" in AppEngine's Cron Jobs section), and the task queue it's supposed to run never pops up in the Task Queues section.

What I don't understand is that if I open /update manually I have the login prompt below. How is cron supposed to bypass that? How can I debug what's going on?

GAE login prompt

Thanks for the help.

EDIT/followup on @dlebech answer: The problem persists after adding a login: admin line to the concerned url in app.yaml. Locally (by signing in as an administrator and visiting the URL of the handler in your browser as mentioned by the Securing URLs for Cron) everything goes fine, but once I deploy, my app never gets past the OAuth2 decorator:

  • With a few debug print statements...

    import webapp2
    ...
    
    YOUTUBE_RW_SCOPE = "https://www.googleapis.com/auth/youtube"
    YOUTUBE_API_SERVICE_NAME = "youtube"
    YOUTUBE_API_VERSION = "v3"
    print "Building youtube object"
    print "Built youtube object"
    youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION)
    print "Building decorator object"
    decorator = OAuth2DecoratorFromClientSecrets(CLIENT_SECRETS, YOUTUBE_RW_SCOPE)
    print "Built decorator object"
    ...
    
    class FetchHandlerPage(webapp2.RequestHandler):
        print "Entering FetchHandlerPage"
    
        @decorator.oauth_required
        def get(self):
            print "Entering FetchHandlerPage:get"
            gae_user_id = USER_ID
            query_string = urlencode({'user_id': gae_user_id})
            taskqueue.add(url='/fetchworker?' + query_string, method='GET')
    
  • ... here is what I see after deployment in my GAE logs (the logs stops at the last line, nothing happens next):

    2013-05-31 16:12:02.765 /fetch 302 1746ms 0kb AppEngine-Google; (+http://code.google.com/appengine)
    0.1.0.1 - - [31/May/2013:13:12:02 -0700] "GET /fetch HTTP/1.1" 302 385 - "AppEngine-Google; (+http://code.google.com/appengine)" "myapp.appspot.com" ms=1747 cpu_ms=844 cpm_usd=0.000070 queue_name=__cron task_name=... loading_request=1 app_engine_release=1.8.0 instance=...
    I 2013-05-31 16:12:02.444 URL being requested: https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest?userIp=0.1.0.1
    E 2013-05-31 16:12:02.764 Building youtube object
    E 2013-05-31 16:12:02.764 Built youtube object
    E 2013-05-31 16:12:02.764 Building decorator object
    E 2013-05-31 16:12:02.764 Built decorator object
    E 2013-05-31 16:12:02.764 End static variables
    E 2013-05-31 16:12:02.764 Entering FetchHandlerPage
    I 2013-05-31 16:12:02.765 This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This requ
    
Community
  • 1
  • 1
Ronan Jouchet
  • 1,303
  • 1
  • 15
  • 28

1 Answers1

4

How is cron supposed to bypass that?

Make sure the cron url is configured with login: admin and not login: required. Cron jobs "get past the login prompt" automatically. See the documentation for more information.

How can I debug what's going on?

Since a cron job is started by a GET request to a specific url, you should be able to debug the job by just making a GET request to that url and either see what errors the development server makes or see what is in the logs for the GET request.

dlebech
  • 1,817
  • 14
  • 27
  • Hi, thanks for pointing me towards `login:admin`, I didn't understand it had this effect. Sadly, the problem persists (or maybe it's another one? I'm not certain :-/ ). I added a **EDIT/followup on @dlebech answer** section to my original post, what do you think? – Ronan Jouchet May 31 '13 at 20:22
  • Why do you still need the oauth_required decorator? – dragonx May 31 '13 at 20:54
  • @dragonx my app creates YouTube playlists, it needs to go through the [OAuth2 dance](https://developers.google.com/youtube/v3/guides/authentication#OAuth2_Flows), and this decorator seems the recommended/easiest way to go. Am I wrong? – Ronan Jouchet May 31 '13 at 21:41
  • 1
    @RonanJouchet. Yes, this is wrong. If there is no user, then the decorator is not what you want. You don't need it since you have the user ID from `/update?user_id=SOME_VALUE`. – bossylobster May 31 '13 at 22:36
  • Yes I understand that, in my case, the 3 parties of OAuth2 are actually 2, but I don't fully understand the different parts I need to define (my own Flow? Something else?). So I'm back to the OAuth2 help, and I'll post a new question if I still need help. Thanks a lot! – Ronan Jouchet May 31 '13 at 23:23
  • 1
    You probably need oauth2 to login to YouTube. But you're not longer using oauth2 to enter FetchHandlerPage with cron jobs or task queues, those requests are authenticated with Google's User API. – dragonx Jun 01 '13 at 05:28
  • 1
    @RonanJouchet As dragonx hints at, the reason it might work for you is because you are already logged in to your Google account when visiting the url. It would be helpful to see what the oauth_required decorator does. – dlebech Jun 01 '13 at 06:52
  • Thanks everybody! Now I understand what's wrong and that I need to use `access_type=offline` flag, but I think I'll (again) need to be taken by the hand to do so. Help welcome at *[How to make 'access_type=offline' / server-only OAuth2 operations on GAE/Python?](http://stackoverflow.com/questions/16900919/how-to-make-access-type-offline-server-only-oauth2-operations-on-gae-python)* – Ronan Jouchet Jun 03 '13 at 15:57