looking for a clean, easy way to force user to change password on first login

2,406 views
Skip to first unread message

pjv

unread,
Jul 17, 2009, 5:08:58 PM7/17/09
to Django users
i am working on a project where i need to create a number of users
(standard django User objects who will login to the site using the
vanilla django auth framework) along with random passwords (rather
than allowing the users to sign up and supply their own passwords).
after the site launches, staff will email each user their username and
the generated random password and a link to the site.

ideally, the random password would be a one-time password and when the
user logs in, they would be automatically redirected to the change
password page and required to pick a new password.

i've thought about creating a special link to put into the email that
would hit a view that redirected to the change password view rather
than the usual home page after login, but that seems a little kludgy
and also easy to get around since the user might not use the link from
the email.

i've done a fair amount of googling and struck out. i don't want to
reinvent the wheel here, or write a bunch of code if i don't have to.
anyone have any ideas or pointers to prior art?

Shawn Milochik

unread,
Jul 17, 2009, 11:35:31 PM7/17/09
to django...@googlegroups.com
This isn't ideal, but it should work (or prompt someone to propose
something better).

Add a one-to-one table for the user, with a field containing the
initial password (encrypted, of course, so it looks like the password
in the auth_user table).

When the user logs in, have the login page check to see if the
passwords match. If they do, redirect to the password change page
instead of the normal redirect page.


pjv

unread,
Jul 18, 2009, 1:24:27 PM7/18/09
to Django users
thanks for your reply, shawn. that's a good idea, and i already have a
one-to-one table inherited from User where i can stash the initial
encrypted password. the only thing i don't like about doing it this
way is that i am currently trying to use as much generic, built-in
django as i can and that means in this case that i am using the
standard django login function (i.e. (r'^accounts/login/$',
'django.contrib.auth.views.login')).

i first thought that i might be able to just write a little wrapper
around that function to implement the logic you suggested, letting the
generic function log the user in and then deciding where to redirect
based on the password comparison between User and the one-to-one
table.

but django.contrib.auth.views.login has a redirect buried right inside
it, so i don't see how i can do this without re-implementing the whole
login function in my project. that's not a big deal from a code
standpoint; just a copy-paste and adding the additional logic which is
minimal. but i was hoping to avoid replacing the generic django
functionality in areas like this where future django updates might
cause conflicts. this might not be a big deal in this case, but i am
relatively new to django and don't have a sense of where this kind of
hacking is safe and where not.

Shawn Milochik

unread,
Jul 18, 2009, 10:13:37 PM7/18/09
to django...@googlegroups.com
If I understand correctly, you can do this without having to re-
implementing the login. You will have to make a (very simple) login
template, and write a login view that contains these:

from django.contrib.auth import login
login(request, form.get_user())

Then you can handle the redirection however you like.


pjv

unread,
Jul 19, 2009, 8:21:57 AM7/19/09
to Django users
thanks again. writing that login view is what i meant by re-
implementing the login. my terminology is probably confusing. there is
a generic login view in django.contrib.auth.views that does what you
are saying, only [obviously] without the custom redirect logic that i
want. i just copied and pasted that view into my own view and modified
the 'standard' redirect logic in it to include the test for the two
passwords being the same. but replacing the generic view was what i
was originally hoping to avoid in case it gets me out of sync with
future django updates on how auth/login works.

but it's probably fine, and it is currently giving me the behavior
that i want.

Ronghui Yu

unread,
Jul 19, 2009, 10:06:10 AM7/19/09
to django...@googlegroups.com
How about writing a decorator?


pjv 写道:

Roland van Laar

unread,
Jul 26, 2009, 11:54:57 AM7/26/09
to django...@googlegroups.com
Ronghui Yu wrote:
> How about writing a decorator?
That's possible, although there is an easier way:

The best way imho is to generate a random password when you
create the user, and to send them a password reset email.
Which can be implemented using django.contrib.auth.

That way they don't have to know the random password, and
they can't login until they have set a new password.

And that way there is no need to have extra fields in the models.

Regards,

Roland van Laar
> Ronghui Yu <mailto:ston...@163.com>
>
> >

pjv

unread,
Jul 26, 2009, 7:36:15 PM7/26/09
to Django users
i thought of something along those lines. that's exactly the kind of
thing that i was originally searching for -- a way to do it without
cluttering things up and without building a bunch of unnecessary
infrastructure or hacking core django code.

unfortunately, when you do those nice reset emails, the token that
gets generated is only good for ten minutes. since we'll be triggering
the email to go out to a bunch of users, there is no way to know when
they will get the email or respond to it.

it would be really cool if there were a checkbox on the standard
django user admin page that said "Force password change on next
login".

ZhangZheng

unread,
Aug 6, 2009, 10:51:39 AM8/6/09
to django...@googlegroups.com
you can use
process_response(self,request,response)

in the process_response, you can do :
if requst.user is in the first-login table, you can redirect URL to
change-passwd page

a little suggestion,


pjv 写道:
Reply all
Reply to author
Forward
0 new messages