3

I'm using 'login' option in my app.yaml configuration file for a GAE application. Looks like this:

- url: /admin/.*
  script: myapp.app
  login: admin

- url: /.*
  script: myapp.app
  login: required

UPDATE (by suggestion of bossylobster): I want a user always signed in (unsigned users can't do anything), and I need to know who the user is. Actually, I need OAuth2 credentials to communicate with Google APIs (for example, I need to fetch some user's info with Google Profiles API, and write in the user's calendar with Google Calendar API). Finally, I need an admin user to perform some operations (like create new domain's users, with Google Provisioning API)

I'm using google-api-client library, and playing around with oauth2 decorators. Then, in my RequestHandlers, I have this:

class MainHandler(webapp.RequestHandler):

  @decorator.oauth_aware
  def get(self):
    if decorator.has_credentials():
      # do something

    else:
      url = decorator.authorize_url()
      self.response.out.write(template.render('templates/index.html',
           {'authorize_url': url}))

Finally, I've read about another method:

user = users.get_current_user()
if user:
  # do something
else:
  greeting = ("<a href=\"%s\">Sign in or register</a>." %
    users.create_login_url("/"))

  self.response.out.write("<html><body>%s</body></html>" % greeting)

What is the best method to handle the user's authentication to fit my needs (see UPDATE)?

Many thanks in advance

Community
  • 1
  • 1
Jorge Arévalo
  • 2,468
  • 4
  • 28
  • 41

1 Answers1

6

I think you may be confusing what the OAuth 2.0 decorator does vs. the other two approaches.

The OAuth 2.0 decorator is not specific to your app, you would use it if you want to get OAuth 2.0 credentials for your users and then use those to communicate with Google APIs.

The other two are simply ways to get the user information from a session cookie that is set by App Engine.

If you really want a decorator, you would use login_required, documented here:
https://developers.google.com/appengine/docs/python/tools/webapp/utilmodule

There is no one best approach between specifying in app.yaml, checking if users.get_current_user is None or using @login_required on specified handlers.

A rough approximation of the three distinct times you'd want to use these are the following:

1) If you want users to be logged in, but don't need to know the specific user, use login: required in app.yaml.

2) If want to know the user, but also have a fallback if the user is not logged in, use users.get_current_user and tailor your behavior to the user or to None if that is the returned value.

3) If you want to know the user and always have one logged in, use @login_required.

UPDATE:

(Based on a further explanation of needs.) Since you always want to log your users in and always want OAuth 2.0 credentials for them, you should always use decorator.oauth_required.

As for using the APIs, only the Google Calendar API can be used with the google-api-python-client library. The Google Apps Provisioning API is a Google Data API, while the Calendar API is a discovery-based API.

As a result, you'll need to use the gdata-python-client library to use the Provisioning API. You'll need to manually convert from a oauth2client.client.OAuth2Credentials object to a gdata.gauth.OAuth2Token object to use the same token for either one.

When using OAuth2Decorator, you'll be able to access an instance of oauth2client.client.OAuth2Credentials via decorator.credentials().

SECOND UPDATE:

I recently added support for this to gdata-python-client.

from gdata.gauth import OAuth2TokenFromCredentials
auth_token = OAuth2TokenFromCredentials(decorator.credentials())
auth_token.authorize(client)

The implementation allows the two token/credentials objects decorator.credentials() and auth_token to stay in sync, no matter which object you change values on.

bossylobster
  • 9,603
  • 1
  • 39
  • 55
  • Thanks for your quick response! I always want my user logged in, and know the user. So, I guess I should use 3). But I also need OAuth2 credentials to communicate with Google APIs. May I use @login_required AND oAuth2 decorator in the same method? – Jorge Arévalo Dec 20 '12 at 22:47
  • You should update your question to state this. This was not at all clear from your question. `OAuth2Decorator` extends the `users.get_current_user` behavior and subsequently stores OAuth 2.0 credentials for a signed in user after they have completed the OAuth flow. – bossylobster Dec 20 '12 at 23:01
  • You're right. I've updated the question with a bigger explanation of my needs. – Jorge Arévalo Dec 20 '12 at 23:14
  • Thanks! So I see I'm in the right way. I'm actually using the libraries you said. The "dark" part for me now is the OAuth2 conversions. Your response is absolutely correct and helpful, anyway. Many thanks again! – Jorge Arévalo Dec 21 '12 at 13:32
  • If you want to ask another question about conversion and point me to it, I'd be happy to help there. – bossylobster Dec 21 '12 at 18:50
  • Actually, I'm dealing with this still unresolved problem http://stackoverflow.com/questions/13943321/typeerror-on-freebusy-call-to-google-calendar-api-v3-using-python-apiclient – Jorge Arévalo Dec 22 '12 at 11:26
  • About your last update, my problem is I need 2-legged auth (domain-wide delegation of authority). So, my OAuth 2.0 credentials are not valid. I need admin credentials. Related question here http://stackoverflow.com/questions/14059306/python-gae-app-using-2-legged-oauth-and-3-legged-oauth-at-same-time – Jorge Arévalo Dec 28 '12 at 02:19