[Twisted-Python] Passport, my ideas about an LDAP backend
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.
More information about the Twisted-Python