omniauth-ldap 2.3.2 → 2.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +48 -3
- data/CITATION.cff +0 -0
- data/CODE_OF_CONDUCT.md +0 -0
- data/CONTRIBUTING.md +6 -3
- data/FUNDING.md +7 -10
- data/LICENSE.txt +1 -1
- data/README.md +48 -58
- data/REEK +0 -0
- data/RUBOCOP.md +0 -0
- data/SECURITY.md +0 -0
- data/lib/omniauth/strategies/ldap.rb +206 -18
- data/lib/omniauth-ldap/adaptor.rb +133 -11
- data/lib/omniauth-ldap/version.rb +10 -1
- data/lib/omniauth-ldap.rb +8 -0
- data/sig/omniauth/ldap/adaptor.rbs +0 -0
- data/sig/omniauth/ldap/version.rbs +0 -0
- data/sig/omniauth/strategies/ldap.rbs +6 -0
- data/sig/omniauth-ldap.rbs +0 -0
- data/sig/rbs/net-ldap.rbs +0 -0
- data/sig/rbs/net-ntlm.rbs +0 -0
- data/sig/rbs/sasl.rbs +0 -0
- data.tar.gz.sig +0 -0
- metadata +5 -33
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cfb42b529db19042a0140d9bdb39698b177710df48bc80eb9c1470bfebda0ae2
|
|
4
|
+
data.tar.gz: 411ba1e8817fc5814c248cbf096471ebe2f4a013a69dff3b6771143526a73f8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e5cd173bb9dd917627ba9d96d3fe3a5e713bb74e3623d8ab1247fe71da0243e0e66658f64dd356247e060fbddda4a9031e76242dd8b0ea0575d9233bfcee1b0d
|
|
7
|
+
data.tar.gz: 70d8dd160e9793037bb4564cde716dfc8cd98c3805b73c65f49c5ecd2383b13c920828affab59e458b224b8f1eebfd4a127d9bd06a55d967e1d397f21f01a1da
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -32,6 +32,47 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
32
32
|
|
|
33
33
|
### Security
|
|
34
34
|
|
|
35
|
+
## [2.3.4] - 2026-05-18
|
|
36
|
+
|
|
37
|
+
- TAG: [v2.3.4][2.3.4t]
|
|
38
|
+
- COVERAGE: 97.44% -- 304/312 lines in 4 files
|
|
39
|
+
- BRANCH COVERAGE: 79.58% -- 113/142 branches in 4 files
|
|
40
|
+
- 94.44% documented
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- Add `header_auth_source` to require explicit selection of trusted header identity source (`:env` or `:http_header`)
|
|
45
|
+
- Add `header_auth_require_tls` to require TLS for trusted header SSO by default
|
|
46
|
+
- Log a prominent security warning when `header_auth` is enabled
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- Trusted header SSO now defaults to trusting only server-set env variables and no longer checks Rack `HTTP_` header variants unless `header_auth_source: :http_header` is configured
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- Fix OpenSSL 3/Ruby 4 compatibility in the TLS options adaptor spec
|
|
55
|
+
|
|
56
|
+
### Security
|
|
57
|
+
|
|
58
|
+
- Harden trusted header SSO against spoofing by removing automatic fallback from `REMOTE_USER` to `HTTP_REMOTE_USER`
|
|
59
|
+
|
|
60
|
+
## [2.3.3] - 2025-11-10
|
|
61
|
+
|
|
62
|
+
- TAG: [v2.3.3][2.3.3t]
|
|
63
|
+
- COVERAGE: 97.61% -- 286/293 lines in 4 files
|
|
64
|
+
- BRANCH COVERAGE: 79.69% -- 102/128 branches in 4 files
|
|
65
|
+
- 94.44% documented
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- Documentation cleanup & updates
|
|
70
|
+
- YARD documentation covering 94% of the code
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- kettle-dev v1.1.54
|
|
75
|
+
|
|
35
76
|
## [2.3.2] - 2025-11-06
|
|
36
77
|
|
|
37
78
|
- TAG: [v2.3.2][2.3.2t]
|
|
@@ -50,14 +91,14 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
50
91
|
- https://datatracker.ietf.org/doc/html/draft-behera-ldap-password-policy-11
|
|
51
92
|
- Support for JSON bodies
|
|
52
93
|
- Support custom LDAP attributes mapping
|
|
53
|
-
- Raise a distinct error when LDAP server is unreachable
|
|
54
|
-
- Previously raised an invalid credentials authentication failure error, which is technically incorrect
|
|
55
94
|
- Documentation of TLS verification options
|
|
56
95
|
|
|
57
96
|
### Changed
|
|
58
97
|
|
|
59
98
|
- Make support for OmniAuth v1.2+ explicit
|
|
60
99
|
- Versions < 1.2 do not support SCRIPT_NAME properly, and may cause other issues
|
|
100
|
+
- Raise a distinct error when LDAP server is unreachable
|
|
101
|
+
- Previously raised an invalid credentials authentication failure error, which is technically incorrect
|
|
61
102
|
|
|
62
103
|
## [2.3.1] - 2025-11-05
|
|
63
104
|
|
|
@@ -224,7 +265,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
224
265
|
[1.0.0]: https://github.com/omniauth/omniauth-ldap/compare/5656da80d4193e0d0584f44bac493a87695e580f...v1.0.0
|
|
225
266
|
[1.0.0t]: https://github.com/omniauth/omniauth-ldap/releases/tag/v1.0.0
|
|
226
267
|
|
|
227
|
-
[Unreleased]: https://github.com/omniauth/omniauth-ldap/compare/v2.3.
|
|
268
|
+
[Unreleased]: https://github.com/omniauth/omniauth-ldap/compare/v2.3.4...HEAD
|
|
269
|
+
[2.3.4]: https://github.com/omniauth/omniauth-ldap/compare/v2.3.3...v2.3.4
|
|
270
|
+
[2.3.4t]: https://github.com/omniauth/omniauth-ldap/releases/tag/v2.3.4
|
|
271
|
+
[2.3.3]: https://github.com/omniauth/omniauth-ldap/compare/v2.3.2...v2.3.3
|
|
272
|
+
[2.3.3t]: https://github.com/omniauth/omniauth-ldap/releases/tag/v2.3.3
|
|
228
273
|
[2.3.2]: https://github.com/omniauth/omniauth-ldap/compare/v2.3.1...v2.3.2
|
|
229
274
|
[2.3.2t]: https://github.com/omniauth/omniauth-ldap/releases/tag/v2.3.2
|
|
230
275
|
[2.3.1]: https://github.com/omniauth/omniauth-ldap/compare/v2.0.0...v2.3.1
|
data/CITATION.cff
CHANGED
|
File without changes
|
data/CODE_OF_CONDUCT.md
CHANGED
|
File without changes
|
data/CONTRIBUTING.md
CHANGED
|
@@ -24,13 +24,13 @@ Follow these instructions:
|
|
|
24
24
|
|
|
25
25
|
## Executables vs Rake tasks
|
|
26
26
|
|
|
27
|
-
Executables shipped by dependencies, such as
|
|
27
|
+
Executables shipped by dependencies, such as kettle-dev, and stone_checksums, are available
|
|
28
28
|
after running `bin/setup`. These include:
|
|
29
29
|
|
|
30
30
|
- gem_checksums
|
|
31
31
|
- kettle-changelog
|
|
32
32
|
- kettle-commit-msg
|
|
33
|
-
-
|
|
33
|
+
- kettle-dev-setup
|
|
34
34
|
- kettle-dvcs
|
|
35
35
|
- kettle-pre-release
|
|
36
36
|
- kettle-readme-backers
|
|
@@ -68,7 +68,9 @@ GitHub API and CI helpers
|
|
|
68
68
|
Releasing and signing
|
|
69
69
|
- SKIP_GEM_SIGNING: If set, skip gem signing during build/release
|
|
70
70
|
- GEM_CERT_USER: Username for selecting your public cert in `certs/<USER>.pem` (defaults to $USER)
|
|
71
|
-
- SOURCE_DATE_EPOCH: Reproducible build timestamp.
|
|
71
|
+
- SOURCE_DATE_EPOCH: Reproducible build timestamp.
|
|
72
|
+
- `kettle-release` will set this automatically for the session.
|
|
73
|
+
- Not needed on bundler >= 2.7.0, as reproducible builds have become the default.
|
|
72
74
|
|
|
73
75
|
Git hooks and commit message helpers (exe/kettle-commit-msg)
|
|
74
76
|
- GIT_HOOK_BRANCH_VALIDATE: Branch name validation mode (e.g., `jira`) or `false` to disable
|
|
@@ -166,6 +168,7 @@ NOTE: To build without signing the gem set `SKIP_GEM_SIGNING` to any value in th
|
|
|
166
168
|
1. Update version.rb to contain the correct version-to-be-released.
|
|
167
169
|
2. Run `bundle exec kettle-changelog`.
|
|
168
170
|
3. Run `bundle exec kettle-release`.
|
|
171
|
+
4. Stay awake and monitor the release process for any errors, and answer any prompts.
|
|
169
172
|
|
|
170
173
|
#### Manual process
|
|
171
174
|
|
data/FUNDING.md
CHANGED
|
@@ -6,7 +6,7 @@ Many paths lead to being a sponsor or a backer of this project. Are you on such
|
|
|
6
6
|
|
|
7
7
|
[![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal]
|
|
8
8
|
|
|
9
|
-
[![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS
|
|
9
|
+
[![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS efforts using Patreon][🖇patreon-img]][🖇patreon]
|
|
10
10
|
|
|
11
11
|
[⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
|
|
12
12
|
[⛳liberapay]: https://liberapay.com/pboling/donate
|
|
@@ -27,11 +27,11 @@ Many paths lead to being a sponsor or a backer of this project. Are you on such
|
|
|
27
27
|
|
|
28
28
|
<!-- RELEASE-NOTES-FOOTER-END -->
|
|
29
29
|
|
|
30
|
-
# 🤑
|
|
30
|
+
# 🤑 A request for help
|
|
31
31
|
|
|
32
32
|
Maintainers have teeth and need to pay their dentists.
|
|
33
|
-
After getting laid off in an RIF in March and
|
|
34
|
-
I
|
|
33
|
+
After getting laid off in an RIF in March, and encountering difficulty finding a new one,
|
|
34
|
+
I began spending most of my time building open source tools.
|
|
35
35
|
I'm hoping to be able to pay for my kids' health insurance this month,
|
|
36
36
|
so if you value the work I am doing, I need your support.
|
|
37
37
|
Please consider sponsoring me or the project.
|
|
@@ -40,16 +40,13 @@ To join the community or get help 👇️ Join the Discord.
|
|
|
40
40
|
|
|
41
41
|
[![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
|
|
42
42
|
|
|
43
|
-
To say "thanks
|
|
43
|
+
To say "thanks!" ☝️ Join the Discord or 👇️ send money.
|
|
44
44
|
|
|
45
|
-
[![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay
|
|
45
|
+
[![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal]
|
|
46
46
|
|
|
47
47
|
# Another Way to Support Open Source Software
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
>—Anne Frank
|
|
51
|
-
|
|
52
|
-
I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions — totaling 79 hours of FLOSS coding over just the past seven days, a pretty regular week for me. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈 cats).
|
|
49
|
+
I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈 cats).
|
|
53
50
|
|
|
54
51
|
If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`.
|
|
55
52
|
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,32 +1,3 @@
|
|
|
1
|
-
| 📍 NOTE |
|
|
2
|
-
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
3
|
-
| 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. |
|
|
5
|
-
| It is a [complicated story][draper-takeover] which is difficult to [parse quickly][draper-lies]. |
|
|
6
|
-
| I'm adding notes like this to gems because I [don't condone theft][draper-theft] of repositories or gems from their rightful owners. |
|
|
7
|
-
| If a similar theft happened with my repos/gems, I'd hope some would stand up for me. |
|
|
8
|
-
| Disenfranchised former-maintainers have started [gem.coop][gem-coop]. |
|
|
9
|
-
| Once available I will publish there exclusively; unless RubyCentral makes amends with the community. |
|
|
10
|
-
| The ["Technology for Humans: Joel Draper"][reinteractive-podcast] podcast episode by [reinteractive][reinteractive] is the most cogent summary I'm aware of. |
|
|
11
|
-
| See [here][gem-naming], [here][gem-coop] and [here][martin-ann] for more info on what comes next. |
|
|
12
|
-
| What I'm doing: A (WIP) proposal for [bundler/gem scopes][gem-scopes], and a (WIP) proposal for a federated [gem server][gem-server]. |
|
|
13
|
-
|
|
14
|
-
[rubygems-org]: https://github.com/rubygems/
|
|
15
|
-
[draper-security]: https://joel.drapper.me/p/ruby-central-security-measures/
|
|
16
|
-
[draper-takeover]: https://joel.drapper.me/p/ruby-central-takeover/
|
|
17
|
-
[ellen-takeover]: https://pup-e.com/blog/goodbye-rubygems/
|
|
18
|
-
[simi-removed]: https://www.reddit.com/r/ruby/s/gOk42POCaV
|
|
19
|
-
[martin-removed]: https://bsky.app/profile/martinemde.com/post/3m3occezxxs2q
|
|
20
|
-
[draper-lies]: https://joel.drapper.me/p/ruby-central-fact-check/
|
|
21
|
-
[draper-theft]: https://joel.drapper.me/p/ruby-central/
|
|
22
|
-
[reinteractive]: https://reinteractive.com/ruby-on-rails
|
|
23
|
-
[gem-coop]: https://gem.coop
|
|
24
|
-
[gem-naming]: https://github.com/gem-coop/gem.coop/issues/12
|
|
25
|
-
[martin-ann]: https://martinemde.com/2025/10/05/announcing-gem-coop.html
|
|
26
|
-
[gem-scopes]: https://github.com/galtzo-floss/bundle-namespace
|
|
27
|
-
[gem-server]: https://github.com/galtzo-floss/gem-server
|
|
28
|
-
[reinteractive-podcast]: https://youtu.be/_H4qbtC5qzU?si=BvuBU90R2wAqD2E6
|
|
29
|
-
|
|
30
1
|
[![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-i]][🖼️galtzo-discord] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![omniauth Logo (presumed to be) by tomeara, (presumed to be) MIT License][🖼️omniauth-i]][🖼️omniauth]
|
|
31
2
|
|
|
32
3
|
[🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
|
|
@@ -48,6 +19,13 @@
|
|
|
48
19
|
|
|
49
20
|
[![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate at ko-fi.com][🖇kofi-img]][🖇kofi]
|
|
50
21
|
|
|
22
|
+
<details>
|
|
23
|
+
<summary>👣 How will this project approach the September 2025 hostile takeover of RubyGems? 🚑️</summary>
|
|
24
|
+
|
|
25
|
+
I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo).
|
|
26
|
+
|
|
27
|
+
</details>
|
|
28
|
+
|
|
51
29
|
## 🌻 Synopsis
|
|
52
30
|
|
|
53
31
|
Use the LDAP strategy as a middleware in your application:
|
|
@@ -79,9 +57,11 @@ use OmniAuth::Strategies::LDAP,
|
|
|
79
57
|
# use OmniAuth::Strategies::LDAP, filter: '(&(uid=%{username})(memberOf=cn=myapp-users,ou=groups,dc=example,dc=com))'
|
|
80
58
|
```
|
|
81
59
|
|
|
82
|
-
|
|
60
|
+
At minimum you normally configure `:host`, `:base`, and either `:uid` or `:filter`. The other options shown above customize connection behavior, TLS, username normalization, timeouts, and returned auth info.
|
|
83
61
|
|
|
84
|
-
|
|
62
|
+
For trusted header SSO, enable `header_auth: true` and explicitly choose the trusted identity source with `header_auth_source: :env` or `header_auth_source: :http_header`. See [Trusted header SSO](#trusted-header-sso-remote_user-and-friends) for the security requirements.
|
|
63
|
+
|
|
64
|
+
### TLS certificate verification
|
|
85
65
|
|
|
86
66
|
This gem enables TLS certificate verification by default when you use `encryption: "ssl"` (LDAPS / simple TLS) or `encryption: "tls"` (STARTTLS). We always pass `tls_options` to Net::LDAP based on `OpenSSL::SSL::SSLContext::DEFAULT_PARAMS`, which includes `verify_mode: OpenSSL::SSL::VERIFY_PEER` and sane defaults.
|
|
87
67
|
|
|
@@ -153,7 +133,7 @@ Compatible with MRI Ruby 2.0+, and concordant releases of JRuby, and TruffleRuby
|
|
|
153
133
|
|
|
154
134
|
Available as part of the Tidelift Subscription.
|
|
155
135
|
|
|
156
|
-
<details>
|
|
136
|
+
<details markdown="1">
|
|
157
137
|
<summary>Need enterprise-level guarantees?</summary>
|
|
158
138
|
|
|
159
139
|
The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
|
|
@@ -188,7 +168,7 @@ gem install omniauth-ldap
|
|
|
188
168
|
|
|
189
169
|
### 🔒 Secure Installation
|
|
190
170
|
|
|
191
|
-
<details>
|
|
171
|
+
<details markdown="1">
|
|
192
172
|
<summary>For Medium or High Security Installations</summary>
|
|
193
173
|
|
|
194
174
|
This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by
|
|
@@ -228,14 +208,14 @@ The following options are available for configuring the OmniAuth LDAP strategy:
|
|
|
228
208
|
### Required Options
|
|
229
209
|
|
|
230
210
|
- `:host` - The hostname or IP address of the LDAP server.
|
|
231
|
-
- `:port` - The port number of the LDAP server (default: 389).
|
|
232
|
-
- `:method` - The connection method. Allowed values: `:plain`, `:ssl`, `:tls` (default: `:plain`).
|
|
233
211
|
- `:base` - The base DN for the LDAP search.
|
|
234
212
|
- `: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. Note: This `:uid` option is the search attribute, not the top-level `auth.uid` in the OmniAuth result.
|
|
235
213
|
|
|
236
214
|
### Optional Options
|
|
237
215
|
|
|
238
216
|
- `:title` - The title for the authentication form (default: "LDAP Authentication").
|
|
217
|
+
- `:port` - The port number of the LDAP server (default: 389).
|
|
218
|
+
- `:encryption` - The connection method. Allowed values: `:plain`, `:ssl`, `:tls` (default: `:plain`). `:method` is still accepted for compatibility, but is deprecated.
|
|
239
219
|
- `:bind_dn` - The DN to bind with for searching users (required if anonymous access is not allowed).
|
|
240
220
|
- `:password` - The password for the bind DN.
|
|
241
221
|
- `:name_proc` - A proc to process the username before using it in the search (default: identity proc that returns the username unchanged).
|
|
@@ -249,6 +229,10 @@ The following options are available for configuring the OmniAuth LDAP strategy:
|
|
|
249
229
|
- `:connect_timeout` - Maximum time in seconds to wait when establishing the TCP connection to the LDAP server. Forwarded to `Net::LDAP`.
|
|
250
230
|
- `:read_timeout` - Maximum time in seconds to wait for reads during LDAP operations (search/bind). Forwarded to `Net::LDAP`.
|
|
251
231
|
- `:mapping` - Customize how LDAP attributes map to the returned `auth.info` hash. A sensible default mapping is built into the strategy and will be merged with your overrides. See `lib/omniauth/strategies/ldap.rb` for the default keys and behavior; values can be a String (single attribute), an Array (first present attribute wins), or a Hash (string pattern with placeholders like `%0` combined from multiple attributes).
|
|
232
|
+
- `:header_auth` - Enable trusted upstream identity SSO (default: false). When enabled, the strategy trusts the configured header/env key, performs an LDAP lookup, and skips the user password bind.
|
|
233
|
+
- `:header_name` - Header/env key used for trusted header SSO (default: "REMOTE_USER").
|
|
234
|
+
- `:header_auth_source` - Trusted identity source for header SSO (default: `:env`). Use `:env` to read only `env["REMOTE_USER"]`-style server variables. Use `:http_header` to read only Rack `HTTP_` header keys such as `env["HTTP_REMOTE_USER"]`; only configure this behind a proxy that strips client-supplied copies.
|
|
235
|
+
- `:header_auth_require_tls` - Require TLS for trusted header SSO requests (default: true).
|
|
252
236
|
|
|
253
237
|
Example enabling password policy:
|
|
254
238
|
|
|
@@ -284,7 +268,7 @@ Where to find the "username"-style value
|
|
|
284
268
|
- You can also read the raw attribute from `auth.extra.raw_info` (a `Net::LDAP::Entry`):
|
|
285
269
|
|
|
286
270
|
```ruby
|
|
287
|
-
|
|
271
|
+
post "/auth/ldap/callback" do
|
|
288
272
|
auth = request.env["omniauth.auth"]
|
|
289
273
|
dn = auth.uid # => "cn=alice,ou=users,dc=example,dc=com"
|
|
290
274
|
username = auth.info.nickname # => "alice" (from uid/sAMAccountName)
|
|
@@ -300,7 +284,7 @@ If you need top-level `auth.uid` to be something other than the DN (for example,
|
|
|
300
284
|
## 🔧 Basic Usage
|
|
301
285
|
|
|
302
286
|
The strategy exposes a simple Rack middleware and can be used in plain Rack apps, Sinatra, or Rails.
|
|
303
|
-
|
|
287
|
+
With OmniAuth 2.x, initiate authentication with `POST /auth/ldap`; `GET /auth/ldap` returns 404 by default. Older OmniAuth 1.x deployments may still render the form on `GET /auth/ldap`. Handle the callback at `/auth/ldap/callback`.
|
|
304
288
|
|
|
305
289
|
Below are several concrete examples to get you started.
|
|
306
290
|
|
|
@@ -316,7 +300,7 @@ use OmniAuth::Builder do
|
|
|
316
300
|
provider :ldap,
|
|
317
301
|
host: "ldap.example.com",
|
|
318
302
|
port: 389,
|
|
319
|
-
|
|
303
|
+
encryption: :plain,
|
|
320
304
|
base: "dc=example,dc=com",
|
|
321
305
|
uid: "uid",
|
|
322
306
|
title: "Example LDAP"
|
|
@@ -325,7 +309,7 @@ end
|
|
|
325
309
|
run lambda { |env| [404, {"Content-Type" => "text/plain"}, [env.key?("omniauth.auth").to_s]] }
|
|
326
310
|
```
|
|
327
311
|
|
|
328
|
-
|
|
312
|
+
Submit `POST /auth/ldap` to initiate authentication. With OmniAuth 2.x, the middleware renders the login form on POST when credentials are not already present; with OmniAuth 1.x, `GET /auth/ldap` can also render the form.
|
|
329
313
|
|
|
330
314
|
### Sinatra example
|
|
331
315
|
|
|
@@ -344,10 +328,10 @@ use OmniAuth::Builder do
|
|
|
344
328
|
end
|
|
345
329
|
|
|
346
330
|
get "/" do
|
|
347
|
-
'<
|
|
331
|
+
'<form action="/auth/ldap" method="post"><button type="submit">Sign in with LDAP</button></form>'
|
|
348
332
|
end
|
|
349
333
|
|
|
350
|
-
|
|
334
|
+
post "/auth/ldap/callback" do
|
|
351
335
|
auth = request.env["omniauth.auth"]
|
|
352
336
|
"Hello, #{auth.info["name"]}"
|
|
353
337
|
end
|
|
@@ -371,7 +355,7 @@ Rails.application.config.middleware.use(OmniAuth::Builder) do
|
|
|
371
355
|
end
|
|
372
356
|
```
|
|
373
357
|
|
|
374
|
-
Then
|
|
358
|
+
Then submit users to `/auth/ldap` with POST in your app (for example, from a Devise sign-in page).
|
|
375
359
|
|
|
376
360
|
### Use JSON Body
|
|
377
361
|
|
|
@@ -422,7 +406,7 @@ Examples
|
|
|
422
406
|
|
|
423
407
|
Notes
|
|
424
408
|
|
|
425
|
-
- You can still initiate authentication
|
|
409
|
+
- You can still initiate authentication with a regular form POST and then submit credentials as form-encoded data. JSON is an additional option, not a replacement.
|
|
426
410
|
- In the callback phase (`POST /auth/ldap/callback`), the strategy reads JSON credentials the same way; Rails exposes them via `action_dispatch.request.request_parameters` and non-Rails apps should use a JSON parser middleware.
|
|
427
411
|
|
|
428
412
|
### Using a custom filter
|
|
@@ -607,15 +591,19 @@ Note: You generally do not need this override. Prefer configuring your proxy to
|
|
|
607
591
|
|
|
608
592
|
### Trusted header SSO (REMOTE_USER and friends)
|
|
609
593
|
|
|
610
|
-
Some deployments terminate SSO at a reverse proxy or portal and forward the already-authenticated user identity via
|
|
594
|
+
Some deployments terminate SSO at a reverse proxy or portal and forward the already-authenticated user identity via a server-set environment variable or HTTP header such as `REMOTE_USER`.
|
|
611
595
|
When you enable this mode, the LDAP strategy will trust the upstream header, perform a directory lookup for that user, and complete OmniAuth without asking the user for a password.
|
|
612
596
|
|
|
613
|
-
Important: Only enable this behind a trusted front-end that
|
|
597
|
+
Important: Only enable this behind a trusted front-end that authenticates users before they can reach the OmniAuth endpoint. When `header_auth` is enabled the strategy logs a prominent security warning because it trusts the upstream identity completely.
|
|
614
598
|
|
|
615
599
|
Configuration options:
|
|
616
600
|
|
|
617
601
|
- `:header_auth` (Boolean, default: false) — Enable trusted header SSO.
|
|
618
|
-
- `:header_name` (String, default: "REMOTE_USER") — The env/header key to read.
|
|
602
|
+
- `:header_name` (String, default: "REMOTE_USER") — The env/header key to read.
|
|
603
|
+
- `:header_auth_source` (`:env` or `:http_header`, default: `:env`) — Which Rack env key form to trust.
|
|
604
|
+
- `:env` reads only the exact server-set environment key, such as `env["REMOTE_USER"]`.
|
|
605
|
+
- `:http_header` reads only the Rack HTTP header key, such as `env["HTTP_REMOTE_USER"]`. Only use this behind a proxy that strips client-sent copies of the header before setting its trusted value.
|
|
606
|
+
- `:header_auth_require_tls` (Boolean, default: true) — Raise an error if trusted header SSO is used on a non-TLS request.
|
|
619
607
|
- `:name_proc` is applied to the header value before search (e.g., to strip a domain part).
|
|
620
608
|
- Search is done using your configured `:uid` or `:filter` and the service bind (`:bind_dn`/`:password`) or anonymous bind if allowed.
|
|
621
609
|
|
|
@@ -629,8 +617,9 @@ use OmniAuth::Builder do
|
|
|
629
617
|
uid: "uid",
|
|
630
618
|
bind_dn: "cn=search,dc=example,dc=com",
|
|
631
619
|
password: ENV["LDAP_SEARCH_PASSWORD"],
|
|
632
|
-
header_auth: true,
|
|
633
|
-
header_name: "REMOTE_USER",
|
|
620
|
+
header_auth: true, # trust the configured upstream identity
|
|
621
|
+
header_name: "REMOTE_USER", # default
|
|
622
|
+
header_auth_source: :env, # default; reads env["REMOTE_USER"]
|
|
634
623
|
name_proc: proc { |n| n.split("@").first }
|
|
635
624
|
end
|
|
636
625
|
```
|
|
@@ -648,6 +637,7 @@ Rails.application.config.middleware.use(OmniAuth::Builder) do
|
|
|
648
637
|
password: ENV["LDAP_SEARCH_PASSWORD"],
|
|
649
638
|
header_auth: true,
|
|
650
639
|
header_name: "REMOTE_USER",
|
|
640
|
+
header_auth_source: :env,
|
|
651
641
|
# Optionally restrict with a group filter while using the header value
|
|
652
642
|
filter: "(&(sAMAccountName=%{username})(memberOf=cn=myapp-users,ou=groups,dc=acme,dc=corp))",
|
|
653
643
|
name_proc: proc { |n| n.gsub(/@.*$/, "") }
|
|
@@ -662,13 +652,14 @@ Flow:
|
|
|
662
652
|
|
|
663
653
|
Security checklist:
|
|
664
654
|
|
|
665
|
-
-
|
|
666
|
-
-
|
|
655
|
+
- Prefer `header_auth_source: :env` for server-set variables such as `REMOTE_USER`.
|
|
656
|
+
- Use `header_auth_source: :http_header` only when your reverse proxy strips user-controlled copies of the header and sets the canonical value itself.
|
|
657
|
+
- Keep `header_auth_require_tls` enabled unless a separate trusted channel protects traffic between the proxy and your app.
|
|
667
658
|
- Consider also restricting with a group-based `:filter` so only authorized users can sign in.
|
|
668
659
|
|
|
669
660
|
## 🦷 FLOSS Funding
|
|
670
661
|
|
|
671
|
-
While
|
|
662
|
+
While omniauth tools are free software and will always be, the project would benefit immensely from some funding.
|
|
672
663
|
Raising a monthly budget of... "dollars" would make the project more sustainable.
|
|
673
664
|
|
|
674
665
|
We welcome both individual and corporate sponsors! We also offer a
|
|
@@ -678,7 +669,7 @@ Currently, [GitHub Sponsors][🖇sponsor], and [Liberapay][⛳liberapay] are our
|
|
|
678
669
|
**If you're working in a company that's making significant use of omniauth tools we'd
|
|
679
670
|
appreciate it if you suggest to your company to become a omniauth sponsor.**
|
|
680
671
|
|
|
681
|
-
You can support
|
|
672
|
+
You can support the development of omniauth tools via
|
|
682
673
|
[GitHub Sponsors][🖇sponsor],
|
|
683
674
|
[Liberapay][⛳liberapay],
|
|
684
675
|
[PayPal][🖇paypal],
|
|
@@ -698,7 +689,7 @@ I’m developing a new library, [floss_funding][🖇floss-funding-gem], designed
|
|
|
698
689
|
|
|
699
690
|
**[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
|
|
700
691
|
|
|
701
|
-
[![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS
|
|
692
|
+
[![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS efforts using Patreon][🖇patreon-img]][🖇patreon]
|
|
702
693
|
|
|
703
694
|
## 🔐 Security
|
|
704
695
|
|
|
@@ -770,12 +761,11 @@ For example:
|
|
|
770
761
|
spec.add_dependency("omniauth-ldap", "~> 1.0")
|
|
771
762
|
```
|
|
772
763
|
|
|
773
|
-
<details>
|
|
764
|
+
<details markdown="1">
|
|
774
765
|
<summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
|
|
775
766
|
|
|
776
767
|
SemVer should, IMO, but doesn't explicitly, say that dropping support for specific Platforms
|
|
777
|
-
is a *breaking change* to an API.
|
|
778
|
-
It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless.
|
|
768
|
+
is a *breaking change* to an API, and for that reason the bike shedding is endless.
|
|
779
769
|
|
|
780
770
|
To get a better understanding of how SemVer is intended to work over a project's lifetime,
|
|
781
771
|
read this article from the creator of SemVer:
|
|
@@ -796,7 +786,7 @@ See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright
|
|
|
796
786
|
|
|
797
787
|
<ul>
|
|
798
788
|
<li>
|
|
799
|
-
Copyright (c) 2025 Peter H. Boling, of
|
|
789
|
+
Copyright (c) 2025 - 2026 Peter H. Boling, of
|
|
800
790
|
<a href="https://discord.gg/3qme4XHNKN">
|
|
801
791
|
Galtzo.com
|
|
802
792
|
<picture>
|
|
@@ -991,7 +981,7 @@ Thanks for RTFM. ☺️
|
|
|
991
981
|
[📌gitmoji]: https://gitmoji.dev
|
|
992
982
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
993
983
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
994
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.
|
|
984
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.312-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
995
985
|
[🔐security]: SECURITY.md
|
|
996
986
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
997
987
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/REEK
CHANGED
|
File without changes
|
data/RUBOCOP.md
CHANGED
|
File without changes
|
data/SECURITY.md
CHANGED
|
File without changes
|
|
@@ -1,14 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "omniauth"
|
|
2
4
|
require "omniauth/version"
|
|
3
5
|
|
|
6
|
+
# OmniAuth strategies namespace.
|
|
7
|
+
#
|
|
8
|
+
# This file implements an LDAP authentication strategy for OmniAuth.
|
|
9
|
+
# It provides both an interactive request phase (login form) and a
|
|
10
|
+
# callback phase which binds to an LDAP directory to authenticate the
|
|
11
|
+
# user or performs a lookup for header-based SSO.
|
|
12
|
+
#
|
|
13
|
+
# The strategy exposes a number of options (see `option` calls below)
|
|
14
|
+
# that control LDAP connection, mapping of LDAP attributes to the
|
|
15
|
+
# OmniAuth `info` hash, header-based SSO behavior, and SSL/timeouts.
|
|
16
|
+
#
|
|
17
|
+
# @example Minimal Rack mounting
|
|
18
|
+
# use OmniAuth::Builder do
|
|
19
|
+
# provider :ldap, {
|
|
20
|
+
# host: 'ldap.example.com',
|
|
21
|
+
# base: 'dc=example,dc=com'
|
|
22
|
+
# }
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
4
25
|
module OmniAuth
|
|
5
26
|
module Strategies
|
|
27
|
+
# LDAP OmniAuth strategy
|
|
28
|
+
#
|
|
29
|
+
# This class implements the OmniAuth::Strategy interface and performs
|
|
30
|
+
# LDAP authentication using an `Adaptor` object. It supports three
|
|
31
|
+
# primary flows:
|
|
32
|
+
#
|
|
33
|
+
# - Interactive login form (request_phase) where users POST username/password
|
|
34
|
+
# - Callback binding where the strategy attempts to bind as the user
|
|
35
|
+
# - Header-based SSO (trusted upstream) where a header identifies the user
|
|
36
|
+
#
|
|
37
|
+
# The mapping from LDAP attributes to resulting `info` fields is
|
|
38
|
+
# configurable via the `:mapping` option. See `map_user` for the
|
|
39
|
+
# mapping algorithm.
|
|
40
|
+
#
|
|
41
|
+
# @see OmniAuth::Strategy
|
|
6
42
|
class LDAP
|
|
43
|
+
# Whether the loaded OmniAuth version is >= 2.0.0; used to set default request methods.
|
|
44
|
+
# @return [Boolean]
|
|
7
45
|
OMNIAUTH_GTE_V2 = Gem::Version.new(OmniAuth::VERSION) >= Gem::Version.new("2.0.0")
|
|
46
|
+
|
|
8
47
|
include OmniAuth::Strategy
|
|
9
48
|
|
|
49
|
+
# Raised when credentials are invalid or the user cannot be authenticated.
|
|
50
|
+
# @example
|
|
51
|
+
# raise InvalidCredentialsError, 'Invalid credentials'
|
|
10
52
|
InvalidCredentialsError = Class.new(StandardError)
|
|
11
53
|
|
|
54
|
+
# Default mapping for converting LDAP attributes to OmniAuth `info` keys.
|
|
55
|
+
# Keys are the resulting `info` hash keys (strings). Values may be:
|
|
56
|
+
# - String: single LDAP attribute name
|
|
57
|
+
# - Array: list of attribute names in priority order
|
|
58
|
+
# - Hash: pattern mapping where pattern keys contain %<n> placeholders
|
|
59
|
+
# that are substituted from a list of possible attribute names
|
|
60
|
+
#
|
|
61
|
+
# @return [Hash<String, String|Array|Hash>]
|
|
12
62
|
option :mapping, {
|
|
13
63
|
"name" => "cn",
|
|
14
64
|
"first_name" => "givenName",
|
|
@@ -24,7 +74,11 @@ module OmniAuth
|
|
|
24
74
|
"image" => "jpegPhoto",
|
|
25
75
|
"description" => "description",
|
|
26
76
|
}
|
|
27
|
-
|
|
77
|
+
|
|
78
|
+
# Default title shown on the login form.
|
|
79
|
+
# @return [String]
|
|
80
|
+
option :title, "LDAP Authentication"
|
|
81
|
+
|
|
28
82
|
# For OmniAuth >= 2.0 the default allowed request method is POST only.
|
|
29
83
|
# Ensure the strategy follows that default so GET /auth/:provider returns 404 as expected in tests.
|
|
30
84
|
if OMNIAUTH_GTE_V2
|
|
@@ -32,6 +86,8 @@ module OmniAuth
|
|
|
32
86
|
else
|
|
33
87
|
option(:request_methods, [:get, :post])
|
|
34
88
|
end
|
|
89
|
+
|
|
90
|
+
# Default LDAP connection options / behavior
|
|
35
91
|
option :port, 389
|
|
36
92
|
option :method, :plain
|
|
37
93
|
option :disable_verify_certificates, false
|
|
@@ -39,17 +95,34 @@ module OmniAuth
|
|
|
39
95
|
option :ssl_version, nil # use OpenSSL default if nil
|
|
40
96
|
option :uid, "sAMAccountName"
|
|
41
97
|
option :name_proc, lambda { |n| n }
|
|
98
|
+
|
|
42
99
|
# Trusted header SSO support (disabled by default)
|
|
43
|
-
# :header_auth - when true and the header is present, the strategy trusts
|
|
44
|
-
# and searches the directory for the user without
|
|
45
|
-
#
|
|
46
|
-
#
|
|
100
|
+
# :header_auth - when true and the configured header/env key is present, the strategy trusts
|
|
101
|
+
# the upstream gateway and searches the directory for the user without
|
|
102
|
+
# requiring a user password.
|
|
103
|
+
# :header_name - which header/env key to read (default: "REMOTE_USER").
|
|
104
|
+
# :header_auth_source - :env trusts only server-set env variables. :http_header trusts only
|
|
105
|
+
# Rack HTTP header keys, and should only be used behind a proxy that
|
|
106
|
+
# strips client-supplied copies of the header.
|
|
107
|
+
# :header_auth_require_tls - require a TLS request for header auth.
|
|
47
108
|
option :header_auth, false
|
|
48
109
|
option :header_name, "REMOTE_USER"
|
|
110
|
+
option :header_auth_source, :env
|
|
111
|
+
option :header_auth_require_tls, true
|
|
112
|
+
|
|
49
113
|
# Optional timeouts (forwarded to Net::LDAP when supported)
|
|
50
114
|
option :connect_timeout, nil
|
|
51
115
|
option :read_timeout, nil
|
|
52
116
|
|
|
117
|
+
# Request phase: Render the login form or redirect to callback for header-auth or direct POSTed credentials
|
|
118
|
+
#
|
|
119
|
+
# This will behave differently depending on OmniAuth version and request method:
|
|
120
|
+
# - For OmniAuth >= 2.0 a GET to /auth/:provider should return 404 (so we return a 404 for GET requests).
|
|
121
|
+
# - If header-based SSO is enabled and a trusted header is present we immediately redirect to the callback.
|
|
122
|
+
# - If credentials are POSTed directly to /auth/:provider we redirect to the callback so the test helpers
|
|
123
|
+
# that populate `env['omniauth.auth']` can operate on the callback request.
|
|
124
|
+
#
|
|
125
|
+
# @return [Array] A Rack response triple from the login form or redirect.
|
|
53
126
|
def request_phase
|
|
54
127
|
# OmniAuth >= 2.0 expects the request phase to be POST-only for /auth/:provider.
|
|
55
128
|
# Some test environments (and OmniAuth itself) enforce this by returning 404 on GET.
|
|
@@ -57,6 +130,8 @@ module OmniAuth
|
|
|
57
130
|
return Rack::Response.new("", 404, {"Content-Type" => "text/plain"}).finish
|
|
58
131
|
end
|
|
59
132
|
|
|
133
|
+
validate_header_auth_configuration!
|
|
134
|
+
|
|
60
135
|
# Fast-path: if a trusted identity header is present, skip the login form
|
|
61
136
|
# and jump to the callback where we will complete using directory lookup.
|
|
62
137
|
if header_username
|
|
@@ -78,11 +153,26 @@ module OmniAuth
|
|
|
78
153
|
f.to_response
|
|
79
154
|
end
|
|
80
155
|
|
|
156
|
+
# Callback phase: Authenticate user or perform header-based lookup
|
|
157
|
+
#
|
|
158
|
+
# This method executes on the callback URL and implements the main
|
|
159
|
+
# authentication logic. There are two primary paths:
|
|
160
|
+
#
|
|
161
|
+
# - Header-based lookup: when `options[:header_auth]` is enabled and a header value is present,
|
|
162
|
+
# we perform a read-only directory lookup for the user and, if found, map attributes and finish.
|
|
163
|
+
# - Password bind: when username/password are provided we attempt a bind as the user using the adaptor.
|
|
164
|
+
#
|
|
165
|
+
# Errors raised by the LDAP adaptor are captured and turned into OmniAuth failures.
|
|
166
|
+
#
|
|
167
|
+
# @raise [InvalidCredentialsError] when credentials are invalid
|
|
168
|
+
# @return [Object] result of calling `super` from the OmniAuth::Strategy chain
|
|
81
169
|
def callback_phase
|
|
82
170
|
@adaptor = OmniAuth::LDAP::Adaptor.new(@options)
|
|
83
171
|
|
|
84
172
|
return fail!(:invalid_request_method) unless valid_request_method?
|
|
85
173
|
|
|
174
|
+
validate_header_auth_configuration!
|
|
175
|
+
|
|
86
176
|
# Header-based SSO (REMOTE_USER-style) path
|
|
87
177
|
if (hu = header_username)
|
|
88
178
|
begin
|
|
@@ -118,6 +208,15 @@ module OmniAuth
|
|
|
118
208
|
end
|
|
119
209
|
end
|
|
120
210
|
|
|
211
|
+
# Build an LDAP filter for searching/binding the user.
|
|
212
|
+
#
|
|
213
|
+
# If the adaptor has a custom `filter` option set it will be used (with
|
|
214
|
+
# interpolation of `%{username}`). Otherwise a simple equality filter for
|
|
215
|
+
# the configured uid attribute is used.
|
|
216
|
+
#
|
|
217
|
+
# @param adaptor [OmniAuth::LDAP::Adaptor] the adaptor used to build connection/filters
|
|
218
|
+
# @param username_override [String, nil] optional username to build the filter for (defaults to request username)
|
|
219
|
+
# @return [Net::LDAP::Filter] the constructed filter object
|
|
121
220
|
def filter(adaptor, username_override = nil)
|
|
122
221
|
flt = adaptor.filter
|
|
123
222
|
if flt && !flt.to_s.empty?
|
|
@@ -128,17 +227,37 @@ module OmniAuth
|
|
|
128
227
|
end
|
|
129
228
|
end
|
|
130
229
|
|
|
131
|
-
uid
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
230
|
+
# The uid exposed to OmniAuth consumers.
|
|
231
|
+
#
|
|
232
|
+
# This block-based DSL is part of OmniAuth::Strategy; document the value
|
|
233
|
+
# returned by the block.
|
|
234
|
+
#
|
|
235
|
+
# @return [String] the user's uid as determined from the mapped info
|
|
236
|
+
uid { @user_info["uid"] }
|
|
237
|
+
|
|
238
|
+
# The `info` hash returned to OmniAuth consumers. Usually contains name, email, etc.
|
|
239
|
+
# @return [Hash<String, Object>]
|
|
240
|
+
info { @user_info }
|
|
241
|
+
|
|
242
|
+
# Extra information exposed under `extra[:raw_info]` containing the raw LDAP entry.
|
|
243
|
+
# @return [Hash{Symbol => Object}]
|
|
244
|
+
extra { {raw_info: @ldap_user_info} }
|
|
140
245
|
|
|
141
246
|
class << self
|
|
247
|
+
# Map LDAP attributes from the directory entry into a simple Hash used
|
|
248
|
+
# for the OmniAuth `info` hash according to the provided `mapper`.
|
|
249
|
+
#
|
|
250
|
+
# The mapper supports three types of values:
|
|
251
|
+
# - String: a single attribute name. The method will call the attribute
|
|
252
|
+
# reader (downcased symbol) on the `object` and take the first value.
|
|
253
|
+
# - Array: iterate values and pick the first attribute that exists on the object.
|
|
254
|
+
# - Hash: a mapping of a pattern string to an array of attribute-name lists
|
|
255
|
+
# where each `%<n>` placeholder in the pattern will be substituted by the
|
|
256
|
+
# first available attribute from the corresponding list.
|
|
257
|
+
#
|
|
258
|
+
# @param mapper [Hash] mapping configuration (see option :mapping)
|
|
259
|
+
# @param object [#respond_to?, #[]] directory entry (commonly a Net::LDAP::Entry or similar)
|
|
260
|
+
# @return [Hash<String, Object>] the mapped user info hash
|
|
142
261
|
def map_user(mapper, object)
|
|
143
262
|
user = {}
|
|
144
263
|
mapper.each do |key, value|
|
|
@@ -177,33 +296,93 @@ module OmniAuth
|
|
|
177
296
|
|
|
178
297
|
protected
|
|
179
298
|
|
|
299
|
+
# Validate that the incoming request method is allowed.
|
|
300
|
+
#
|
|
301
|
+
# For OmniAuth >= 2.0 the default is POST only. This method checks the
|
|
302
|
+
# Rack env REQUEST_METHOD directly so tests and environments that stub
|
|
303
|
+
# request.HTTP_METHOD are handled deterministically.
|
|
304
|
+
#
|
|
305
|
+
# @return [Boolean] true when the request method is POST
|
|
180
306
|
def valid_request_method?
|
|
181
307
|
request.env["REQUEST_METHOD"] == "POST"
|
|
182
308
|
end
|
|
183
309
|
|
|
310
|
+
# Determine if the request is missing required credentials.
|
|
311
|
+
#
|
|
312
|
+
# @return [Boolean] true when username or password are nil/empty
|
|
184
313
|
def missing_credentials?
|
|
185
314
|
request_data["username"].nil? || request_data["username"].empty? || request_data["password"].nil? || request_data["password"].empty?
|
|
186
315
|
end
|
|
187
316
|
|
|
317
|
+
# Extract request parameters in a way compatible with Rails/Rack.
|
|
318
|
+
#
|
|
319
|
+
# @return [Hash] parameters hash containing at least "username" and "password" when provided
|
|
188
320
|
def request_data
|
|
189
321
|
@env["action_dispatch.request.request_parameters"] || request.params
|
|
190
322
|
end
|
|
191
323
|
|
|
192
|
-
# Extract a normalized username from a trusted header when enabled.
|
|
324
|
+
# Extract a normalized username from a trusted header/env key when enabled.
|
|
193
325
|
# Returns nil when not configured or not present.
|
|
326
|
+
#
|
|
327
|
+
# The source is intentionally explicit: :env reads the raw env key
|
|
328
|
+
# (e.g. "REMOTE_USER"), while :http_header reads the Rack HTTP_ variant
|
|
329
|
+
# (e.g. "HTTP_REMOTE_USER" or "HTTP_X_REMOTE_USER").
|
|
330
|
+
#
|
|
331
|
+
# @return [String, nil] normalized username or nil if not present
|
|
194
332
|
def header_username
|
|
195
333
|
return unless options[:header_auth]
|
|
196
334
|
|
|
197
|
-
|
|
198
|
-
# Try both the raw env var (e.g., REMOTE_USER) and the Rack HTTP_ variant (e.g., HTTP_REMOTE_USER or HTTP_X_REMOTE_USER)
|
|
199
|
-
raw = request.env[name] || request.env["HTTP_#{name.upcase.tr("-", "_")}"]
|
|
335
|
+
raw = request.env[header_auth_env_key]
|
|
200
336
|
return if raw.nil? || raw.to_s.strip.empty?
|
|
201
337
|
|
|
202
338
|
options[:name_proc].call(raw.to_s)
|
|
203
339
|
end
|
|
204
340
|
|
|
341
|
+
# Validate trusted header auth before reading the configured identity key.
|
|
342
|
+
#
|
|
343
|
+
# @raise [ArgumentError] when the header auth options are unsafe or invalid
|
|
344
|
+
# @return [void]
|
|
345
|
+
def validate_header_auth_configuration!
|
|
346
|
+
return unless options[:header_auth]
|
|
347
|
+
|
|
348
|
+
log_header_auth_warning
|
|
349
|
+
|
|
350
|
+
source = (options[:header_auth_source] || :env).to_sym
|
|
351
|
+
unless [:env, :http_header].include?(source)
|
|
352
|
+
raise ArgumentError, "header_auth_source must be :env or :http_header"
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
if options[:header_auth_require_tls] && !request.ssl?
|
|
356
|
+
raise ArgumentError, "header_auth requires TLS unless header_auth_require_tls is disabled"
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Rack env key selected by the explicit header auth source option.
|
|
361
|
+
#
|
|
362
|
+
# @return [String]
|
|
363
|
+
def header_auth_env_key
|
|
364
|
+
name = options[:header_name] || "REMOTE_USER"
|
|
365
|
+
return name if (options[:header_auth_source] || :env).to_sym == :env
|
|
366
|
+
|
|
367
|
+
"HTTP_#{name.upcase.tr("-", "_")}"
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Warn operators that trusted header auth delegates authentication to the upstream gateway.
|
|
371
|
+
#
|
|
372
|
+
# @return [void]
|
|
373
|
+
def log_header_auth_warning
|
|
374
|
+
logger = OmniAuth.config.respond_to?(:logger) ? OmniAuth.config.logger : nil
|
|
375
|
+
return unless logger && logger.respond_to?(:warn)
|
|
376
|
+
|
|
377
|
+
logger.warn("[omniauth-ldap] SECURITY WARNING: header_auth is enabled. This trusts upstream authentication completely; only enable it behind a trusted proxy that strips client-supplied identity headers.")
|
|
378
|
+
end
|
|
379
|
+
|
|
205
380
|
# Perform a directory lookup for the given username using the strategy configuration
|
|
206
381
|
# (bind_dn/password or anonymous). Does not attempt to bind as the user.
|
|
382
|
+
#
|
|
383
|
+
# @param adaptor [OmniAuth::LDAP::Adaptor] initialized adaptor
|
|
384
|
+
# @param username [String] username to look up
|
|
385
|
+
# @return [Object, nil] first directory entry found or nil
|
|
207
386
|
def directory_lookup(adaptor, username)
|
|
208
387
|
entry = nil
|
|
209
388
|
search_filter = filter(adaptor, username)
|
|
@@ -216,6 +395,11 @@ module OmniAuth
|
|
|
216
395
|
|
|
217
396
|
# If the adaptor captured a Password Policy response control, expose a minimal, stable hash
|
|
218
397
|
# in the Rack env for applications to inspect.
|
|
398
|
+
#
|
|
399
|
+
# The structure is available at `request.env['omniauth.ldap.password_policy']`.
|
|
400
|
+
#
|
|
401
|
+
# @param adaptor [OmniAuth::LDAP::Adaptor]
|
|
402
|
+
# @return [void]
|
|
219
403
|
def attach_password_policy_env(adaptor)
|
|
220
404
|
return unless adaptor.respond_to?(:password_policy) && adaptor.password_policy
|
|
221
405
|
ctrl = adaptor.respond_to?(:last_password_policy_response) ? adaptor.last_password_policy_response : nil
|
|
@@ -226,6 +410,10 @@ module OmniAuth
|
|
|
226
410
|
end
|
|
227
411
|
|
|
228
412
|
# Best-effort extraction across net-ldap versions; if fields are not available, returns a raw payload.
|
|
413
|
+
#
|
|
414
|
+
# @param control [Object, nil] the password policy response control if available
|
|
415
|
+
# @param operation [Object, nil] the last operation result if available
|
|
416
|
+
# @return [Hash] normalized password policy info with keys :raw, :error, :time_before_expiration, :grace_authns_remaining, :oid, :operation
|
|
229
417
|
def extract_password_policy(control, operation)
|
|
230
418
|
data = {raw: control}
|
|
231
419
|
if control
|
|
@@ -10,12 +10,36 @@ require "sasl"
|
|
|
10
10
|
|
|
11
11
|
module OmniAuth
|
|
12
12
|
module LDAP
|
|
13
|
+
# Adaptor encapsulates the behavior required to connect to an LDAP server
|
|
14
|
+
# and perform searches and binds. It maps user-provided configuration into
|
|
15
|
+
# a Net::LDAP connection and provides compatibility helpers for different
|
|
16
|
+
# net-ldap and SASL versions. The adaptor is intentionally defensive and
|
|
17
|
+
# provides a small, stable API used by the OmniAuth strategy.
|
|
18
|
+
#
|
|
19
|
+
# @example Initialize with minimal config
|
|
20
|
+
# adaptor = OmniAuth::LDAP::Adaptor.new(base: 'dc=example,dc=com', host: 'ldap.example.com')
|
|
21
|
+
#
|
|
22
|
+
# @note Public API: {validate}, {initialize}, {bind_as}, and attr readers such as {connection}, {uid}
|
|
13
23
|
class Adaptor
|
|
24
|
+
# Generic adaptor error super-class
|
|
25
|
+
# @see Error classes that inherit from this class
|
|
14
26
|
class LdapError < StandardError; end
|
|
27
|
+
|
|
28
|
+
# Raised when configuration is invalid
|
|
29
|
+
# @example
|
|
30
|
+
# raise ConfigurationError, 'missing base'
|
|
15
31
|
class ConfigurationError < StandardError; end
|
|
32
|
+
|
|
33
|
+
# Raised when authentication fails
|
|
16
34
|
class AuthenticationError < StandardError; end
|
|
35
|
+
|
|
36
|
+
# Raised on connection-related failures
|
|
17
37
|
class ConnectionError < StandardError; end
|
|
18
38
|
|
|
39
|
+
# Valid configuration keys accepted by the adaptor. These correspond to
|
|
40
|
+
# the options supported by the gem and are used during initialization.
|
|
41
|
+
#
|
|
42
|
+
# @return [Array<Symbol>]
|
|
19
43
|
VALID_ADAPTER_CONFIGURATION_KEYS = [
|
|
20
44
|
:hosts,
|
|
21
45
|
:host,
|
|
@@ -42,7 +66,9 @@ module OmniAuth
|
|
|
42
66
|
:ssl_version,
|
|
43
67
|
]
|
|
44
68
|
|
|
45
|
-
#
|
|
69
|
+
# Required configuration keys. This may include alternatives as sub-lists
|
|
70
|
+
# (e.g., [:hosts, :host] means either key is acceptable).
|
|
71
|
+
# @return [Array]
|
|
46
72
|
MUST_HAVE_KEYS = [
|
|
47
73
|
:base,
|
|
48
74
|
[:encryption, :method], # :method is deprecated
|
|
@@ -51,6 +77,8 @@ module OmniAuth
|
|
|
51
77
|
[:uid, :filter],
|
|
52
78
|
]
|
|
53
79
|
|
|
80
|
+
# Supported encryption method mapping for configuration readability.
|
|
81
|
+
# @return [Hash<Symbol,Symbol,nil>]
|
|
54
82
|
ENCRYPTION_METHOD = {
|
|
55
83
|
simple_tls: :simple_tls,
|
|
56
84
|
start_tls: :start_tls,
|
|
@@ -62,21 +90,70 @@ module OmniAuth
|
|
|
62
90
|
tls: :start_tls,
|
|
63
91
|
}
|
|
64
92
|
|
|
93
|
+
# @!attribute [rw] bind_dn
|
|
94
|
+
# The distinguished name used for binding when provided in configuration.
|
|
95
|
+
# @return [String, nil]
|
|
96
|
+
# @!attribute [rw] password
|
|
97
|
+
# The bind password (may be nil for anonymous binds)
|
|
98
|
+
# @return [String, nil]
|
|
65
99
|
attr_accessor :bind_dn, :password
|
|
100
|
+
|
|
101
|
+
# Read-only attributes exposing connection and configuration state.
|
|
102
|
+
# @!attribute [r] connection
|
|
103
|
+
# The underlying Net::LDAP connection object.
|
|
104
|
+
# @return [Net::LDAP]
|
|
105
|
+
# @!attribute [r] uid
|
|
106
|
+
# The user id attribute used for lookups (e.g., 'sAMAccountName')
|
|
107
|
+
# @return [String]
|
|
108
|
+
# @!attribute [r] base
|
|
109
|
+
# The base DN for searches.
|
|
110
|
+
# @return [String]
|
|
111
|
+
# @!attribute [r] auth
|
|
112
|
+
# The final auth structure used by net-ldap.
|
|
113
|
+
# @return [Hash]
|
|
114
|
+
# @!attribute [r] filter
|
|
115
|
+
# Custom filter pattern when provided in configuration.
|
|
116
|
+
# @return [String, nil]
|
|
117
|
+
# @!attribute [r] password_policy
|
|
118
|
+
# Whether to request LDAP Password Policy controls.
|
|
119
|
+
# @return [Boolean]
|
|
120
|
+
# @!attribute [r] last_operation_result
|
|
121
|
+
# Last operation result object returned by the ldap library (if any)
|
|
122
|
+
# @return [Object, nil]
|
|
123
|
+
# @!attribute [r] last_password_policy_response
|
|
124
|
+
# Last extracted password policy response control (if any)
|
|
125
|
+
# @return [Object, nil]
|
|
66
126
|
attr_reader :connection, :uid, :base, :auth, :filter, :password_policy, :last_operation_result, :last_password_policy_response
|
|
67
127
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
128
|
+
# Validate that a minimal configuration is present. Raises ArgumentError when required
|
|
129
|
+
# keys are missing. This is a convenience to provide early feedback to callers.
|
|
130
|
+
#
|
|
131
|
+
# @param configuration [Hash] configuration hash passed to the adaptor
|
|
132
|
+
# @raise [ArgumentError] when required keys are missing
|
|
133
|
+
# @return [void]
|
|
134
|
+
class << self
|
|
135
|
+
def validate(configuration = {})
|
|
136
|
+
message = []
|
|
137
|
+
MUST_HAVE_KEYS.each do |names|
|
|
138
|
+
names = [names].flatten
|
|
139
|
+
missing_keys = names.select { |name| configuration[name].nil? }
|
|
140
|
+
if missing_keys == names
|
|
141
|
+
message << names.join(" or ")
|
|
142
|
+
end
|
|
75
143
|
end
|
|
144
|
+
raise ArgumentError.new(message.join(",") + " MUST be provided") unless message.empty?
|
|
76
145
|
end
|
|
77
|
-
raise ArgumentError.new(message.join(",") + " MUST be provided") unless message.empty?
|
|
78
146
|
end
|
|
79
147
|
|
|
148
|
+
# Create a new adaptor instance backed by a Net::LDAP connection.
|
|
149
|
+
#
|
|
150
|
+
# The constructor does not immediately open a network connection but
|
|
151
|
+
# prepares the Net::LDAP instance according to the provided configuration.
|
|
152
|
+
# It also applies timeout settings where supported by the installed net-ldap version.
|
|
153
|
+
#
|
|
154
|
+
# @param configuration [Hash] user-provided configuration options
|
|
155
|
+
# @raise [ArgumentError, ConfigurationError] on invalid configuration
|
|
156
|
+
# @return [OmniAuth::LDAP::Adaptor]
|
|
80
157
|
def initialize(configuration = {})
|
|
81
158
|
Adaptor.validate(configuration)
|
|
82
159
|
@configuration = configuration.dup
|
|
@@ -128,6 +205,16 @@ module OmniAuth
|
|
|
128
205
|
#:base => "dc=yourcompany, dc=com",
|
|
129
206
|
# :filter => "(mail=#{user})",
|
|
130
207
|
# :password => psw
|
|
208
|
+
#
|
|
209
|
+
# Attempt to locate a user entry and bind as that entry using the supplied
|
|
210
|
+
# password. Returns the entry on success, or false/nil on failure.
|
|
211
|
+
#
|
|
212
|
+
# @param args [Hash] search and bind options forwarded to net-ldap's search
|
|
213
|
+
# @option args [Net::LDAP::Filter,String] :filter LDAP filter to use
|
|
214
|
+
# @option args [Integer] :size maximum number of results to fetch
|
|
215
|
+
# @option args [String,Proc] :password a password string or callable returning a password
|
|
216
|
+
# @return [Net::LDAP::Entry, false, nil] the found entry on successful bind, otherwise false/nil
|
|
217
|
+
# @raise [ConnectionError] if the underlying LDAP search fails
|
|
131
218
|
def bind_as(args = {})
|
|
132
219
|
result = false
|
|
133
220
|
@last_operation_result = nil
|
|
@@ -179,6 +266,9 @@ module OmniAuth
|
|
|
179
266
|
|
|
180
267
|
private
|
|
181
268
|
|
|
269
|
+
# Build encryption options for Net::LDAP given the configured method
|
|
270
|
+
#
|
|
271
|
+
# @return [Hash, nil] encryption options or nil for plain (no encryption)
|
|
182
272
|
def encryption_options
|
|
183
273
|
translated_method = translate_method
|
|
184
274
|
return unless translated_method
|
|
@@ -189,6 +279,10 @@ module OmniAuth
|
|
|
189
279
|
}
|
|
190
280
|
end
|
|
191
281
|
|
|
282
|
+
# Normalize the user-provided encryption/method option and map to known values.
|
|
283
|
+
#
|
|
284
|
+
# @raise [ConfigurationError] when an unknown method is provided
|
|
285
|
+
# @return [Symbol, nil]
|
|
192
286
|
def translate_method
|
|
193
287
|
method = @encryption || @method
|
|
194
288
|
method ||= "plain"
|
|
@@ -203,6 +297,10 @@ module OmniAuth
|
|
|
203
297
|
ENCRYPTION_METHOD[normalized_method]
|
|
204
298
|
end
|
|
205
299
|
|
|
300
|
+
# Build TLS options including backward-compatibility for deprecated keys.
|
|
301
|
+
#
|
|
302
|
+
# @param translated_method [Symbol] the normalized encryption method
|
|
303
|
+
# @return [Hash] a hash suitable for passing as :tls_options
|
|
206
304
|
def tls_options(translated_method)
|
|
207
305
|
return {} if translated_method.nil? # (plain)
|
|
208
306
|
|
|
@@ -223,6 +321,10 @@ module OmniAuth
|
|
|
223
321
|
options
|
|
224
322
|
end
|
|
225
323
|
|
|
324
|
+
# Build a list of SASL auth structures for each requested mechanism.
|
|
325
|
+
#
|
|
326
|
+
# @param options [Hash] options such as :username and :password
|
|
327
|
+
# @return [Array<Hash>] list of auth structures
|
|
226
328
|
def sasl_auths(options = {})
|
|
227
329
|
auths = []
|
|
228
330
|
sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms
|
|
@@ -241,6 +343,9 @@ module OmniAuth
|
|
|
241
343
|
auths
|
|
242
344
|
end
|
|
243
345
|
|
|
346
|
+
# Prepare SASL DIGEST-MD5 bind details
|
|
347
|
+
# @param options [Hash]
|
|
348
|
+
# @return [Array] initial_credential and a challenge response proc
|
|
244
349
|
def sasl_bind_setup_digest_md5(options)
|
|
245
350
|
bind_dn = options[:username]
|
|
246
351
|
initial_credential = ""
|
|
@@ -253,6 +358,9 @@ module OmniAuth
|
|
|
253
358
|
[initial_credential, challenge_response]
|
|
254
359
|
end
|
|
255
360
|
|
|
361
|
+
# Prepare SASL GSS-SPNEGO bind details
|
|
362
|
+
# @param options [Hash]
|
|
363
|
+
# @return [Array] initial Type1 message and a nego proc
|
|
256
364
|
def sasl_bind_setup_gss_spnego(options)
|
|
257
365
|
bind_dn = options[:username]
|
|
258
366
|
psw = options[:password]
|
|
@@ -268,8 +376,9 @@ module OmniAuth
|
|
|
268
376
|
[Net::NTLM::Message::Type1.new.serialize, nego]
|
|
269
377
|
end
|
|
270
378
|
|
|
271
|
-
|
|
272
|
-
|
|
379
|
+
# Default TLS/OpenSSL options used when not explicitly configured.
|
|
380
|
+
#
|
|
381
|
+
# @return [Hash]
|
|
273
382
|
def default_options
|
|
274
383
|
if @disable_verify_certificates
|
|
275
384
|
# It is important to explicitly set verify_mode for two reasons:
|
|
@@ -286,6 +395,9 @@ module OmniAuth
|
|
|
286
395
|
#
|
|
287
396
|
# This gem may not always be in the context of Rails so we
|
|
288
397
|
# do this rather than `.blank?`.
|
|
398
|
+
#
|
|
399
|
+
# @param hash [Hash]
|
|
400
|
+
# @return [Hash] sanitized hash with blank values removed
|
|
289
401
|
def sanitize_hash_values(hash)
|
|
290
402
|
hash.delete_if do |_, value|
|
|
291
403
|
value.nil? ||
|
|
@@ -293,6 +405,10 @@ module OmniAuth
|
|
|
293
405
|
end
|
|
294
406
|
end
|
|
295
407
|
|
|
408
|
+
# Convert string keys to symbol keys for options hashes.
|
|
409
|
+
#
|
|
410
|
+
# @param hash [Hash]
|
|
411
|
+
# @return [Hash<Symbol, Object>]
|
|
296
412
|
def symbolize_hash_keys(hash)
|
|
297
413
|
hash.each_with_object({}) do |(key, value), result|
|
|
298
414
|
result[key.to_sym] = value
|
|
@@ -300,6 +416,12 @@ module OmniAuth
|
|
|
300
416
|
end
|
|
301
417
|
|
|
302
418
|
# Capture the operation result and extract any Password Policy response control if present.
|
|
419
|
+
#
|
|
420
|
+
# This method is defensive: if the server or the installed net-ldap gem doesn't
|
|
421
|
+
# support controls, the method will swallow errors and leave policy fields nil.
|
|
422
|
+
#
|
|
423
|
+
# @param conn [Net::LDAP]
|
|
424
|
+
# @return [void]
|
|
303
425
|
def capture_password_policy(conn)
|
|
304
426
|
return unless @password_policy
|
|
305
427
|
return unless conn.respond_to?(:get_operation_result)
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
module OmniAuth
|
|
2
2
|
module LDAP
|
|
3
|
+
# Version namespace for the omniauth-ldap gem
|
|
4
|
+
#
|
|
5
|
+
# This module contains the version constant used by rubygems and in code
|
|
6
|
+
# consumers. It intentionally exposes VERSION both inside the Version
|
|
7
|
+
# namespace and as OmniAuth::LDAP::VERSION for compatibility.
|
|
3
8
|
module Version
|
|
4
|
-
|
|
9
|
+
# Public semantic version for the gem
|
|
10
|
+
# @return [String]
|
|
11
|
+
VERSION = "2.3.4"
|
|
5
12
|
end
|
|
13
|
+
# Convenience constant for consumers that expect OmniAuth::LDAP::VERSION
|
|
14
|
+
# @return [String]
|
|
6
15
|
VERSION = Version::VERSION # Make VERSION available in traditional way
|
|
7
16
|
end
|
|
8
17
|
end
|
data/lib/omniauth-ldap.rb
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# Integrate the VersionGem helper into the OmniAuth::LDAP::Version module
|
|
2
|
+
# to expose common version-related helper methods. This file is the public
|
|
3
|
+
# entry point required by consumers of the gem.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# require 'omniauth-ldap'
|
|
7
|
+
# OmniAuth::LDAP::VERSION # => "2.3.2"
|
|
8
|
+
|
|
1
9
|
require "version_gem"
|
|
2
10
|
|
|
3
11
|
require "omniauth-ldap/version"
|
|
File without changes
|
|
File without changes
|
|
@@ -22,6 +22,12 @@ module OmniAuth
|
|
|
22
22
|
# Extract username from a trusted header when enabled
|
|
23
23
|
def header_username: () -> (String | nil)
|
|
24
24
|
|
|
25
|
+
def validate_header_auth_configuration!: () -> void
|
|
26
|
+
|
|
27
|
+
def header_auth_env_key: () -> String
|
|
28
|
+
|
|
29
|
+
def log_header_auth_warning: () -> void
|
|
30
|
+
|
|
25
31
|
# Perform a directory lookup for a given username; returns an Entry or nil
|
|
26
32
|
def directory_lookup: (OmniAuth::LDAP::Adaptor, String) -> untyped
|
|
27
33
|
|
data/sig/omniauth-ldap.rbs
CHANGED
|
File without changes
|
data/sig/rbs/net-ldap.rbs
CHANGED
|
File without changes
|
data/sig/rbs/net-ntlm.rbs
CHANGED
|
File without changes
|
data/sig/rbs/sasl.rbs
CHANGED
|
File without changes
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omniauth-ldap
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.3.
|
|
4
|
+
version: 2.3.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter Boling
|
|
@@ -337,34 +337,6 @@ dependencies:
|
|
|
337
337
|
- - ">="
|
|
338
338
|
- !ruby/object:Gem::Version
|
|
339
339
|
version: 1.0.3
|
|
340
|
-
- !ruby/object:Gem::Dependency
|
|
341
|
-
name: vcr
|
|
342
|
-
requirement: !ruby/object:Gem::Requirement
|
|
343
|
-
requirements:
|
|
344
|
-
- - ">="
|
|
345
|
-
- !ruby/object:Gem::Version
|
|
346
|
-
version: '4'
|
|
347
|
-
type: :development
|
|
348
|
-
prerelease: false
|
|
349
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
350
|
-
requirements:
|
|
351
|
-
- - ">="
|
|
352
|
-
- !ruby/object:Gem::Version
|
|
353
|
-
version: '4'
|
|
354
|
-
- !ruby/object:Gem::Dependency
|
|
355
|
-
name: webmock
|
|
356
|
-
requirement: !ruby/object:Gem::Requirement
|
|
357
|
-
requirements:
|
|
358
|
-
- - ">="
|
|
359
|
-
- !ruby/object:Gem::Version
|
|
360
|
-
version: '3'
|
|
361
|
-
type: :development
|
|
362
|
-
prerelease: false
|
|
363
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
364
|
-
requirements:
|
|
365
|
-
- - ">="
|
|
366
|
-
- !ruby/object:Gem::Version
|
|
367
|
-
version: '3'
|
|
368
340
|
description: "\U0001F4C1 LDAP strategy for OmniAuth."
|
|
369
341
|
email:
|
|
370
342
|
- floss@galtzo.com
|
|
@@ -408,10 +380,10 @@ licenses:
|
|
|
408
380
|
- MIT
|
|
409
381
|
metadata:
|
|
410
382
|
homepage_uri: https://omniauth-ldap.galtzo.com/
|
|
411
|
-
source_code_uri: https://github.com/omniauth/omniauth-ldap/tree/v2.3.
|
|
412
|
-
changelog_uri: https://github.com/omniauth/omniauth-ldap/blob/v2.3.
|
|
383
|
+
source_code_uri: https://github.com/omniauth/omniauth-ldap/tree/v2.3.4
|
|
384
|
+
changelog_uri: https://github.com/omniauth/omniauth-ldap/blob/v2.3.4/CHANGELOG.md
|
|
413
385
|
bug_tracker_uri: https://github.com/omniauth/omniauth-ldap/issues
|
|
414
|
-
documentation_uri: https://www.rubydoc.info/gems/omniauth-ldap/2.3.
|
|
386
|
+
documentation_uri: https://www.rubydoc.info/gems/omniauth-ldap/2.3.4
|
|
415
387
|
funding_uri: https://github.com/sponsors/pboling
|
|
416
388
|
wiki_uri: https://github.com/omniauth/omniauth-ldap/wiki
|
|
417
389
|
news_uri: https://www.railsbling.com/tags/omniauth-ldap
|
|
@@ -440,7 +412,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
440
412
|
- !ruby/object:Gem::Version
|
|
441
413
|
version: '0'
|
|
442
414
|
requirements: []
|
|
443
|
-
rubygems_version:
|
|
415
|
+
rubygems_version: 4.0.11
|
|
444
416
|
specification_version: 4
|
|
445
417
|
summary: "\U0001F4C1 LDAP strategy for OmniAuth."
|
|
446
418
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|