Skip to content

Instantly share code, notes, and snippets.

@ogier
Created April 4, 2012 18:05
Show Gist options
  • Save ogier/2304321 to your computer and use it in GitHub Desktop.
Save ogier/2304321 to your computer and use it in GitHub Desktop.
GSoC 2012: auth.User replacement

GSoC 2012: auth.User replacement

Alex Ogier
Rising Senior, Princeton University
alex.ogier@gmail.com

Technical Details

The scope of this project is to break any hard ties to the auth.User model, and allow Django developers to cleanly specify alternate models to be used instead.

The prerequisites for a successful alternate User ecosystem as I see them are:

  1. Require no changes from anyone if the current User model satisfies their needs.
  2. Explicitly opt-in to any new changes.
  3. Provide extensive documentation and a clean set of building blocks to make implementing your own model a simple, obvious task.
  4. Carefully document the contract that each Django contrib app requires from User models, and provide easy ways of satisfying those contracts.

The implementation is described as Solution 2a at https://code.djangoproject.com/wiki/ContribAuthImprovements

The rationale behind the design I have chosen is written up at https://gist.github.com/2289395, and the implementation so far is at https://github.com/ogier/django/tree/auth-mixins.

I think the basic structure has consensus on the django-dev list: Developers write their own User object that fulfills various constraints via duck-typing. There are still some technical decisions to be resolved around how such a model is accessed, whether by just one setting, USER_MODEL, or per app as ADMIN_USER_MODEL, COMMENTS_USER_MODEL, etc. There is some question as to whether models should be made replaceable via a general mechanism, or just special-cased to User model settings. Still to be decided is the precise interaction between authentication backends and User models.

These details can be part of an ongoing discussion.

Previous discussion threads were formative in shaping this proposal:

Documentation and Testing

This project, because it will offers a fundamental contract for authentication, will be successful or not largely based on how well-motivated and documented all of our decisions are. I foresee that the brunt of the project's time will be spent producing viable test cases and documentation. The technical changes required are minimal, which I consider a good thing -- there are no new metaphors to learn, just cleaner use of Django's primitives.

We should have easy tutorials that describe the best way to handle the 80% questions people ask: How can I have people be identified by email? How can I have a longer username?

I think the project will be considerably more valuable if it lands in 1.5 with not only comprehensive documentation and example material for developer-defined User models, but also if there are several reference implementations in the wild of third-party authentication mechanisms that take advantage of our changes. I think we should work with the maintainers of existing pluggable authentication providers to have a lineup of authentication options that developers can take advantage of immediately.

Most third-party auth options currently are monolithic, because without a nice pluggable interface the cost-benefit ratio of integrating with any particular auth provider is low if they only support one service or auth mechanism. I think the ecosystem will be healthier if a Twitter auth mechanism for example can say:

If you are using Django 1.5 and have your own User model, the process is simple:

Add our urls to your urlconf by importing[...]

Now add our fields to your User model. We require a twitter_auth.fields.TwitterHandle() field named twitter_handle and a twitter_auth.fields.AccessToken() field named access_token. You can either specify them manually:

from twitter_auth.fields import TwitterHandle, AccessToken
class MyUser(models.Model):
    twitter_handle = TwitterHandle()
    access_token = AccessToken()
    ...

or you can just inherit from twitter_auth.mixins.TwitterAuthMixin which provides these fields for you:

from twitter_auth.fields import TwitterAuthMixin
class MyUser(TwitterAuthMixin, mixins.PermissionsMixin, ...):
    ...

Add our authentication backend, twitter_auth.TwitterAuthBackend to your AUTHENTICATION_BACKENDS setting and you're done! You can direct people to reverse('twitter_auth:login') to begin the authentication process[...]

That seems like a really clean way for a third party to document their pluggable authentication (or for that matter, pluggable anything for Users).

Timeline

This contribution is largely a social upheaval rather than a technical one. Test cases, documentation and discussion must happen in parallel with development -- if there's one thing I've learned it's that documenting a process is one of the best ways to pick apart its weaknesses before it's too late.

Here's my conception of the ~13 weeks that GSoC is expected to consist of:

  • 3 weeks -- Core refactoring. Use cases and tests for basic identity changes, such as lengthening the email field or using the email as primary identifier. Existing authentication mechanisms (i.e. those in django.contrib) refactored as necessary to work with a custom user model.
  • 2 weeks -- Contrib dependency specification. Flesh out and define the contracts that admin and comments expect from Users. Document in detail as a model for third-party apps. Test various bare-minimum custom users that satisfy each contract.
  • 2 weeks -- Flesh out authentication backend API. Presumably the current API for authentication backends is limited by its conception as a mechanism purely for authenticating django.contrib.auth.models.User. We should evaluate whether multiple authenticated user models are possible or desirable, and this point is when we should put our foot down.
  • 3-4 weeks -- Document and prototype custom user extensions. Wrap standard python authentication libraries for testing alongside included password mechanisms (even if we don't include twitter/facebook/openid/LDAP modules distributed with Django, their existence will help motivate the project.)

Ideally at this point the code will be ready to move out of its GSoC feature branch and into trunk. Actually having people write to the specification we have for User models and try to port third-party libraries to support generic users is bound to bring up pain points.

  • 3-4 weeks -- Explore additional access mechanisms and validation. Taking cues from the issues that arise over the course of implementing the core functionality, anything that makes adoption and migration smoother is something we should seriously consider.

Anyways, that is my conception of an acceptable proposal for GSoC 2012. Please send me feedback at alex.ogier@gmail.com .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment