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