Prosthetic Conscience
Jason McBrayer's weblog; occasional personal notes and commentary
Mon, 05 Dec 2005
Django alternate auth HOWTO
One of the most frequently-asked questions about Django is “How do I change the authentication system to (hook into my existing authentication system / use something other than the django database). In my first couple of posts in this section, I gave one answer. The method I gave works, and it has the advantage of working on a per-app basis (if that is what you need). However, it was also written before the Django authentication documentation was written. The method I posted uses anonymous sessions (from Django’s perspective) and does not really use the Django authentication framework. Most people will probably want to use as much of the Django authentication framework, however. As I’ve now figured it out (I’m sure I’m not the first, but I’ve never seen it comprehensively documented anywhere), I’m posting how to do this. Let me emphasize that I am not at all an expert on Django internals; I’m just posting my experiences and am open to correction on any points.
First, make an app to hold the new user model and (optionally) views for logging in and out.
In the model, you are going to be over-riding the standard django.models.auth.users model with one that subclasses it. So here is what you need.
from django.core import meta
from django.models import auth
# Create your models here.
class User(auth.User):
location = meta.CharField(maxlength=100, blank=True)
favourite_cheese = meta.CharField(maxlength=30, blank=True)
class META:
admin = meta.Admin(
fields = (
(None, {'fields': ('username', )}),
('Personal info', {'fields': ('first_name',
'last_name', 'email')}),
('Extra info', {'fields': ('location', “favourite_cheese”,)}),
('Permissions', {'fields': ('is_staff', 'is_active',
'is_superuser', 'user_permissions')}),
('Important dates', {'fields': ('last_login',
'date_joined')}),
('Groups', {'fields': ('groups',)}),
),
list_display = ('username', 'email', 'first_name',
'last_name', 'is_staff'),
list_filter = ('is_staff', 'is_superuser'),
search_fields = ('username', 'first_name', 'last_name',
'email'),
remove_fields = ('password_md5',)
)
replaces_module = 'auth.users'
def check_password(self, raw_password):
'''Override the auth framework's password checking '''
# Insert code for checking (e.g) ldap password here
if external_password_check(self.username, raw_password):
return True
else:
return False
def set_password(self, raw_password):
'''Override the auth framework's password setting '''
# Insert code for setting password.
external_password_set(self.username, raw_password)
return True
# end
This model does not have to be installed using “django-admin.py install fancyauth”, and indeed, doing so will fail. What you need to do, instead, is modify the auth_users table in your project’s database to add any fields you have added. In the above model, that is ‘location’ and ‘favourite_cheese’.
The convenience function create_user(username, email, password) is also broken by this change. Writing a replacement is left as an exercise to the reader (if needed; I don't find it all that useful). You will also need to set/change passwords either through a python interactive session, or through a custom view – it can't be changed in the admin system, though you can create users there.
This is basically the minimum you could do to use custom authentication with the Django authentication framework. Other things you might want to do:
Make the User model function as a cache of external user information (e.g., fill out fields from GECOS data in LDAP or Unix password file).
Login view automatically creates a user record if needed before checking password.
Make everything completely transparent with regard to Django authentication API and admin framework.
One final note: this authentication system is project-wide. If you have an app that has significantly different authentication needs from the rest of your site, you will need either to give it its own authentication framework, or (more likely) write your views in such a way that just being authenticated doesn’t imply much about what a user is authorized to do.
[ Posted: 13:25] | [ Category: ] | Permalink | Comments: 3 ]
Powered by PyBlosxom
Subscribe