Mitch Pronschinske is a Senior Content Analyst at DZone. That means he writes and searches for the finest developer content in the land so that you don't have to. He often eats peanut butter and bananas, likes to make his own ringtones, enjoys card and board games, and is married to an underwear model. Mitch is a DZone Zone Leader and has posted 2573 posts at DZone. You can read more from them at their website. View Full User Profile

AEoid: An OpenID Library for GAE

12.21.2009
| 9934 views |
  • submit to reddit
The Google App Engine team just released the AEoid library for fast and easy user authentication handling with OpenID.  AEoid is currently in its "first look" alpha phase with more features on the way.  In order for users to get started quickly, AEoid focuses on "convention over configuration."  You don't need to have any experience with OpenID in order to get started.

The GAE team made AEoid's interface very similar to the App Engine Users API so users could leverage a familiar environment:

from aeoid import users

class TestData(db.Model):
user = users.UserProperty()

class TestHandler(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
if not user:
self.redirect(users.create_login_url(self.request.url))
return
logging.warn("Logged in as %s (%s)", user.nickname(), user.user_id())
data = TestData(user=user)
data.put()

There are just a few differences.  First, you have to specify an OpenID URL in order to construct a User Object.  Users are identified by their OpenID endpoint.  Since nicknames and email addresses are user-generated, they're not validated or guaranteed to be unique.  is_current_user_admin() hasn't been implemented and login: clauses in app.yaml are not affected by AEoid, but they still use the regular Users API to authenticate.

AEoid uses a single piece of WSGI middleware, which you include in your app upon installation.  With App Engine's built in webapp framework, or any other framework that calls the run_wsgi_app function, App Engine's configuration framework can be used to install AEoid. 

from aeoid import middleware

def webapp_add_wsgi_middleware(app):
app = middleware.AeoidMiddleware(app)
return app

Frameworks that don't use run_wsgi_app, will need to insert the middleware into the processing chain.

application = webapp.WSGIApplication([
# ...
], debug=True)
application = middleware.AeoidMiddleware(application)

The AEoid code uses the python-openid library for authenticating with OpenID.  The beaker sessions library is used for user session tracking.  The components of the AEoid code include request handlers, the public interface, and the middleware code.  The request handlers (login/log out pages and requests) contain most of the OpenID machinery.  Users submit their OpenID URL then the login handler redirects them back to their provider after creating an OpenID request.  After login is finished, the provider sends the user back to AEoid's completion handler, which then creates the user session and redirects them back to the application.  The public interface is just like the App Engine Users module.  User objects are wrappers around a datastore entity with the user's information.  A UserProperty stores the key to the internal User object while providing a UI identical to the UserProperty's interface.

Although AEoid should be compatible with most frameworks, it has only been tested with the webapp framework so far.  The code may have problems integrating with frameworks that include their own copy of beaker or python-openid.  The GAE team says there's a lot of room for improvement on AEoid.  If you are using AEoid with a framework other than webapp, the team wants to know about it so they can add the frameworks to the list of compatible integrations.  GAE is also looking for feature requests and bug reports.  They say the UI is subject to change depending on user feedback.  Users can't configure the OpenID library right now, but the GAE team says this will likely change in the near future.