To create a lower entry barrier to logging into our intranet I created a very simple backend using Google Apps Premium provisioning API (http://code.google.com/apis/apps/gdata_provisioning_api_v2.0_reference.html).
This enables controlling access for your users based on their status in your Google Apps instance. (NOTE! Since the provisioning API is only available in the Premium version of Google Apps you first need to upgrade if you haven't done so already)
Requirements: You need Google Data libraries for python. They can be downloaded from http://code.google.com/p/gdata-python-client/downloads/list Google Apps Premium -- User used by the script must have admin rights
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #!/usr/bin/python
# -*- coding: utf-8 -*-
from django.contrib.auth.backends import ModelBackend as DefaultModelBackend
from django.contrib.auth.models import User
from gdata.apps.service import AppsService
from gdata.service import BadAuthentication, CaptchaRequired
from django.conf import settings
"""
add to settings.py
# Google Apps specific for module auth
# The user needs Adminitrative rights to your domain to be able to do the sync
GOOGLE_APPS_ADMIN_EMAIL = 'login@yourdomain.com'
GOOGLE_APPS_DOMAIN = 'yourdomain.com'
GOOGLE_APPS_ADMIN_SECRET = 'yourpassworld'
# Replace the path to where you put the file
AUTHENTICATION_BACKENDS = ('path.to.backends.GoogleAppsModelBackend',)
"""
class GoogleAppsModelBackend(DefaultModelBackend):
"""
Using Google Apps Provisioning API to authenticate and create users.
"""
def authenticate(self, username=None, password=None):
# Using correct username or password here does not matter since we're using ClientLogin further down
service = AppsService(email=settings.GOOGLE_APPS_ADMIN_EMAIL, domain=settings.GOOGLE_APPS_DOMAIN, password=settings.GOOGLE_APPS_ADMIN_SECRET)
check_local_password = False
try:
service.ClientLogin(username, password)
except BadAuthentication: # If username is within domain but fails because of username or password
return None
except CaptchaRequired:
# Google asks for captcha if the email is outside your domain. This can be used to create 'local'
# administrator accounts, wallmounted statistics accounts etc.
check_local = True
try:
user = User.objects.get(username=username)
if check_local and not user.check_password(password):
# Not in google and not local. Go away!
return None
except User.DoesNotExist:
if not check_local:
user = User.objects.create_user(username=username,email=username)
user.save()
else:
return None
if not check_local:
# Here we need to us a super user
service = AppsService(email=settings.GOOGLE_APPS_ADMIN_EMAIL, domain=settings.GOOGLE_APPS_DOMAIN, password=settings.GOOGLE_APPS_ADMIN_SECRET)
service.ProgrammaticLogin()
# When a user logs in is a good idea to sync if the user is actually still allowed in the domain
guser = service.RetrieveUser(username.replace('@%s' % settings.GOOGLE_APPS_DOMAIN,''))
if not self.google_apps_sync(guser, user): return None
return user
def google_apps_sync(self, guser, user):
# Sync with google apps
# We assume that username and email does not change
user.first_name = guser.name.given_name
user.last_name = guser.name.family_name
user.is_superuser = guser.login.admin == 'true'
user.is_active = guser.login.suspended == 'false'
user.save()
return user.is_active
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 3 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 4 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 8 months ago
Comments
If the user defined in settings.GOOGLE_APPS_ADMIN_EMAIL does not have admin rights you'll get an gdata.apps.service.AppsForYourDomainException
#
Please login first before commenting.