Improve persist_in_session POD formatting
[catagits/Catalyst-Authentication-Store-LDAP.git] / lib / Catalyst / Authentication / Store / LDAP.pm
1 package Catalyst::Authentication::Store::LDAP;
2
3 use strict;
4 use warnings;
5
6 our $VERSION = '1.015';
7
8 use Catalyst::Authentication::Store::LDAP::Backend;
9
10 sub new {
11     my ( $class, $config, $app ) = @_;
12     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 it's 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 it's 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> / 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