tags:

views:

91

answers:

5

I have a Django app where there are 2 use cases where I want a user to be able to login without a password.

  1. User registers and gets activation link in e-mail.
  2. User resets password and gets link to change password form in e-mail.

The links include a one-time-use key that I validate, and then I want to log the user in without using credentials.

# This raises an exception unless
# I call user.authenticate 1st.
auth.login(request, user)

How do I acheive this?

+1  A: 

Look at django-registration app, it's exactly what you need :)

bx2
A: 

I don't think that either of those cases should count as a "login". They should be handled as a special case, via views that don't require authentication.

Mike DeSimone
That's probably a better idea for the 2nd case I have listed, but for the 1st case I would like the user to be automatically logged in once they have clicked the activate link. I can't think of any good reason to make them enter their user name and password again after activating.
limscoder
A: 

You can write your own authentication backend(s) which handles your two use cases. See the docs on writing and using a custom auth backend: http://docs.djangoproject.com/en/1.2/topics/auth/#other-authentication-sources

EDIT: There seems there might be some misconception about how difficult it might be to write your own auth backend. From the docs:

An authentication backend is a class that implements two methods: get_user(user_id) and authenticate(**credentials).

That's right. It's any class that implements two functions both which return User objects.

The get_user method takes a user_id -- which could be a username, database ID or whatever -- and returns a User object.

...authenticate should check the credentials it gets, and it should return a User object that matches those credentials, if the credentials are valid. If they're not valid, it should return None.

The OP has already stated that the links contain one-time keys that he validates (and presumably has associated with the user he wishes to log in). In other words he's already written the business logic for the backend, he would just need to convert it into an appropirate class.

Custom authentication backends can do a number of awesome things in Django 1.2 like object level permissions but they don't have to be that complicated. Plus they stack so you can mix in your token based authentication with the default model backend or OpenID or Facebook. But in the end an auth backend is just class with two methods and I don't see how you can call that overkill.

Mark Lavin
Are you serious? This is not a case for writing your own backend! If he'd like to use ie. OpenID or authentication from other sources - that's OK, but not in this case - it would be overkill!
bx2
"The links include a one-time-use key that I validate" He's basically doing token based authentication now which is a perfect use case for your own auth backend.
Mark Lavin
I like this idea, but there doesn't seem to be a way to specify a backend when calling authenticate(). I don't want to add the token backend to settings.AUTHENTICATION_BACKEND, because the authentication waterfall is not appropriate. I only want to authenticate against the token backend. I guess I will manually instantiate the token backend, do the authentication, and then set user.backend manually as described in rekmulk's answer.
limscoder
+1  A: 

Here you have working snippet that logins user without requiring credentials.

http://djangosnippets.org/snippets/1547/

Dominik Szopa
A: 

You can use the method described here in the Django docs. You grab your user based on the one-time-use key you supplied them and call login(request, user). The catch here is that you'll need to manually specify the authentication backend because you're not calling authenticate() first.

from django.contrib.auth import login

def my_view(request):

    // your user retrieval code
    ...

    user.backend='django.contrib.auth.backends.ModelBackend'
    login(request, user)
t3k76