Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
LDAP results
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  2 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Mike Orr  
View profile  
 More options Jan 27 2010, 5:39 pm
From: Mike Orr <sluggos...@gmail.com>
Date: Wed, 27 Jan 2010 14:39:35 -0800
Local: Wed, Jan 27 2010 5:39 pm
Subject: [Repoze-dev] LDAP results
I took the plunge this week and installed Repoze.who/what and made a
Pylons site using htpasswd and LDAP. It's all working but I'm
surprised a bit at the LDAP behavior compared to the homegrown
authenticator I've been using, and wondering if I'll need to write my
own adapter to get the behavior I want.

I'm using LDAPAuthenticatorPlugin and LDAPAttributesPlugin, with a
custom connection:

===
def ldap_connection_factory():
    ldap_url = "ldaps://example.com:636"
    certs = os.path.join(config["here"], "myapp", "lib", "certs.pem")
    ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, certs)
    server = ldap.initialize(ldap_url, trace_level=2)
    server.protocol = ldap.VERSION3
    return server
LDAPAuthenticatorPlugin(
        ldap_connection_factory(), "ou=People,o=example.com")
LDAPAttributesPlugin(
        ldap_connection_factory())
===

For comparision, here's my existing homegrown code which should be
self-explanatory:

===
def authenticate_ldap(username, password):
    """Authenticate a user via LDAP and return his/her LDAP properties.

    Raises AuthenticationError if the credentials are rejected, or
    EnvironmentError if the LDAP server can't be reached.
    """
    import ldap
    if "," in username:
        raise UsernameError("invalid character in username: ,")
    uid = chop_at(username, "@example.com")
    dn = "uid=%s,ou=People,o=example.com" % uid
    log.debug("Authenticating %r at %s", dn, LDAP_SERVER)
    try:
        ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,
            config["ldap.server_certificates"])
        server = ldap.initialize(LDAP_SERVER)
        server.protocol = ldap.VERSION3
        server.simple_bind_s(dn, password)
        properties = server.search_s(dn, ldap.SCOPE_SUBTREE)
        if not properties:
            raise ldap.NO_SUCH_OBJECT()
    except ldap.NO_SUCH_OBJECT, e:
        log.debug("LDAP says no such user '%s' (%s)", uid, username)
        raise UsernameError()
    except ldap.INVALID_CREDENTIALS, e:
        log.debug("LDAP rejected password for user '%s' (%s)", uid, username)
        raise PasswordError()
    except ldap.SERVER_DOWN, e:
        raise EnvironmentError("can't access authentication server")
    return properties
===

With this configuration I'm getting the following:

1) The plugins expect a long-lasting connection, and don't have any
provision to reconnect if the server goes down. I know our LDAP server
goes down occasionally, and I wonder if I'd have to restart the
application in that case. My code makes a separate connection for
every login, which is the other extreme. The ideal would be for the
constructor to accept a callable that creates a connection, then reuse
the existing connection if possible, or if certain exceptions occur,
create a new connnection. But it looks like I'd have to rewrite the
plugin for that.

2) The password is put into "repoze.who.identify" after a successful
login. That seems insecure. The rest of the application doesn't need
to know what the password is. I could make a metadata provider to
delete it, but that seems like a kludge.

3) The full DSN is appearing instead of the username in
"repoze.who.credentials", "repoze.who.identity['repoze.who.userid'],
and "REMOTE_USER".  I suppose that's correct from LDAP's perspective
because a username could be ambiguous, but from my perspective the DSN
is just an internal detail of LDAP, and what I need is the username to
do authorization with or display.

4) The attributes plugin is not returning the 'ou' and 'ou1'
properties which I need for authorization.  It's returning only a
small subset of the LDAP properties. It seems to be returning the ones
accessible to anonymous users. My code does that if I don't do
.simple_bind_s as the user.  But the plugin is doing the binding, so I
don't know why the properties aren't showing up.

5) The plugin doesn't differentiate between "server down", "no such
user", and "bad password", it just returns None for all of them. This
makes it impossible to give the user a specific error message.  I
could make a plugin that puts the info "repoze.who.identity", although
I think that's supposed to be blank if the login is unsuccessful. But
I don't want to tell the user they don't exist when the real problem
is the authentication server being down, or people will think their
account disappeared.

6) Is it possible for a plugin to combine authentication and metadata
in one step? Because if it's in a database, I can get both with a
single query, or if it's in LDAP I can do one right after the other in
the same connection.

