AppEngine OAuth contrib and refresh_token
Posted by ark, ,

I thought I understood OAuth but had a bit of difficulty recently and it was all about how AppEngine and the oauth contrib package and its decorators work so I thought I’d document here.

My app was working great. My OAuth credentials worked fine in dev and worked fine on prod too. But after a while the prod credentials stopped working. Finally I ended up at this answer on stackoverflow. Specifically notice the Note/Gotcha at the end. No problem I thought I’ll just pass in approval_prompt=force and all will be well. BUT NO.

First I was using oauth2client.contrib.appengine.oauth2decorator_from_clientsecrets which didn’t allow me to pass in extra keyword arguments, once I switched to using oauth2client.contrib.appengine.OAuth2DecoratorFromClientSecrets it took my approval_prompt and admonished me that it’s been changed to prompt="consent" but even with that it still didn’t work. I added this code which helped a lot:

    credentials = decorator.credentials
    if credentials.refresh_token is None:
      logging.error('Got credentials with no refresh_token.')
      return self.error(500)

On my dev instance my credentials were fine, but in production still no refresh_token even though I was passing in prompt="consent". Turns out the AppEngine contrib package has ANOTHER layer of caching on top of memcache. So I needed to clear out CredentialsModel and memcache while we’re at it and finally it worked. Here’s the links for the dev and production datastores so you can clear yours out.