2

I have a GAE Python app which I am transitioning from using the App Engine users library to oauth2 using oauth2client.

I read some questions (eg, Managing users authentication in Google App Engine) about using oauth2 with App Engine, and it seemed that the users library does not understand if any other authentication systems (ie, oauth2) are being used to authenticate users.

So I was planning to hand-roll my logged-in/out model using oauth2 instead of the users library. However, I was then surprised to find out that when using the oauth2client.appengine library, the calls to the users library returned data from the oauth2 authenticated user, as shown in this sample code:

import webapp2
from google.appengine.api import users
from oauth2client.appengine import OAuth2Decorator

oauth2deco = OAuth2Decorator(...)

class TestOauth(webapp2.RequestHandler):
  @oauth2deco.oauth_required
  def get(self):
    print users.get_current_user()  # Prints user's email

app = webapp2.WSGIApplication([
    ('/', TestOauth),
    (oauth2deco.callback_path, oauth2deco.callback_handler())
])

In this sample above, the user is prompted to log in with an oauth2 login screen (and not the traditional App Engine login screen from users.CreateLoginURL), but the call to users.get_current_user() works as expected.

I'm curious, how does this work? I see that the users.get_current_user() function returns a new User() object, which seems to read some environment variables: https://cloud.google.com/appengine/docs/standard/python/refdocs/modules/google/appengine/api/users#User

However, I never saw these being set by oauth2client, so I'm still confused.

2 Answers 2

1

Having a look at the oauth2client client library's source code for the @oauth2deco.oauth_required decorator, it appears that internally the library is using the Users API to perform the authentication:

if not user:
    request_handler.redirect(users.create_login_url(
        request_handler.request.uri))
    return

This decorator is defined in the oauth2client.contrib.appengine package, a utility for making it easier to use OAuth 2.0 on Google App Engine.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for pointing that out. I wonder how the users library "knows" how/when to use oauth vs regular GAE auth, though. From what I can tell (from the users doc), some of the env vars like AUTH_DOMAIN, USER_ID, etc. must be being set by oauth2client, however I don't see the oauth2client library actually doing this.
Actually it's the other way around. The oauth2client determines the environment on which the code is running and, if running on App Engine, delegates to the users API for authentication.
1

Well, you're still using the users api:

from google.appengine.api import users

    ...

    print users.get_current_user()  # Prints user's email

To use the oauth2client you'd need to actually configure and use it in the code, its operation is completely separated from the users operation (which will continue to do its job as well if still in use, as you observed).

3 Comments

Maybe I wasn't clear as to exactly what was happening in the sample provided, but the user is prompted to log in with the oauth login screen but never presented with the App Engine users library login screen (from users.CreateLoginURL())
Check if by any chance the user didn't remain logged in (from the users prospective) from before the code was switched over to oauth2 - browser cookies can do that. Try with another user as well. Maybe even keep the users auth around (for testing purposes) so that you can log in/out as needed until you're convinced the new code works as expected.
I don't think it's possible that that's the issue. I'm using an incognito browsing session, but also the value returned by users.get_current_user().user_id() is different when using the code above than using the users library without oauth.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.