Version 1.010
[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.010';
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 =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",
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
160 He also notes: "I found the case in the value of user_field to be significant: 
161 it didn't seem to work when I had the mixed case value there."
162
163 =head2 ldap_server
164
165 This should be the hostname of your LDAP server.
166
167 =head2 ldap_server_options
168
169 This should be a hashref containing options to pass to L<Net::LDAP>->new().  
170 See L<Net::LDAP> for the full list.
171
172 =head2 binddn
173
174 This should be the DN of the object you wish to bind to the directory as
175 during the first phase of authentication. (The user lookup phase)
176
177 If you supply the value "anonymous" to this option, we will bind anonymously
178 to the directory.  This is the default.
179
180 =head2 bindpw
181
182 This is the password for the initial bind.
183
184 =head2 start_tls
185
186 If this is set to 1, we will convert the LDAP connection to use SSL.
187
188 =head2 start_tls_options
189
190 This is a hashref, which contains the arguments to the L<Net::LDAP> start_tls
191 method.  See L<Net::LDAP> for the complete list of options.
192
193 =head2 user_basedn
194
195 This is the basedn for the initial user lookup.  Usually points to the
196 top of your "users" branch; ie "ou=people,dc=yourcompany,dc=com".
197
198 =head2 user_filter
199
200 This is the LDAP Search filter used during user lookup.  The special string 
201 '%s' will be replaced with the username you pass to $c->login.  By default
202 it is set to '(uid=%s)'.  Other possibly useful filters:
203
204     (&(objectClass=posixAccount)(uid=%s))
205     (&(objectClass=User)(cn=%s))
206
207 =head2 user_scope
208
209 This specifies the scope of the search for the initial user lookup.  Valid
210 values are "base", "one", and "sub".  Defaults to "sub".
211
212 =head2 user_field
213
214 This is the attribute of the returned LDAP object we will use for their
215 "username".  This defaults to "uid".  If you had user_filter set to:
216
217     (&(objectClass=User)(cn=%s))
218
219 You would probably set this to "cn". You can also set it to an array,
220 to allow more than one login field. The first field will be returned
221 as identifier for the user.
222
223 =head2 user_search_options
224
225 This takes a hashref.  It will append it's values to the call to
226 L<Net::LDAP>'s "search" method during the initial user lookup.  See
227 L<Net::LDAP> for valid options.
228
229 Be careful not to specify:
230
231     filter
232     scope
233     base
234
235 As they are already taken care of by other configuration options.
236
237 =head2 user_results_filter
238
239 This is a Perl CODE ref that can be used to filter out multiple results
240 from your LDAP query. In theory, your LDAP query should only return one result
241 and find_user() will throw an exception if it encounters more than one result.
242 However, if you have, for whatever reason, a legitimate reason for returning
243 multiple search results from your LDAP query, use C<user_results_filter> to filter
244 out the LDAP entries you do not want considered. Your CODE ref should expect
245 a single argument, a Net::LDAP::Search object, and it should return exactly one
246 value, a Net::LDAP::Entry object.
247
248 Example:
249
250  user_results_filter => sub {
251                           my $search_obj = shift;
252                           foreach my $entry ($search_obj->entries) {
253                               return $entry if my_match_logic( $entry );
254                           }
255                           return undef; # i.e., no match
256                         }
257  
258 =head2 use_roles
259
260 Whether or not to enable role lookups.  It defaults to true; set it to 0 if 
261 you want to always avoid role lookups.
262
263 =head2 role_basedn
264
265 This should be the basedn where the LDAP Objects representing your roles are.
266
267 =head2 role_filter
268
269 This should be the LDAP Search filter to use during the role lookup.  It
270 defaults to '(memberUid=%s)'.  The %s in this filter is replaced with the value
271 of the "role_value" configuration option.
272
273 So, if you had a role_value of "cn", then this would be populated with the cn
274 of the User's LDAP object.  The special case is a role_value of "dn", which
275 will be replaced with the User's DN.
276
277 =head2 role_scope
278
279 This specifies the scope of the search for the user's role lookup.  Valid
280 values are "base", "one", and "sub".  Defaults to "sub".
281
282 =head2 role_field
283
284 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".
285
286 =head2 role_value
287
288 This is the attribute of the User object we want to use in our role_filter. 
289 If this is set to "dn", we will use the User Objects DN.
290
291 =head2 role_search_options
292
293 This takes a hashref.  It will append it's values to the call to
294 L<Net::LDAP>'s "search" method during the user's role lookup.  See
295 L<Net::LDAP> for valid options.
296
297 Be careful not to specify:
298
299     filter
300     scope
301     base
302
303 As they are already taken care of by other configuration options.
304
305 =head2 role_search_as_user
306
307 By default this setting is false, and the role search will be performed
308 by binding to the directory with the details in the I<binddn> and I<bindpw>
309 fields. If this is set to false, then the role search will instead be
310 performed when bound as the user you authenticated as.
311
312 =head2 entry_class
313
314 The name of the class of LDAP entries returned. This class should
315 exist and is expected to be a subclass of Net::LDAP::Entry
316
317 =head2 user_class
318
319 The name of the class of user object returned. By default, this is
320 L<Catalyst::Authentication::Store::LDAP::User>.
321
322 =head1 METHODS
323
324 =head2 new
325
326 This method will populate
327 L<Catalyst::Plugin::Authentication/default_auth_store> with this object. 
328
329 =head1 AUTHORS
330
331 Adam Jacob <holoway@cpan.org>
332
333 Some parts stolen shamelessly and entirely from
334 L<Catalyst::Plugin::Authentication::Store::Htpasswd>.
335
336 Currently maintained by Peter Karman <karman@cpan.org>.
337
338 =head1 THANKS
339
340 To nothingmuch, ghenry, castaway and the rest of #catalyst for the help. :)
341
342 =head1 SEE ALSO
343
344 L<Catalyst::Authentication::Store::LDAP>,
345 L<Catalyst::Authentication::Store::LDAP::User>,
346 L<Catalyst::Authentication::Store::LDAP::Backend>,
347 L<Catalyst::Plugin::Authentication>, 
348 L<Net::LDAP>
349
350 =head1 COPYRIGHT & LICENSE
351
352 Copyright (c) 2005 the aforementioned authors. All rights
353 reserved. This program is free software; you can redistribute
354 it and/or modify it under the same terms as Perl itself.
355
356 =cut
357
358