Catalyst::Authentication::Store::LDAP - Authentication from an LDAP Directory.


    use Catalyst qw(

      'authentication' => {
         default_realm => "ldap",
         realms => {
           ldap => {
             credential => {
               class => "Password",
               password_field => "password",
               password_type => "self_check",
             store => {
               binddn              => "anonymous",
               bindpw              => "dontcarehow",
               class               => "LDAP",
               ldap_server         => "",
               ldap_server_options => { timeout => 30 },
               role_basedn         => "ou=groups,ou=OxObjects,dc=yourcompany,dc=com",
               role_field          => "uid",
               role_filter         => "(&(objectClass=posixGroup)(memberUid=%s))",
               role_scope          => "one",
               role_search_options => { deref => "always" },
               role_value          => "dn",
               role_search_as_user => 0,
               start_tls           => 1,
               start_tls_options   => { verify => "none" },
               entry_class         => "MyApp::LDAP::Entry",
               use_roles           => 1,
               user_basedn         => "ou=people,dc=yourcompany,dc=com",
               user_field          => "uid",
               user_filter         => "(&(objectClass=posixAccount)(uid=%s))",
               user_scope          => "one", # or "sub" for Active Directory
               user_search_options => {
                 deref => 'always',
                 attrs => [qw( distinguishedname name mail )],
               user_results_filter => sub { return shift->pop_entry },
               persist_in_session  => 'all',

    sub login : Global {
        my ( $self, $c ) = @_;

                          id          => $c->req->param("login"),
                          password    => $c->req->param("password")
        $c->res->body("Welcome " . $c->user->username . "!");


This plugin implements the Catalyst::Authentication v.10 API. Read that documentation first if you are upgrading from a previous version of this plugin.

This plugin uses Net::LDAP to let your application authenticate against an LDAP directory. It has a pretty high degree of flexibility, given the wide variation of LDAP directories and schemas from one system to another.

It authenticates users in two steps:

1) A search of the directory is performed, looking for a user object that matches the username you pass. This is done with the bind credentials supplied in the "binddn" and "bindpw" configuration options.

2) If that object is found, we then re-bind to the directory as that object. Assuming this is successful, the user is Authenticated.


Configuring with YAML

Set Configuration to be loaded via Config.yml in

    use YAML qw(LoadFile);
    use Path::Class 'file';

            file(__PACKAGE__->config->{home}, 'Config.yml')

Settings in Config.yml (adapt these to whatever configuration format you use):

    # Config for Store::LDAP
        default_realm: ldap
                    class: Password
                    password_field: password
                    password_type:  self_check
                    class: LDAP
                        timeout: 30
                    binddn: anonymous
                    bindpw: dontcarehow
                    start_tls: 1
                        verify: none
                    user_basedn: ou=people,dc=yourcompany,dc=com
                    user_filter: (&(objectClass=posixAccount)(uid=%s))
                    user_scope: one
                    user_field: uid
                        deref: always
                    use_roles: 1
                    role_basedn: ou=groups,ou=OxObjects,dc=yourcompany,dc=com
                    role_filter: (&(objectClass=posixGroup)(memberUid=%s))
                    role_scope: one
                    role_field: uid
                    role_value: dn
                        deref: always

NOTE: The settings above reflect the default values for OpenLDAP. If you are using Active Directory instead, Matija Grabnar suggests that the following tweeks to the example configuration will work:

    user_basedn: ou=Domain Users,ou=Accounts,dc=mycompany,dc=com
    user_field:  samaccountname
    user_filter: (sAMAccountName=%s)
    user_scope: sub

He also notes: "I found the case in the value of user_field to be significant: it didn't seem to work when I had the mixed case value there."


This should be the hostname of your LDAP server.


This should be a hashref containing options to pass to Net::LDAP->new(). See Net::LDAP for the full list.


This should be the DN of the object you wish to bind to the directory as during the first phase of authentication. (The user lookup phase)

If you supply the value "anonymous" to this option, we will bind anonymously to the directory. This is the default.


This is the password for the initial bind.


If this is set to 1, we will convert the LDAP connection to use SSL.


This is a hashref, which contains the arguments to the Net::LDAP start_tls method. See Net::LDAP for the complete list of options.


This is the basedn for the initial user lookup. Usually points to the top of your "users" branch; ie "ou=people,dc=yourcompany,dc=com".


This is the LDAP Search filter used during user lookup. The special string '%s' will be replaced with the username you pass to $c->login. By default it is set to '(uid=%s)'. Other possibly useful filters:



This specifies the scope of the search for the initial user lookup. Valid values are "base", "one", and "sub". Defaults to "sub".


This is the attribute of the returned LDAP object we will use for their "username". This defaults to "uid". If you had user_filter set to:


You would probably set this to "cn". You can also set it to an array, to allow more than one login field. The first field will be returned as identifier for the user.


This takes a hashref. It will append its values to the call to Net::LDAP's "search" method during the initial user lookup. See Net::LDAP for valid options.

Be careful not to specify:


As they are already taken care of by other configuration options.


This is a Perl CODE ref that can be used to filter out multiple results from your LDAP query. In theory, your LDAP query should only return one result and find_user() will throw an exception if it encounters more than one result. However, if you have, for whatever reason, a legitimate reason for returning multiple search results from your LDAP query, use user_results_filter to filter out the LDAP entries you do not want considered. Your CODE ref should expect a single argument, a Net::LDAP::Search object, and it should return exactly one value, a Net::LDAP::Entry object.


 user_results_filter => sub {
                          my $search_obj = shift;
                          foreach my $entry ($search_obj->entries) {
                              return $entry if my_match_logic( $entry );
                          return undef; # i.e., no match


Whether or not to enable role lookups. It defaults to true; set it to 0 if you want to always avoid role lookups.


This should be the basedn where the LDAP Objects representing your roles are.


This should be the LDAP Search filter to use during the role lookup. It defaults to '(memberUid=%s)'. The %s in this filter is replaced with the value of the "role_value" configuration option.

So, if you had a role_value of "cn", then this would be populated with the cn of the User's LDAP object. The special case is a role_value of "dn", which will be replaced with the User's DN.


This specifies the scope of the search for the user's role lookup. Valid values are "base", "one", and "sub". Defaults to "sub".


Should be set to the Attribute of the Role Object's returned during Role lookup you want to use as the "name" of the role. Defaults to "CN".


This is the attribute of the User object we want to use in our role_filter. If this is set to "dn", we will use the User Objects DN.


This takes a hashref. It will append its values to the call to Net::LDAP's "search" method during the user's role lookup. See Net::LDAP for valid options.

Be careful not to specify:


As they are already taken care of by other configuration options.


By default this setting is false, and the role search will be performed by binding to the directory with the details in the binddn and bindpw fields. If this is set to false, then the role search will instead be performed when bound as the user you authenticated as.


Can take one of the following values, defaults to username:


Only store the username in the session and lookup the user and its roles on every request. That was how the module worked until version 1.015 and is also the default for backwards compatibility.


Store the user object and its roles in the session and never look it up in the store after login.

NOTE: It's recommended to limit the user attributes fetched from LDAP using "user_search_options" / attrs to not exhaust the session store.


The name of the class of LDAP entries returned. This class should exist and is expected to be a subclass of Net::LDAP::Entry


The name of the class of user object returned. By default, this is Catalyst::Authentication::Store::LDAP::User.



This method will populate "default_auth_store" in Catalyst::Plugin::Authentication with this object.


Adam Jacob <> Peter Karman <> Alexander Hartmaier <>

Some parts stolen shamelessly and entirely from Catalyst::Plugin::Authentication::Store::Htpasswd.

Currently maintained by Dagfinn Ilmari Mannsåker <>.


To nothingmuch, ghenry, castaway and the rest of #catalyst for the help. :)


Catalyst::Authentication::Store::LDAP, Catalyst::Authentication::Store::LDAP::User, Catalyst::Authentication::Store::LDAP::Backend, Catalyst::Plugin::Authentication, Net::LDAP


Copyright (c) 2005 the aforementioned authors. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.