7) It seems to be rechecking the metadata on every visit after they
log in, though that could be because my test app is unsophisticated
and is not saving the metadata in the session. Although if I did do
that, I'm not sure how to tell Repoze.who that I already have the
identity and don't need it to refetch the metadata.

Anyway, I'm going to mull over what to do about these things, but I
was wondering if somebody with better Repoze knowledge might have some
ideas.

--
Mike Orr <sluggos...@gmail.com>
_______________________________________________
Repoze-dev mailing list
Repoze-...@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Gustavo Narea  
View profile  
 More options Jan 28 2010, 7:20 pm
From: Gustavo Narea <m...@gustavonarea.net>
Date: Fri, 29 Jan 2010 00:20:10 +0000
Local: Thurs, Jan 28 2010 7:20 pm
Subject: Re: [Repoze-dev] LDAP results
Hello, Mike.

Mike said:

> 1) The plugins expect a long-lasting connection, and don't have any
> provision to reconnect if the server goes down. I know our LDAP server
> goes down occasionally, and I wonder if I'd have to restart the
> application in that case. My code makes a separate connection for
> every login, which is the other extreme. The ideal would be for the
> constructor to accept a callable that creates a connection, then reuse
> the existing connection if possible, or if certain exceptions occur,
> create a new connnection. But it looks like I'd have to rewrite the
> plugin for that.

I'm afraid so :/

> 2) The password is put into "repoze.who.identify" after a successful
> login. That seems insecure. The rest of the application doesn't need
> to know what the password is. I could make a metadata provider to
> delete it, but that seems like a kludge.

That's in repoze.who itself, but I don't think that's a problem: It will be
available in the POST arguments anyway.

> 3) The full DSN is appearing instead of the username in
> "repoze.who.credentials", "repoze.who.identity['repoze.who.userid'],
> and "REMOTE_USER".  I suppose that's correct from LDAP's perspective
> because a username could be ambiguous, but from my perspective the DSN
> is just an internal detail of LDAP, and what I need is the username to
> do authorization with or display.

I agree it makes sense. Possibly the best solution would be to make that
plugin optionally return the user Id. instead of the whole DN.

> 4) The attributes plugin is not returning the 'ou' and 'ou1'
> properties which I need for authorization.  It's returning only a
> small subset of the LDAP properties. It seems to be returning the ones
> accessible to anonymous users. My code does that if I don't do
> .simple_bind_s as the user.  But the plugin is doing the binding, so I
> don't know why the properties aren't showing up.

Have you tried the `attributes' arguments?
http://code.gustavonarea.net/repoze.who.plugins.ldap/Using.html#repoz...

> 5) The plugin doesn't differentiate between "server down", "no such
> user", and "bad password", it just returns None for all of them. This
> makes it impossible to give the user a specific error message.  I
> could make a plugin that puts the info "repoze.who.identity", although
> I think that's supposed to be blank if the login is unsuccessful. But
> I don't want to tell the user they don't exist when the real problem
> is the authentication server being down, or people will think their
> account disappeared.

Good point. That plugin could use a (boolean) environment variable (e.g.,
"repoze.who.ldap.connection_error") which would be checked when the user could
not be logged in.

> 6) Is it possible for a plugin to combine authentication and metadata
> in one step? Because if it's in a database, I can get both with a
> single query, or if it's in LDAP I can do one right after the other in
> the same connection.

No, because they are two separate processes in repoze.who:
http://gustavonarea.net/uploads/Figure2.png

But in practice, that's perfectly possible if you put these attributes in
"repoze.who.identity".

> 7) It seems to be rechecking the metadata on every visit after they
> log in, though that could be because my test app is unsophisticated
> and is not saving the metadata in the session. Although if I did do
> that, I'm not sure how to tell Repoze.who that I already have the
> identity and don't need it to refetch the metadata.

You could extend that plugin and override the add_metadata() method, so when
you already have the data in the session, you put it in the `identity'
variable passed as argument; if not, you would run the parent class'
add_metadata().

HTH.

PS: Please note this plugin is in bug-fix mode, not under active development,
for the time being:
http://lists.repoze.org/pipermail/repoze-dev/2010-January/002546.html
--
Gustavo Narea <xri://=Gustavo>.
| Tech blog: =Gustavo/(+blog)/tech  ~  About me: =Gustavo/about |
_______________________________________________
Repoze-dev mailing list
Repoze-...@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »