Sunday, February 12, 2012

Simple auth on App Engine without passwords













class AuthHandler(webapp2.RequestHandler, SimpleAuthHandler):

  def _on_signin(self, data, auth_info, provider):
    data is a user info dictionary.
    auth_info contains access token or oauth token and secret.

    See what's in it with, auth_info)

    auth_id = auth_info['id']

    # 1. check whether user exist, e.g.
    #    User.get_by_auth_id(auth_id)
    # 2. create a new user if it doesn't
    #    User(**data).put()
    # 3. sign in the user
    #    self.session['_user_id'] = auth_id
    # See more on how to work the above steps here:
  def logout(self):

  def _callback_uri_for(self, provider):

  def _get_consumer_info_for(self, provider):
    For OAuth 2.0 you should also return a scope, e.g.
    The scope depens solely on the provider.
    See example/
    return secrets.AUTH_CONFIG[provider]


The method is being passed 3 argumens:
  "id": "114517983826182834234",
  "email": "",
  "verified_email": true,
  "name": "Alex Vagin",
  "given_name": "Alex",
  "family_name": "Vagin",
  "link": "",
  "picture": "",
  "gender": "male",
  "locale": "en"

  "grant_type": "authorization_token",
  "client_id": "",
  "redirect_uri": ""


Deployed version of the example is here:



Let me know what you think!

pip install simpleauth.


  1. Hi Alex, thanks for posting this code. I am just starting out with GAE, authentication, webapps etc and found this very easy to get up and running.

    But, I am having some trouble getting my head around how to extend this. As a "simple" test I am trying to access a Google Data feed after authenticating. I am sure that I am missing something very simple, but I cant figure out how to get the token (not the string that is displayed on the profile page) back so I can access the feed:

    class DocsHandler(BaseRequestHandler):
    def get(self):
    if self.logged_in:
    session = self.auth.get_user_by_session()
    token = session['token']
    client = gdata.spreadsheets.client.SpreadsheetsClient()

    --> #how to get the real token back ???
    --> token.authorize(client)

    This yields: AttributeError: 'unicode' object has no attribute 'authorize'

    I have gone through your code and all of the webapp2 docs, tried everything I could think of with User and UserToken, etc, and cant get anything to work. What am I missing here?


  2. Hey Gary, I see what you mean. The session['token'] is a so-called request token needed to get an access token (I know, lots of "tokens", sorry).

    The access token is being passed in _on_signin() callback (see, where auth_data argument would be something like this:

    {'access_token': 'ya29.AHES6ZRf23UHVi1V2.....', 'token_type': 'Bearer', 'expires_in': 3600, 'id_token': 'eyJhbGciOiJSUzI1N....a4BgMjRUW2Rs1038'}

    Now, if you're referring to, you'll have instantiate their own OAuth2Token passing it the above access_token (you'll have to store it somewhere during e.g. _on_signin() so that you can use it later on):

    token = gdata.gauth. OAuth2Token(
    client_id='your registered app ID ',
    client_secret='your app secret',
    scope='scope to access google spreadsheet',
    user_agent='some ID, e.g. MyApp',
    access_token = access_token_from_the_above


    OAuth2Token is defined here:

    Also, see some alternative here:

    Hope this helps!

  3. Ah, OK... So all the pieces were there, I just couldnt figure out how to make them fit ;-) Thanks a lot for the guidance, this is very helpful to understanding how the whole process works.

  4. Hi Alex, thanks a lot for making SimpleAuth. It's a great shortcut towards more user-friendly authentification!

    Obviously it's still possible that a user doesn't have (or doesn't want to use) any of the provided login methods. In that case it's probably a good idea to provide a simple username/password or email/password login as a fallback.

    How would you extend SimpleAuth to enable that?

    Of course it's possible to simply hack that functionality into the SimpleAuth flow, but you seem to know AppEngine and its APIs very well and I'd like to hear your opinion on what the best solution might be.


  5. Hey Tim, good point!

    The simple username/password auth is already there, in webapp2, but you're making a very good point and I'll definitely include this in the example and SimpleAuth itself.

    Will try get this done in the next days. I'll keep you posted.

    Thanks for the feedback!

  6. Hi Alex,

    Love SimpleAuth - so easy to implement and yet so flexible. Would you have any tips for accessing a webapp with simpleauth from a command line prompt (posting using httplib etc.). It's wrecking my head :/


  7. Hey Stephen!
    If I'm understand it correctly, you might try doing it using the remote API, e.g.:

    PYTHONPATH=.:$PYTHONPATH /usr/local/google_appengine/ -s localhost:8080

    dev~example> import simpleauth
    dev~example> handler = simpleauth.SimpleAuthHandler()
    dev~example> auth_info = {'access_token':'my token'}
    dev~example> google_user_dict = handler._get_google_user_info(auth_info)

    You can basically call any method on that 'handler', which is defined starting from here:

    Hope this helps! If not, we now have a google group :)!forum/gae-simpleauth

  8. Hi Alex,
    I look at SimpleAuth and I don't see password flow (aka resource owner password credentials grant) that Time suggested. My understanding is that webapp2.extensions.auth generates the access_token but then it stores it inside a session and session iside a cookie (not necessarily but by default). That is a problem to me as I try to implement API-only service for native mobile clients. I thought that all I need is a simple bearer access_token that client app receives from the server and then keeps including into a header. Do I get it wrong? Is it implemented in SimpleAuth and I just missed it?

  9. Hey Michael. SimpleAuth doesn't do password flows but this post will clarify things:

    You get it right. Only that SimpleAuth doesn't provide an authentication mecanism for your app. It only does authentication with third party providers. Everything else is up to you.

    For instance, if you look at the example app, I'm using webapp2's built-in get_user_by_session() method ( which indeed uses cookies.

    For your API-only auth you could, for instance, parse an auth header, extract a token and then use get_user_by_token() method from webapp2_extras.auth:

    Hope this helps.


What do you think?