[Twisted-Python] Passport, my ideas about an LDAP backend

Tommi Virtanen tv at twistedmatrix.com
Mon Dec 31 11:28:52 EST 2001

Glyph Lefkowitz <glyph at twistedmatrix.com> writes:

> > Requirement #2: Passport must be able to store data in the
> > Perspective during authentication.
> > However, if the application wants to use LDAP for more than just user
> > authentication, things get a bit worse. We could just store the
> > password we saw the user enter, and later bind to the LDAP server as
> > this user. However, I dislike storing plain-text passwords in virtual
> > memory.
> I'm not sure what you're talking about here -- it sounds like you're
> using "authentication" to mean two different things.  First, what is
> *the* Perspective?  An Identity (presumably Identities are stored in
> LDAP) has multiple Perspectives.

	I'm probably all confused by Perspectives and Identities. 
	s/Perspective/Identity/. And naturally the fd shouldn't be
	persistent -- just to make sure.

	Yes, I want LDAP to be more than authentication. Consider an
	application that has users stored in the LDAP tree, in one
	subtree. It also has some user-editable data stored in (same
	or different) subtree. LDAP server ACLs allow some of the
	users access to some of the fields, etc. If you want to make a
	web frontend, you need to use LDAP as an authentication
	backend, and you need to use that authentication (to the LDAP
	server) in order to perform actions on the LDAP server.

	Think of it this way: an authentication server gives you a
	key, and when you later perform actions toward external
	services as the authenticated user, you need to provide the
	key. In this case, the key is a TCP connection. I believe
        Kerberos follows this model, with a "real" key.

> > Requirement #3: Passport must be able to ask users to
> > reauthenticate.
> > 
> > A better way is to remember that we already did bind (authenticate) to
> > the LDAP server as that user. Just reserve that connection for that
> > user alone. As long as the connection is alive, we can keep on talking
> > to the LDAP server.
> > 
> > Now, programs can be restarted, TCP connections can die, and servers
> > can utilize idle timeouts, maximum time limits, or limit maximum
> > number of operations per connection. The TCP connection can die any
> > moment. As we didn't store the user password, we need to ask it again
> > when we see the connection has closed and the user tries an operation
> > that requires talking to the LDAP server. This requires "invalidating"
> > the users previous authentication.
> OK.  So it sounds like you want any interaction with a perspective or
> identity to be able to potentially raise an exception that says "you
> need to offer credentials for this Identity again".  Frameworks (e.g.
> web.guard, pb.AuthRoot) will need to handle this sensibly.

	Well, it is possible to handle with voiding the authentication
	data. For example, with web.guard, this could mean that

        1. web.guard sees authentication is still valid, lets a request

        2. actual request causes actions that discover the LDAP connection
           has closed, give back error

        3. user sees error, clicks "submit" again, or refreshes.

        4. web.guard sees an unauthenticated user, asks for authentication

        5. user authenticates

        6. web.guard lets the resource pass by (A separate ugliness is that
           web.guard complains if it has to authenticate anything with
           forms, and destroys submitted data)

> It's a reasonable requirement, but it may be domain-specific to your
> LDAP interaction stuff.  I know that I have at least one system where
> authentication is persistent within a server once it's been accomplished
> (interaction with the authentication database stops after the user's
> been verified).

	Yes, and one time would be enough even for an LDAP server that
	is used as authentication only. The point where it isn't
	enough is achieved by creating a proxy in Twisted, where the
	proxy isn't the final service that authenticates users, but
	just acts as a smart protocol converter. Then the proxy is at
        the mercy of the final service.

	And that's what I've been doing. LDAP <-> web.

double a,b=4,c;main(){for(;++a<2e6;c-=(b=-b)/a++);printf("%f\n",c);}

More information about the Twisted-Python mailing list