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