[Zope-dev] REQUEST.AUTHENTICATED_USER question

vio vmilitaru@sympatico.ca
Wed, 23 Jan 2002 21:52:40 -0500


First, thanks for your time on this thread, everybody!

* Leonardo Rochael Almeida <leo@hiper.com.br> [020123 19:42]:
> Hi Vio,
> 
> By the contents of your message, you seem to be a little off track
> w.r.t. the way authentication works between the browser and Zope.
> 
> By now you seem to have discovered that the browser sends the user
> credentials whenever it fetches a page. If you aren't using a custom
> user folder that uses cookies, then you're most likely using basic
> authentication (which is likely since you don't want the overhead of a
> product). To know for sure answer this question: when you are anonymous
> and you want to access a forbiden area, does the
> browser-standard-login-popup-window shows up?

yes.

> 
> If yes, then there simply is no way you can use "a few placed calls to
> the Zope machinery" to convince the browser that it needs to switch
> identities because you're talking to Zope, not to the browser. Zope
> cannot tell the browser "stop pretending you are anonymous and start
> pretending you're John". The only thing Zope can tell the browser is
> "This user you are using is not authorized", in which case the browser
> will ask the user for another login/password combo, using it's own
> standard login popup window.

Ok, maybe I didn't express myself very clearly in my past messages.
Imagine the following simple scenario, which makes heavy use of 
'CoreSessionTracking', by the way:

1. In my 'standard_html_header' I put a dtml routine who checks for a 
specific session variable, let's call it 'user_id'. If it isn't there, or
there is no session running, it redirects user to my custom 'loginForm'.
	<dtml-if "sessionData.get('user_id')">
		get the beef
	<dtml-else>
		redirect to loginForm

2. The manage_login() who processes the 'loginForm' data, validates user 
credentials against some internal list. Actually, for now I'm using a
standard Users_folder object, but I am tempted to swich to something even
simpler, like a dictionary or a list. I hope you follow me up to now.

In that list, each user_id has also associated with it a list of roles. 
So here we have a central list of 'authorised' users (or a UsersFolder):
	clean_users.append([user_id, password, list_of_roles])
	or
	Users_folder._addUser(name,password,confirm,roles,domains)

Session-storing the credentials: manage_login() stores this related data
as session variables:
	sessionData.set('user_id',user_id)
	sessionData.set('user_roles', list_of_roles)

3. Make all user-visible objects in my product 'Public', knowing that 
they are not 'really' public: any user without a 'user_id' session variable 
will get redirected to my custom login page 'no matter what'. But Zope's
own security machinery is out of the loop on this one (simply by-passed).

4. The little routine in 'standard_html_header' will take care of all dtml.
But I will need to call a similar validating method (or specialized instance)
before running any 'executable' code: 
by 'executable' I mean code who Creates, Destroys, Modifies restricted objects, 
or modifies my custom security settings. This code simply compares content of
'user_roles' session variable with 'my_object_permissions' object attribute
(which can be acquired).

Only if there's a match, the 'executable' python code is allowed to run. 
An alternative here would have been to protect all objects with a 
Zope permission (instead of declaring everything public), 
then switch to a user with that permission for the duration of this 
transaction with:
SecurityManagement.newSecurityManager(None, UserWithPermission)

This is what I ment with "a few well placed calls to the Zope machinery".
Of course I know I'm not talking to the browser, which is but a dumb client
with cookies (and no milk). So it's not the browser who tells Zope "I'm
doctor Zoidberg", but my own code (which acts like a proxy).

In my view, this scenario implements Zope's security core 'principles' of 
'Roles' matching 'Permissions', but using CoreSessionTracking. Writing this
isn't as complicated as it sounds, only cumbersome to paste code into 
existing python classes, and edit many dtml pages to add a 'myPermissions' 
input field to all objects (or at least to the top objects in my hierarchy, 
and let those custom permissions get acquired from lower down). 
A full evening's work, for sure. (I think all hackers are optimists by nature)

My alternative being to study and understand an existing cookie-based
user-folder product, and make it play nice with my own code. Having tried the
latter for the last week without satisfactory results (again, only my fault if
I don't understand totally how things work), I must admit that giving a shot 
at the former scenario sounds quite tempting. Let's see ...

But many thanks for all your help and suggestion, which has been very 
appreciated and useful. If you smell something rotten in my stuff here, 
please do let me know (besides the fact that I am trying to re-invent 
the wheel, of course).
Cheers,
Vio


> 
> On the other hand, if you are using a user-folder product (such as
> exUserFolder or LoginManager) and it is configured for cookie login,
> THEN you might be able to change the user "persistently" by changing the
> cookie. Note, however, that in most cases the cookie contains either a
> valid user/password combo or a key to a hash table that has the
> user/password combo. So, in order to tell the browser to pretend to be
> someone else, you'll probably have to provide the password that goes
> with the user, which will be impossible if the passwords are stored
> encrypted. In all cases, it will require knowledge of the format of the
> cookie that is exclusive to each user-folder and might change in the
> next version of the user-folder product.
> 
> As I said, there is no way that "a few placed calls to the Zope
> machinery" will get what you want, but this is because it is Web, not
> because it is Zope.
> 
> Your best bet is still trying to modify an existing, cookie-using,
> user-folder product, so that you can extend it to have calls that will
> give you the cookie that you should put in the browser to change the
> user identity. It's simply TOO HARD to not get involved with
> user-folders if what you're trying to do deals with user authentication.
> 
> Cheers, Leo
> 
> PS: I.M.B.O. (B. as in biased), exUserFolder is the most maleable of
> them all and the easiest to understand, but it is hard to understand ANY
> user-folder product if you don't understand Web protocols and/or Zope
> authentication machinery.
> 
> On Wed, 2002-01-23 at 19:28, vio wrote:
> > 
> > [...] all I am looking 
> > for is for the few Zope incantations to 'switch' user identities, 
> > and I can take care of the rest. Now I found how to make this switch, using
> > AccessControl.SecurityManagement.newSecurityManager(None, myUser)
> > only this switch doesn't 'persist'. 
> > What is my problem then: at this point, to change the data in the cookie Zope 
> > lays on the browser, so it points to the new 'switched' user. In other words,
> > make a 'persistent' switch.
> > 
> > Furthermore, I don't really need an entire product to do this. Just a few well
> > placed calls to Zope machinery seems to do the trick. 
> > Less overhead as a bonus.
> 
> -- 
> Ideas don't stay in some minds very long because they don't like
> solitary confinement.