Subscribe

Appirio RSS Feed
Subscribe with Bloglines

Add to Google
Subscribe in NewsGator Online

Community

Appirio Technology Blog

Showing posts with label Appengine. Show all posts
Showing posts with label Appengine. Show all posts

Thursday, October 16, 2008

Google Apps Auth Backend for Django

Tim Garthwaite

Google loves Python. In fact, Google's original web spider, which crawls the web to create its search index was written while Larry Page and Sergey Brin (the founders) were still graduate students at Stanford, and rumors abound that it went live written completely in Python. I learned in university that most of the Python code performed well enough that much of the code was still Python to that day (circa 2000), although much of it was highly optimized in platform-specific C. Moreover, Google's new Platform-as-a-Service (PaaS), AppEngine, which allows anyone in the world to host complete web applications "in the cloud" for free (heavy use will be charged at far below-market rates), currently supports only one language (you guessed it: Python). While Google has assured that they will release AppEngine SDKs for other languages, only Python is currently supported.

AppEngine, it can be argued, may not be ready for prime-time commercial or enterprise use, as it does not support SSL for all communication between the browser and servers. Authentication can be done safely by redirecting to a secure login page and returning with a token, but the token (and all your corporate data) would then be passed back and forth in plaintext from then on. Google has promised to add SSL support to AppEngine, but until they do, Appirio's Google Practice has begun recommending the full Django platform (on Apache or, heavens forbid, IIS) for internally developed applications, in anticipation that converting these web applications to AppEngine would be relatively painless.

