File Coverage

blib/lib/Catalyst/Authentication/Store/LDAP.pm
Criterion Covered Total %
statement 9 11 81.8
branch n/a
condition n/a
subroutine 3 4 75.0
pod 1 1 100.0
total 13 16 81.2


line stmt bran cond sub pod time code
1             package Catalyst::Authentication::Store::LDAP;
2              
3 1     1   1426705 use strict;
  1         2  
  1         38  
4 1     1   4 use warnings;
  1         1  
  1         44  
5              
6             our $VERSION = '1.015';
7              
8 1     1   416 use Catalyst::Authentication::Store::LDAP::Backend;
  1         2  
  1         11  
9              
10             sub new {
11 0     0 1   my ( $class, $config, $app ) = @_;
12 0           return Catalyst::Authentication::Store::LDAP::Backend->new(
13             $config);
14             }
15              
16             1;
17              
18             __END__
19              
20             =pod
21              
22             =head1 NAME
23              
24             Catalyst::Authentication::Store::LDAP
25             - Authentication from an LDAP Directory.
26              
27             =head1 SYNOPSIS
28              
29             use Catalyst qw(
30             Authentication
31             );
32              
33             __PACKAGE__->config(
34             'authentication' => {
35             default_realm => "ldap",
36             realms => {
37             ldap => {
38             credential => {
39             class => "Password",
40             password_field => "password",
41             password_type => "self_check",
42             },
43             store => {
44             binddn => "anonymous",
45             bindpw => "dontcarehow",
46             class => "LDAP",
47             ldap_server => "ldap.yourcompany.com",
48             ldap_server_options => { timeout => 30 },
49             role_basedn => "ou=groups,ou=OxObjects,dc=yourcompany,dc=com",
50             role_field => "uid",
51             role_filter => "(&(objectClass=posixGroup)(memberUid=%s))",
52             role_scope => "one",
53             role_search_options => { deref => "always" },
54             role_value => "dn",
55             role_search_as_user => 0,
56             start_tls => 1,
57             start_tls_options => { verify => "none" },
58             entry_class => "MyApp::LDAP::Entry",
59             use_roles => 1,
60             user_basedn => "ou=people,dc=yourcompany,dc=com",
61             user_field => "uid",
62             user_filter => "(&(objectClass=posixAccount)(uid=%s))",
63             user_scope => "one", # or "sub" for Active Directory
64             user_search_options => { deref => "always" },
65             user_results_filter => sub { return shift->pop_entry },
66             },
67             },
68             },
69             },
70             );
71              
72             sub login : Global {
73             my ( $self, $c ) = @_;
74              
75             $c->authenticate({
76             id => $c->req->param("login"),
77             password => $c->req->param("password")
78             });
79             $c->res->body("Welcome " . $c->user->username . "!");
80             }
81              
82             =head1 DESCRIPTION
83              
84             This plugin implements the L<Catalyst::Authentication> v.10 API. Read that documentation first if
85             you are upgrading from a previous version of this plugin.
86              
87             This plugin uses C<Net::LDAP> to let your application authenticate against
88             an LDAP directory. It has a pretty high degree of flexibility, given the
89             wide variation of LDAP directories and schemas from one system to another.
90              
91             It authenticates users in two steps:
92              
93             1) A search of the directory is performed, looking for a user object that
94             matches the username you pass. This is done with the bind credentials
95             supplied in the "binddn" and "bindpw" configuration options.
96              
97             2) If that object is found, we then re-bind to the directory as that object.
98             Assuming this is successful, the user is Authenticated.
99              
100             =head1 CONFIGURATION OPTIONS
101              
102             =head2 Configuring with YAML
103              
104             Set Configuration to be loaded via Config.yml in YourApp.pm
105              
106             use YAML qw(LoadFile);
107             use Path::Class 'file';
108              
109             __PACKAGE__->config(
110             LoadFile(
111             file(__PACKAGE__->config->{home}, 'Config.yml')
112             )
113             );
114              
115             Settings in Config.yml (adapt these to whatever configuration format you use):
116              
117             # Config for Store::LDAP
118             authentication:
119             default_realm: ldap
120             realms:
121             ldap:
122             credential:
123             class: Password
124             password_field: password
125             password_type: self_check
126             store:
127             class: LDAP
128             ldap_server: ldap.yourcompany.com
129             ldap_server_options:
130             timeout: 30
131             binddn: anonymous
132             bindpw: dontcarehow
133             start_tls: 1
134             start_tls_options:
135             verify: none
136             user_basedn: ou=people,dc=yourcompany,dc=com
137             user_filter: (&(objectClass=posixAccount)(uid=%s))
138             user_scope: one
139             user_field: uid
140             user_search_options:
141             deref: always
142             use_roles: 1
143             role_basedn: ou=groups,ou=OxObjects,dc=yourcompany,dc=com
144             role_filter: (&(objectClass=posixGroup)(memberUid=%s))
145             role_scope: one
146             role_field: uid
147             role_value: dn
148             role_search_options:
149             deref: always
150              
151              
152             B<NOTE:> The settings above reflect the default values for OpenLDAP. If you
153             are using Active Directory instead, Matija Grabnar suggests that the following
154             tweeks to the example configuration will work:
155              
156             user_basedn: ou=Domain Users,ou=Accounts,dc=mycompany,dc=com
157             user_field: samaccountname
158             user_filter: (sAMAccountName=%s)
159             user_scope: sub
160              
161             He also notes: "I found the case in the value of user_field to be significant:
162             it didn't seem to work when I had the mixed case value there."
163              
164             =head2 ldap_server
165              
166             This should be the hostname of your LDAP server.
167              
168             =head2 ldap_server_options
169              
170             This should be a hashref containing options to pass to L<Net::LDAP>->new().
171             See L<Net::LDAP> for the full list.
172              
173             =head2 binddn
174              
175             This should be the DN of the object you wish to bind to the directory as
176             during the first phase of authentication. (The user lookup phase)
177              
178             If you supply the value "anonymous" to this option, we will bind anonymously
179             to the directory. This is the default.
180              
181             =head2 bindpw
182              
183             This is the password for the initial bind.
184              
185             =head2 start_tls
186              
187             If this is set to 1, we will convert the LDAP connection to use SSL.
188              
189             =head2 start_tls_options
190              
191             This is a hashref, which contains the arguments to the L<Net::LDAP> start_tls
192             method. See L<Net::LDAP> for the complete list of options.
193              
194             =head2 user_basedn
195              
196             This is the basedn for the initial user lookup. Usually points to the
197             top of your "users" branch; ie "ou=people,dc=yourcompany,dc=com".
198              
199             =head2 user_filter
200              
201             This is the LDAP Search filter used during user lookup. The special string
202             '%s' will be replaced with the username you pass to $c->login. By default
203             it is set to '(uid=%s)'. Other possibly useful filters:
204              
205             (&(objectClass=posixAccount)(uid=%s))
206             (&(objectClass=User)(cn=%s))
207              
208             =head2 user_scope
209              
210             This specifies the scope of the search for the initial user lookup. Valid
211             values are "base", "one", and "sub". Defaults to "sub".
212              
213             =head2 user_field
214              
215             This is the attribute of the returned LDAP object we will use for their
216             "username". This defaults to "uid". If you had user_filter set to:
217              
218             (&(objectClass=User)(cn=%s))
219              
220             You would probably set this to "cn". You can also set it to an array,
221             to allow more than one login field. The first field will be returned
222             as identifier for the user.
223              
224             =head2 user_search_options
225              
226             This takes a hashref. It will append it's values to the call to
227             L<Net::LDAP>'s "search" method during the initial user lookup. See
228             L<Net::LDAP> for valid options.
229              
230             Be careful not to specify:
231              
232             filter
233             scope
234             base
235              
236             As they are already taken care of by other configuration options.
237              
238             =head2 user_results_filter
239              
240             This is a Perl CODE ref that can be used to filter out multiple results
241             from your LDAP query. In theory, your LDAP query should only return one result
242             and find_user() will throw an exception if it encounters more than one result.
243             However, if you have, for whatever reason, a legitimate reason for returning
244             multiple search results from your LDAP query, use C<user_results_filter> to filter
245             out the LDAP entries you do not want considered. Your CODE ref should expect
246             a single argument, a Net::LDAP::Search object, and it should return exactly one
247             value, a Net::LDAP::Entry object.
248              
249             Example:
250              
251             user_results_filter => sub {
252             my $search_obj = shift;
253             foreach my $entry ($search_obj->entries) {
254             return $entry if my_match_logic( $entry );
255             }
256             return undef; # i.e., no match
257             }
258            
259             =head2 use_roles
260              
261             Whether or not to enable role lookups. It defaults to true; set it to 0 if
262             you want to always avoid role lookups.
263              
264             =head2 role_basedn
265              
266             This should be the basedn where the LDAP Objects representing your roles are.
267              
268             =head2 role_filter
269              
270             This should be the LDAP Search filter to use during the role lookup. It
271             defaults to '(memberUid=%s)'. The %s in this filter is replaced with the value
272             of the "role_value" configuration option.
273              
274             So, if you had a role_value of "cn", then this would be populated with the cn
275             of the User's LDAP object. The special case is a role_value of "dn", which
276             will be replaced with the User's DN.
277              
278             =head2 role_scope
279              
280             This specifies the scope of the search for the user's role lookup. Valid
281             values are "base", "one", and "sub". Defaults to "sub".
282              
283             =head2 role_field
284              
285             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".
286              
287             =head2 role_value
288              
289             This is the attribute of the User object we want to use in our role_filter.
290             If this is set to "dn", we will use the User Objects DN.
291              
292             =head2 role_search_options
293              
294             This takes a hashref. It will append it's values to the call to
295             L<Net::LDAP>'s "search" method during the user's role lookup. See
296             L<Net::LDAP> for valid options.
297              
298             Be careful not to specify:
299              
300             filter
301             scope
302             base
303              
304             As they are already taken care of by other configuration options.
305              
306             =head2 role_search_as_user
307              
308             By default this setting is false, and the role search will be performed
309             by binding to the directory with the details in the I<binddn> and I<bindpw>
310             fields. If this is set to false, then the role search will instead be
311             performed when bound as the user you authenticated as.
312              
313             =head2 entry_class
314              
315             The name of the class of LDAP entries returned. This class should
316             exist and is expected to be a subclass of Net::LDAP::Entry
317              
318             =head2 user_class
319              
320             The name of the class of user object returned. By default, this is
321             L<Catalyst::Authentication::Store::LDAP::User>.
322              
323             =head1 METHODS
324              
325             =head2 new
326              
327             This method will populate
328             L<Catalyst::Plugin::Authentication/default_auth_store> with this object.
329              
330             =head1 AUTHORS
331              
332             Adam Jacob <holoway@cpan.org>
333              
334             Some parts stolen shamelessly and entirely from
335             L<Catalyst::Plugin::Authentication::Store::Htpasswd>.
336              
337             Currently maintained by Peter Karman <karman@cpan.org>.
338              
339             =head1 THANKS
340              
341             To nothingmuch, ghenry, castaway and the rest of #catalyst for the help. :)
342              
343             =head1 SEE ALSO
344              
345             L<Catalyst::Authentication::Store::LDAP>,
346             L<Catalyst::Authentication::Store::LDAP::User>,
347             L<Catalyst::Authentication::Store::LDAP::Backend>,
348             L<Catalyst::Plugin::Authentication>,
349             L<Net::LDAP>
350              
351             =head1 COPYRIGHT & LICENSE
352              
353             Copyright (c) 2005 the aforementioned authors. All rights
354             reserved. This program is free software; you can redistribute
355             it and/or modify it under the same terms as Perl itself.
356              
357             =cut
358              
359