You are not logged in Log in Join
You are here: Home » Members » msx » How to allow users to change their own password (mini howto)

Log in
Name

Password

 

How to allow users to change their own password (mini howto)

Change User Password mini howto
-------------------------------

Hi =)

Using Zope I found one problem about the security system : there is not a method to allow an user
to change _his/her own_ password only.

If you want an user to be able to manage password you usually give him a role that has the "Manage
Users" permission. Anyway, doing that you allow him/her to change EVERY password defined in the
same acl_users folder. That may be not so good.

Here is a description of a little hack I made to allow an user to change his/her own password without
giving him any permission to change other users' passwords.

This little hack is in DTML, but implementing it in Python should be a trivial matter.

First of all I made a little form to manage password input (and confirm) :

Here is the file ( I named it changePassForm )

======== changePassForm ===========

<h2>Change password for user <dtml-var expr="AUTHENTICATED_USER.getUserName()"></h2>

<form action="changePassAction" method="POST">

New Password : <input type="password" name="new_password"> <br>
Confirm Password : <input type="password" name="new_password_confirm"> <br>

<input type="submit" value="Change">

===================================

I know..the resulting form is ugly, but it's just fine for me : two "textboxs" where you can
type in password and confirm, and a button with a "Change" caption.. when you press it the
method named changePassAction is called.. that's the method :


======= changePassAction ==========


<dtml-call expr="REQUEST.set('roles',AUTHENTICATED_USER.getRoles())">
<dtml-call expr="REQUEST.set('domains',AUTHENTICATED_USER.getDomains())">
<dtml-call expr="REQUEST.set('name',AUTHENTICATED_USER.getUserName())">
<dtml-call expr="REQUEST.set('password',new_password)">
<dtml-call expr="REQUEST.set('confirm',new_password_confirm)">

<dtml-call expr="acl_users.manage_users('Change',REQUEST)">


===================================


That's the file that calls functions to set the REQUEST object properly and then use that REQUEST
object in the call to acl_users.manage_users that actually changes the password... note that we
change the password of the authenticated user who called the method.
The other entries in REQUEST (domains, roles and user name) are not changed.

I actually added some code before of the calls, just some dtml-if to check if password and confirm
are the same, to check the lenght of the new password and some boring stuff like that.. I've not
included that code here because it's not really important.

Now, the important thing is to _set a proxy role_ for changePassAction.

Proxy roles are very similar to "suid" bit in Unix programs.
When you give a script/method a "proxy role" the script will have the permission of that "proxy" role
instead of the permission of the user who called the method.

Now, it's clear: you have to give to changePassAction a role that can really Manage Users.. Manager has
this permission, but in my humble opinion defining a new role with minimal permission to run this method
properly would be a smarter idea.

And now.. the hack is done.. when the user "foo" calls the method submitting the form, the method itself
will have the permission to change his/her password, but the user itself will not have access to the acl_users
folder.

I hope this will be useful to someone: I'm new to Zope and it wasn't easy to set this stuff up properly.

I must thank everyone on #zope and #zope-it channels ( on irc.debian.org ) for they suggestion and support.

Also let me give you two advices : install ZDebug.. and ALWAYS look Zope's sources when you're stuck ;)

---- msx ----- ( Msx iS not uniX )