Skip to content

Commit 87660cf

Browse files
committed
📝 Document configuration and usage
1 parent 749e46b commit 87660cf

File tree

1 file changed

+134
-33
lines changed

1 file changed

+134
-33
lines changed

README.md

Lines changed: 134 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
| 📍 NOTE |
22
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
33
| RubyGems (the [GitHub org][rubygems-org], not the website) [suffered][draper-security] a [hostile takeover][ellen-takeover] in September 2025. |
4-
| Ultimately [4 maintainers][simi-removed] were [hard removed][martin-removed] and a reason has been given for only 1 of those, while 2 others resigned in protest. |
54
| It is a [complicated story][draper-takeover] which is difficult to [parse quickly][draper-lies]. |
65
| I'm adding notes like this to gems because I [don't condone theft][draper-theft] of repositories or gems from their rightful owners. |
76
| If a similar theft happened with my repos/gems, I'd hope some would stand up for me. |
@@ -38,7 +37,6 @@
3837

3938
# 📁 OmniAuth LDAP
4039

41-
[![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
4240

4341
`if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord].
4442

@@ -54,19 +52,17 @@ Use the LDAP strategy as a middleware in your application:
5452

5553
```ruby
5654
use OmniAuth::Strategies::LDAP,
57-
:title => "My LDAP",
55+
:title => "My LDAP",
5856
:host => '10.101.10.1',
5957
:port => 389,
6058
:method => :plain,
61-
:base => 'dc=intridea, dc=com',
59+
:base => 'dc=intridea,dc=com',
6260
:uid => 'sAMAccountName',
63-
:name_proc => Proc.new {|name| name.gsub(/@.*$/,'')},
61+
:name_proc => Proc.new { |name| name.gsub(/@.*$/, '') },
6462
:bind_dn => 'default_bind_dn',
65-
# Or, alternatively:
66-
#:filter => '(&(uid=%{username})(memberOf=cn=myapp-users,ou=groups,dc=example,dc=com))'
67-
:name_proc => Proc.new {|name| name.gsub(/@.*$/,'')}
68-
:bind_dn => 'default_bind_dn'
6963
:password => 'password'
64+
# Or, alternatively:
65+
# use OmniAuth::Strategies::LDAP, filter: '(&(uid=%{username})(memberOf=cn=myapp-users,ou=groups,dc=example,dc=com))'
7066
```
7167

7268
All of the listed options are required, with the exception of `:title`, `:name_proc`, `:bind_dn`, and `:password`.
@@ -92,7 +88,6 @@ All of the listed options are required, with the exception of `:title`, `:name_p
9288

9389
Compatible with MRI Ruby 0+, and concordant releases of JRuby, and TruffleRuby.
9490

95-
| 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
9691
|------------------------------------------------|--------------------------------------------------------|
9792
| 👟 Check it out! |[github.com/appraisal-rb/appraisal2][💎appraisal2]|
9893

@@ -170,38 +165,144 @@ NOTE: Be prepared to track down certs for signed gems and add them the same way
170165

171166
## ⚙️ Configuration
172167

168+
The following options are available for configuring the OmniAuth LDAP strategy:
173169

170+
### Required Options
171+
172+
- `:host` - The hostname or IP address of the LDAP server.
173+
- `:port` - The port number of the LDAP server (default: 389).
174+
- `:method` - The connection method. Allowed values: `:plain`, `:ssl`, `:tls` (default: `:plain`).
175+
- `:base` - The base DN for the LDAP search.
176+
- `:uid` or `:filter` - Either `:uid` (the LDAP attribute for username, default: "sAMAccountName") or `:filter` (LDAP filter for searching user entries). If `:filter` is provided, `:uid` is not required.
177+
178+
### Optional Options
179+
180+
- `:title` - The title for the authentication form (default: "LDAP Authentication").
181+
- `:bind_dn` - The DN to bind with for searching users (required if anonymous access is not allowed).
182+
- `:password` - The password for the bind DN.
183+
- `:name_proc` - A proc to process the username before using it in the search (default: identity proc that returns the username unchanged).
184+
- `:try_sasl` - Whether to use SASL authentication (default: false).
185+
- `:sasl_mechanisms` - Array of SASL mechanisms to use (e.g., ["DIGEST-MD5", "GSS-SPNEGO"]).
186+
- `:allow_anonymous` - Whether to allow anonymous binding (default: false).
187+
- `:logger` - A logger instance for debugging (optional, for internal use).
174188

175189
## 🔧 Basic Usage
176190

177-
Allowed values of `:method` are: `:plain`, `:ssl`, `:tls`.
191+
The strategy exposes a simple Rack middleware and can be used in plain Rack apps, Sinatra, or Rails.
192+
Direct users to `/auth/ldap` to start authentication and handle the callback at `/auth/ldap/callback`.
193+
194+
Below are several concrete examples to get you started.
195+
196+
### Minimal Rack setup
197+
198+
```ruby
199+
# config.ru
200+
require 'rack'
201+
require 'omniauth-ldap'
202+
203+
use Rack::Session::Cookie, secret: 'change_me'
204+
use OmniAuth::Builder do
205+
provider :ldap,
206+
host: 'ldap.example.com',
207+
port: 389,
208+
method: :plain,
209+
base: 'dc=example,dc=com',
210+
uid: 'uid',
211+
title: 'Example LDAP'
212+
end
213+
214+
run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
215+
```
216+
217+
Visit `GET /auth/ldap` to initiate authentication (the middleware will render a login form unless you POST to `/auth/ldap`).
218+
219+
### Sinatra example
220+
221+
```ruby
222+
require 'sinatra'
223+
require 'omniauth-ldap'
224+
225+
use Rack::Session::Cookie, secret: 'change_me'
226+
use OmniAuth::Builder do
227+
provider :ldap,
228+
title: 'Company LDAP',
229+
host: 'ldap.company.internal',
230+
base: 'dc=company,dc=local',
231+
uid: 'sAMAccountName',
232+
name_proc: proc { |username| username.gsub(/@.*$/, '') }
233+
end
234+
235+
get '/' do
236+
'<a href="/auth/ldap">Sign in with LDAP</a>'
237+
end
238+
239+
get '/auth/ldap/callback' do
240+
auth = request.env['omniauth.auth']
241+
"Hello, #{auth.info['name']}"
242+
end
243+
```
244+
245+
### Rails (initializer) example
246+
247+
Create `config/initializers/omniauth.rb`:
178248

179-
`:bind_dn` and `:password` is the default credentials to perform user lookup.
180-
Most LDAP servers require that you supply a complete DN as a binding-credential, along with an authenticator
181-
such as a password. But for many applications, you often don’t have a full DN to identify the user.
182-
You usually get a simple identifier like a username or an email address, along with a password.
183-
Since many LDAP servers don't allow anonymous access, search function will require a bound connection,
184-
`:bind_dn` and `:password` will be required for searching on the username or email to retrieve the DN attribute
185-
for the user. If the LDAP server allows anonymous access, you don't need to provide these two parameters.
249+
```ruby
250+
Rails.application.config.middleware.use OmniAuth::Builder do
251+
provider :ldap,
252+
title: 'Acme LDAP',
253+
host: 'ldap.acme.internal',
254+
port: 389,
255+
base: 'dc=acme,dc=corp',
256+
uid: 'uid',
257+
bind_dn: 'cn=search,dc=acme,dc=corp',
258+
password: ENV['LDAP_SEARCH_PASSWORD'],
259+
name_proc: proc { |n| n.split('@').first }
260+
end
261+
```
262+
263+
Then link users to `/auth/ldap` in your app (for example, in a Devise sign-in page).
264+
265+
### Using a custom filter
186266

187-
`:uid` is the LDAP attribute name for the username in the login form.
188-
typically AD would be 'sAMAccountName' or 'UserPrincipalName', while OpenLDAP is 'uid'.
267+
If you need to restrict authentication to a group or use a more complex lookup, pass `:filter`. Use `%{username}` — it will be replaced with the processed username (after `:name_proc`).
189268

190-
`:filter` is the LDAP filter used to search the user entry. It can be used in place of :uid for more flexibility.
191-
`%{username}` will be replaced by the username processed by `:name_proc`.
269+
```ruby
270+
provider :ldap,
271+
host: 'ldap.example.com',
272+
base: 'dc=example,dc=com',
273+
filter: '(&(uid=%{username})(memberOf=cn=myapp-users,ou=groups,dc=example,dc=com))',
274+
bind_dn: 'cn=search,dc=example,dc=com',
275+
password: ENV['LDAP_SEARCH_PASSWORD']
276+
```
192277

193-
`:name_proc` allows you to match the username entered with the format of the `:uid` attributes.
194-
For example, value of 'sAMAccountName' in AD contains only the windows username. If your user prefers using
195-
email to login, a `:name_proc` as above will trim the email string down to just the windows login name.
196-
In summary, use `:name_proc` to fill the gap between the submitted username and LDAP uid attribute value.
278+
### SASL (advanced)
197279

198-
`:try_sasl` and `:sasl_mechanisms` are optional. Valid values are:
199-
- `:try_sasl` => `true` or `false`
200-
- `:sasl_mechanisms` => `"DIGEST-MD5"` or `"GSS-SPNEGO"`
201-
Use them to initialize a SASL connection to server. If you are not familiar with these authentication methods,
202-
please just avoid them.
280+
SASL enables alternative bind mechanisms. Only enable if you understand the server-side requirements.
281+
282+
```ruby
283+
provider :ldap,
284+
host: 'ldap.example.com',
285+
base: 'dc=example,dc=com',
286+
try_sasl: true,
287+
sasl_mechanisms: ['DIGEST-MD5'],
288+
uid: 'uid'
289+
```
290+
291+
Supported mechanisms include `"DIGEST-MD5"` and `"GSS-SPNEGO"` depending on your environment and gems.
292+
293+
### Name processing and examples
294+
295+
If users log in with an email but LDAP expects a short username, use `:name_proc` to normalize the submitted value:
296+
297+
```ruby
298+
provider :ldap,
299+
host: 'ldap.example.com',
300+
base: 'dc=example,dc=com',
301+
uid: 'sAMAccountName',
302+
name_proc: proc { |name| name.gsub(/@.*$/, '') }
303+
```
203304

204-
Direct users to `/auth/ldap` to have them authenticated via your company's LDAP server.
305+
This trims `[email protected]` to `alice` before searching.
205306

206307
## 🦷 FLOSS Funding
207308

@@ -529,7 +630,7 @@ Thanks for RTFM. ☺️
529630
[📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
530631
[📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
531632
[📌gitmoji]:https://gitmoji.dev
532-
[📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
633+
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
533634
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
534635
[🧮kloc-img]: https://img.shields.io/badge/KLOC-4.076-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
535636
[🔐security]: SECURITY.md

0 commit comments

Comments
 (0)