The AppEngine Python SDK comes with much of the Django framework pre-installed, including its fantastic templating system. Also, the Object-Relational Mapping (ORM) system built into AppEngine is remarkably similar to the ORM that comes with Django, and the AppEngine authentication system is markably similar to its Django equivalent as well. These facts should make conversion from custom in-house Django applications to AppEngine in the future (and throwing out your pesky web servers, gaining the best features of the world's most robustly distributed compute in the world, in the process) relatively painless.

So let's say you wish to go ahead with creating Python/Django web applications in-house. Django comes with an authentication framework that allows for custom back-ends, meaning that you can test username/password combinations against an arbitrary back-end system, such as Active Directory or any other LDAP system, or even against users stored in a custom database. For one of Appirio's clients who is fully embracing the cloud, including Google Mail, Calendar, and Docs corporate-wide, it made the most sense for a certain application to authenticate against Google Apps itself using Google's Apps Provisioning API. Here's how I accomplished this.

First, you must create the back-end Python class. For example purposes, I have created a 'mymodule' directory (anywhere in my Python path) containing an empty __init__.py file (telling Python to treat this directory as a module) and the file django_backend.py. Of course, you must replace "mydomain.com" with your own domain, and as your Python code base grows, you should adhere to a more logical standard for where you place your libraries. It would make sense to think about this and begin now so you won't have to refactor your code. In my system, the class file is in the 'appirio.google' module. Here are the contents of this file:

from django.contrib.auth.models include User, check_password
from gdata.apps.service include AppsService
from gdata.docs.service include DocsService
DOMAIN = 'mydomain.com'
ADMIN_USERNAME = 'admin_user'
ADMIN_PASSWORD = 'p@s$w3rd'
class GoogleAppsBackend:
""" Authenticate against Google Apps """
def authenticate(self, username=None, password=None):
user = None
email = '%s@%s' % (username, DOMAIN)
admin_email = '%s@%s' % (ADMIN_USERNAME, DOMAIN)
try:
# Check user's password
gdocs = gdata.docs.service.DocsService()
gdocs.email = email
gdocs.password = password
gdocs.ProgrammaticLogin()
# Get the user object
gapps = AppsService(domain=DOMAIN)
gapps.ClientLogin(username=admin_email,
password=admin_password,
account_type='HOSTED', service='apps')
guser = gapps.RetreiveUser(username)
user = User.objects.get_or_create(username=username)
user.email = email
user.last_name = guser.name.family_name
user.first_name = guser.name.given_name
user.is_active = not guser.login.suspended == 'true'
user.is_superuser = guser.login.admin == 'true'
user.is_staff = user.is_superuser
user.save()
except:
pass

return user

def get_user(self, user_id):

user = None

try:

user = User.objects.get(pk=user_id)

except:

pass

return user

Let's briefly review this code. authenticate() uses the GData Python library to ensure the username and password match with the actual Google Apps account. Since you need an administrator account to use the Provisioning API, I chose an arbitrary user-accessible API (Google Docs) to verify the user's password. If the password doesn't match, an exception is thrown, None is returned, and the login fails. If it does match, we log in to the Provisioning API with admin credentials to get the Google Apps user object, guser. Then, using a built-in helper method, we attempt to get the Django User object with matching username, or create a new one. Either way, we take the opportunity to update the User object with data from Apps. get_user() is a required function (as we are creating a class to meet a "duck-type" interface, rather than inheritance). We simply return a Django User, if one exists, or None.

Finally, to enable this back-end, you must modify the site's settings.py file, ensuring 'django.contrib.auth' is included in INSTALLED_APPS, and adding 'mymodule.django_backend.GoogleAppsBackend' to AUTHENTICATION_BACKENDS. You can now test logging into your site as Google Apps users. If you have enabled 'django.contrib.admin', you can then login to your site's admin console and see that these users were automatically added into your Django auth system. You could also easily create a web page to list these users by passing 'users': User.objects.all() into a template and writing template code such as:

<ul>{%foreach user in users%}<li>{{user.email}}</li>{%endfor%}</ul>

We hope you find this code useful. Feel free to use any or all of it in your own Django web applications. If you do, please let us know in the comments!

Wednesday, July 16, 2008

Welcome to the Appirio Tech Blog

The team here at Appirio spends a lot of time building innovative plugins, apps and even complete business solutions using Software-as-a-Service (SaaS) and Platform-as-a-Service (PaaS) technologies from Google and salesforce.com. We like how easy it is to build these solutions-- that's what makes cloud computing so different (and so disruptive). But easy isn't automatic (no matter what your boss thinks). That's why we're writing this blog.

Internally, the Appirio team talks a lot about design patterns, issues, work arounds and cool tricks to make it build on use web platforms. It fun to find a new way to solve a problem and a badge of honor to see who can do it with the "least lines of code".

We want you to be a part of our conversation. Why? So that you get as excited as we are about the power of cloud computing and can build your own cool applications. This blog is for you if want to build on the cloud, whether you are a power-admin or an apex wizard, whether you are a longtime Salesforce and Google customer or just getting started, whether you are an individual contributor or are managing an entire team of developers. We won't have code in every post, but we'll definitely be thinking about it.

Here are a few of the topics we're thinking about, feel free to suggest your own.
  • Salesforce's VisualForce allows developers to design any UI on top of the Salesforce data model. What's possible with VisualForce today, and how can you make the most it?
  • Salesforce's Apex programming language gives you a lot of flexibility and power, but using it effectively requires understanding its capabilities and limitations. Where can you find tips and tricks for developing in Apex?
  • Salesforce's Customer and Partner portal lets you share critical business data information with people outside your company. How can you develop effective portal applications?
  • Google's AppEngine lets you build the next great web app, but is still lacking basic features for enterprise use (e.g., support for HTTPS). Where does AppEngine fit for enterprises and how can you use it with that in mind?
  • Everyone wants to use their on-demand applications from mobile devices like the BlackBerry and iPhone. What's the best way to enable these capabilities and finally unchain your users from their desks (e.g. super monkey ball for the enterprise)?
  • Security is top-of-mind for any company looking to move more of their business onto the cloud. What shoudl you know when configuring roles and profiles, establishing authentication and authorization, and setting up single-sign on?
As you can tell, there's a lot of ground to cover. We'll have folks from Appirio and occassionally some guest writers help us get there.