From 3430749d03a7d295a50a39ffcaf189a7c9c72b9b Mon Sep 17 00:00:00 2001 From: angel brown Date: Wed, 20 Jun 2012 15:28:14 -0400 Subject: [PATCH 1/5] changing callback_path to callback_url to take into account relative root url --- lib/omniauth/strategies/ldap.rb | 6 +++--- spec/omniauth/strategies/ldap_spec.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/omniauth/strategies/ldap.rb b/lib/omniauth/strategies/ldap.rb index a00e7e7..ccd9f49 100644 --- a/lib/omniauth/strategies/ldap.rb +++ b/lib/omniauth/strategies/ldap.rb @@ -57,18 +57,18 @@ def request_phase # Fast-path: if a trusted identity header is present, skip the login form # and jump to the callback where we will complete using directory lookup. if header_username - return Rack::Response.new([], 302, "Location" => callback_path).finish + return Rack::Response.new([], 302, "Location" => callback_url).finish end # If credentials were POSTed directly to /auth/:provider, redirect to the callback path. # This mirrors the behavior of many OmniAuth providers and allows test helpers (like # OmniAuth::Test::PhonySession) to populate `env['omniauth.auth']` on the callback request. if request.post? && request.params["username"].to_s != "" && request.params["password"].to_s != "" - return Rack::Response.new([], 302, "Location" => callback_path).finish + return Rack::Response.new([], 302, "Location" => callback_url).finish end OmniAuth::LDAP::Adaptor.validate(@options) - f = OmniAuth::Form.new(title: options[:title] || "LDAP Authentication", url: callback_path) + f = OmniAuth::Form.new(title: options[:title] || "LDAP Authentication", url: callback_url) f.text_field("Login", "username") f.password_field("Password", "password") f.button("Sign In") diff --git a/spec/omniauth/strategies/ldap_spec.rb b/spec/omniauth/strategies/ldap_spec.rb index bf2564f..93fb5e1 100644 --- a/spec/omniauth/strategies/ldap_spec.rb +++ b/spec/omniauth/strategies/ldap_spec.rb @@ -70,7 +70,7 @@ def make_env(path = "/auth/ldap", props = {}) end it "has the callback as the action for the form" do - expect(last_response.body).to include("action='/auth/ldap/callback'") + expect(last_response.body).to include("action='http://example.org/auth/ldap/callback'") end it "has a text field for each of the fields" do From 8d5c682b399f856023ba8b27c25eb974228a0559 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 5 Nov 2025 20:02:40 -0700 Subject: [PATCH 2/5] =?UTF-8?q?=E2=9C=A8=20Support=20for=20SCRIPT=5FNAME?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .rubocop_gradual.lock | 22 ++--- CHANGELOG.md | 4 + README.md | 75 ++++++++++++++++ docs/OmniAuth.html | 2 +- docs/OmniAuth/LDAP.html | 2 +- docs/OmniAuth/LDAP/Adaptor.html | 2 +- .../LDAP/Adaptor/AuthenticationError.html | 2 +- .../LDAP/Adaptor/ConfigurationError.html | 2 +- .../LDAP/Adaptor/ConnectionError.html | 2 +- docs/OmniAuth/LDAP/Adaptor/LdapError.html | 2 +- docs/OmniAuth/LDAP/Version.html | 2 +- docs/OmniAuth/Strategies.html | 2 +- docs/OmniAuth/Strategies/LDAP.html | 22 ++--- docs/_index.html | 8 +- docs/file.CHANGELOG.html | 11 ++- docs/file.CITATION.html | 2 +- docs/file.CODE_OF_CONDUCT.html | 2 +- docs/file.CONTRIBUTING.html | 2 +- docs/file.FUNDING.html | 2 +- docs/file.LICENSE.html | 2 +- docs/file.README.html | 85 ++++++++++++++++++- docs/file.REEK.html | 2 +- docs/file.RUBOCOP.html | 2 +- docs/file.SECURITY.html | 2 +- docs/file.adaptor.html | 2 +- docs/file.ldap.html | 2 +- docs/file.net-ldap.html | 2 +- docs/file.net-ntlm.html | 2 +- docs/file.omniauth-ldap-2.3.1.gem.html | 71 ++++++++++++++++ docs/file.omniauth-ldap.html | 2 +- docs/file.sasl.html | 2 +- docs/file.version.html | 2 +- docs/file_list.html | 10 +++ docs/index.html | 85 ++++++++++++++++++- docs/top-level-namespace.html | 2 +- lib/omniauth/strategies/ldap.rb | 11 +-- spec/integration/middleware_spec.rb | 16 ++++ spec/omniauth/strategies/ldap_spec.rb | 43 +++++++++- 38 files changed, 457 insertions(+), 56 deletions(-) create mode 100644 docs/file.omniauth-ldap-2.3.1.gem.html diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index bd5000d..f8d88ab 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -5,10 +5,10 @@ [114, 30, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806], [114, 37, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560] ], - "spec/integration/middleware_spec.rb:4062046892": [ + "spec/integration/middleware_spec.rb:4142891586": [ [3, 16, 39, "RSpec/DescribeClass: The first argument to describe should be the class or module being tested.", 638096201], [30, 14, 10, "RSpec/ExpectActual: Provide the actual value you are testing to `expect(...)`.", 837117997], - [65, 5, 317, "RSpec/LeakyConstantDeclaration: Stub class constant instead of declaring explicitly.", 424933157] + [81, 5, 317, "RSpec/LeakyConstantDeclaration: Stub class constant instead of declaring explicitly.", 424933157] ], "spec/integration/roda_integration_spec.rb:1921252381": [ [3, 16, 50, "RSpec/DescribeClass: The first argument to describe should be the class or module being tested.", 3681952328], @@ -30,14 +30,14 @@ [47, 7, 38, "RSpec/AnyInstance: Avoid stubbing using `allow_any_instance_of`.", 3627954156], [84, 7, 48, "RSpec/AnyInstance: Avoid stubbing using `allow_any_instance_of`.", 2759780562] ], - "spec/omniauth/strategies/ldap_spec.rb:783052937": [ - [93, 13, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1130140517], - [148, 17, 28, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3444838747], - [157, 17, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1584148894], - [168, 17, 32, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1515076977], - [177, 19, 19, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2526348694], - [203, 17, 56, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2413495789], - [218, 13, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3182939526], - [251, 15, 19, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2526348694] + "spec/omniauth/strategies/ldap_spec.rb:2044523926": [ + [120, 13, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1130140517], + [175, 17, 28, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3444838747], + [184, 17, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1584148894], + [195, 17, 32, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1515076977], + [204, 19, 19, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2526348694], + [230, 17, 56, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2413495789], + [245, 13, 9, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3182939526], + [278, 15, 19, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2526348694] ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index a488390..6bef234 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ Please file a bug if you notice a violation of semantic versioning. ### Added +- Support for SCRIPT_NAME for proper URL generation + - behind certain proxies/load balancers, or + - under a subdirectory + ### Changed ### Deprecated diff --git a/README.md b/README.md index f8d7bb6..b525090 100644 --- a/README.md +++ b/README.md @@ -401,6 +401,81 @@ provider :ldap, This trims `alice@example.com` to `alice` before searching. +### Mounted under a subdirectory (SCRIPT_NAME) + +If your app is served from a path prefix (for example, behind a reverse proxy at `/myapp`, or mounted via Rack::URLMap, or Rails `relative_url_root`), the OmniAuth callback must include that subdirectory. This strategy uses `callback_url` for the form action and redirects, so it automatically includes any `SCRIPT_NAME` set by Rack/Rails. In other words, you typically do not need any special configuration beyond ensuring `SCRIPT_NAME` is correct in the request environment. + +- Works out-of-the-box when: + - You mount the app at a path using Rack’s `map`/`URLMap`. + - You set Rails’ `config.relative_url_root` (or `RAILS_RELATIVE_URL_ROOT`) or deploy under a prefix with a reverse proxy that sets `SCRIPT_NAME`. + +Rack example (mounted at /myapp): + +```ruby +# config.ru +require "rack" +require "omniauth-ldap" + +app = Rack::Builder.new do + use(Rack::Session::Cookie, secret: "change_me") + use(OmniAuth::Builder) do + provider( + :ldap, + host: "ldap.example.com", + base: "dc=example,dc=com", + uid: "uid", + title: "Example LDAP", + ) + end + + run(->(env) { [404, {"Content-Type" => "text/plain"}, [env.key?("omniauth.auth").to_s]] }) +end + +run Rack::URLMap.new( + "/myapp" => app, +) +``` + +- Visiting `POST /myapp/auth/ldap` renders the login form with `action='http://host/myapp/auth/ldap/callback'`. +- Any redirects (including header-based SSO fast path) will also point to `http://host/myapp/auth/ldap/callback`. + +Rails example (relative_url_root): + +```ruby +# config/environments/production.rb (or an initializer) +Rails.application.configure do + config.relative_url_root = "/myapp" # or set ENV["RAILS_RELATIVE_URL_ROOT"] +end + +# config/initializers/omniauth.rb +Rails.application.config.middleware.use(OmniAuth::Builder) do + provider :ldap, + title: "Acme LDAP", + host: "ldap.acme.internal", + base: "dc=acme,dc=corp", + uid: "uid" +end +``` + +- With `relative_url_root` set, Rails/Rack provide `SCRIPT_NAME=/myapp`, and this strategy will issue a form with `action='.../myapp/auth/ldap/callback'` and redirect accordingly. + +Behind proxies with unusual host/proto handling (optional): + +OmniAuth usually derives the correct scheme/host/prefix from Rack (and standard `X-Forwarded-*` headers). If your environment produces incorrect absolute URLs, you can override the computed host and prefix by setting `OmniAuth.config.full_host`: + +```ruby +OmniAuth.config.full_host = lambda do |env| + scheme = (env["HTTP_X_FORWARDED_PROTO"] || env["rack.url_scheme"]).to_s.split(",").first + host = env["HTTP_X_FORWARDED_HOST"] || env["HTTP_HOST"] || [env["SERVER_NAME"], env["SERVER_PORT"]].compact.join(":") + script = env["SCRIPT_NAME"].to_s + "#{scheme}://#{host}#{script}" +end +``` + +Note: You generally do not need this override. Prefer configuring your proxy to pass standard `X-Forwarded-Proto` and `X-Forwarded-Host` headers and let Rack/OmniAuth compute the full URL. + +- Header-based SSO (`header_auth: true`) also respects `SCRIPT_NAME`; when a trusted header is present on `POST /myapp/auth/ldap`, the strategy redirects to `http://host/myapp/auth/ldap/callback`. + ### Trusted header SSO (REMOTE_USER and friends) Some deployments terminate SSO at a reverse proxy or portal and forward the already-authenticated user identity via an HTTP header such as `REMOTE_USER`. diff --git a/docs/OmniAuth.html b/docs/OmniAuth.html index acfb3ea..a62fd41 100644 --- a/docs/OmniAuth.html +++ b/docs/OmniAuth.html @@ -107,7 +107,7 @@

Defined Under Namespace

diff --git a/docs/OmniAuth/LDAP.html b/docs/OmniAuth/LDAP.html index 8487bea..345d15f 100644 --- a/docs/OmniAuth/LDAP.html +++ b/docs/OmniAuth/LDAP.html @@ -135,7 +135,7 @@

diff --git a/docs/OmniAuth/LDAP/Adaptor.html b/docs/OmniAuth/LDAP/Adaptor.html index 18be523..ef639b3 100644 --- a/docs/OmniAuth/LDAP/Adaptor.html +++ b/docs/OmniAuth/LDAP/Adaptor.html @@ -1036,7 +1036,7 @@

diff --git a/docs/OmniAuth/LDAP/Adaptor/AuthenticationError.html b/docs/OmniAuth/LDAP/Adaptor/AuthenticationError.html index e4a1d6a..741dd00 100644 --- a/docs/OmniAuth/LDAP/Adaptor/AuthenticationError.html +++ b/docs/OmniAuth/LDAP/Adaptor/AuthenticationError.html @@ -114,7 +114,7 @@ diff --git a/docs/OmniAuth/LDAP/Adaptor/ConfigurationError.html b/docs/OmniAuth/LDAP/Adaptor/ConfigurationError.html index 4e01047..5b84f08 100644 --- a/docs/OmniAuth/LDAP/Adaptor/ConfigurationError.html +++ b/docs/OmniAuth/LDAP/Adaptor/ConfigurationError.html @@ -114,7 +114,7 @@ diff --git a/docs/OmniAuth/LDAP/Adaptor/ConnectionError.html b/docs/OmniAuth/LDAP/Adaptor/ConnectionError.html index 796b8b0..532f5cc 100644 --- a/docs/OmniAuth/LDAP/Adaptor/ConnectionError.html +++ b/docs/OmniAuth/LDAP/Adaptor/ConnectionError.html @@ -114,7 +114,7 @@ diff --git a/docs/OmniAuth/LDAP/Adaptor/LdapError.html b/docs/OmniAuth/LDAP/Adaptor/LdapError.html index d528845..9a907d5 100644 --- a/docs/OmniAuth/LDAP/Adaptor/LdapError.html +++ b/docs/OmniAuth/LDAP/Adaptor/LdapError.html @@ -114,7 +114,7 @@ diff --git a/docs/OmniAuth/LDAP/Version.html b/docs/OmniAuth/LDAP/Version.html index 49fcb6c..c67a473 100644 --- a/docs/OmniAuth/LDAP/Version.html +++ b/docs/OmniAuth/LDAP/Version.html @@ -111,7 +111,7 @@

diff --git a/docs/OmniAuth/Strategies.html b/docs/OmniAuth/Strategies.html index 8c3ef0a..c5db66f 100644 --- a/docs/OmniAuth/Strategies.html +++ b/docs/OmniAuth/Strategies.html @@ -105,7 +105,7 @@

Defined Under Namespace

diff --git a/docs/OmniAuth/Strategies/LDAP.html b/docs/OmniAuth/Strategies/LDAP.html index 983a3db..bd39ec2 100644 --- a/docs/OmniAuth/Strategies/LDAP.html +++ b/docs/OmniAuth/Strategies/LDAP.html @@ -285,7 +285,6 @@

 
 
-133
 134
 135
 136
@@ -318,10 +317,11 @@ 

163 164 165 -166

+166 +167 -
# File 'lib/omniauth/strategies/ldap.rb', line 133
+      
# File 'lib/omniauth/strategies/ldap.rb', line 134
 
 def map_user(mapper, object)
   user = {}
@@ -482,15 +482,17 @@ 

117 118 119 -120

+120 +121
# File 'lib/omniauth/strategies/ldap.rb', line 113
 
 def filter(adaptor, username_override = nil)
-  if adaptor.filter && !adaptor.filter.empty?
+  flt = adaptor.filter
+  if flt && !flt.to_s.empty?
     username = Net::LDAP::Filter.escape(@options[:name_proc].call(username_override || request.params["username"]))
-    Net::LDAP::Filter.construct(adaptor.filter % {username: username})
+    Net::LDAP::Filter.construct(flt % {username: username})
   else
     Net::LDAP::Filter.equals(adaptor.uid, @options[:name_proc].call(username_override || request.params["username"]))
   end
@@ -556,18 +558,18 @@ 

# Fast-path: if a trusted identity header is present, skip the login form # and jump to the callback where we will complete using directory lookup. if header_username - return Rack::Response.new([], 302, "Location" => callback_path).finish + return Rack::Response.new([], 302, "Location" => callback_url).finish end # If credentials were POSTed directly to /auth/:provider, redirect to the callback path. # This mirrors the behavior of many OmniAuth providers and allows test helpers (like # OmniAuth::Test::PhonySession) to populate `env['omniauth.auth']` on the callback request. if request.post? && request.params["username"].to_s != "" && request.params["password"].to_s != "" - return Rack::Response.new([], 302, "Location" => callback_path).finish + return Rack::Response.new([], 302, "Location" => callback_url).finish end OmniAuth::LDAP::Adaptor.validate(@options) - f = OmniAuth::Form.new(title: options[:title] || "LDAP Authentication", url: callback_path) + f = OmniAuth::Form.new(title: options[:title] || "LDAP Authentication", url: callback_url) f.text_field("Login", "username") f.password_field("Password", "password") f.button("Sign In") @@ -583,7 +585,7 @@

diff --git a/docs/_index.html b/docs/_index.html index 9f12b79..344bc7f 100644 --- a/docs/_index.html +++ b/docs/_index.html @@ -87,6 +87,12 @@

File Listing

  • CITATION
  • +
  • omniauth-ldap-2.3.1.gem
  • + + +
  • omniauth-ldap-2.3.1.gem
  • + +
  • REEK
  • @@ -248,7 +254,7 @@

    Namespace Listing A-Z

    diff --git a/docs/file.CHANGELOG.html b/docs/file.CHANGELOG.html index 5b8253d..68adc67 100644 --- a/docs/file.CHANGELOG.html +++ b/docs/file.CHANGELOG.html @@ -74,6 +74,15 @@

    Added

    +
      +
    • Support for SCRIPT_NAME for proper URL generation +
        +
      • behind certain proxies/load balancers, or
      • +
      • under a subdirectory
      • +
      +
    • +
    +

    Changed

    Deprecated

    @@ -284,7 +293,7 @@

    diff --git a/docs/file.CITATION.html b/docs/file.CITATION.html index 5a62985..a0f652b 100644 --- a/docs/file.CITATION.html +++ b/docs/file.CITATION.html @@ -82,7 +82,7 @@ diff --git a/docs/file.CODE_OF_CONDUCT.html b/docs/file.CODE_OF_CONDUCT.html index 0bfd65a..6e8b968 100644 --- a/docs/file.CODE_OF_CONDUCT.html +++ b/docs/file.CODE_OF_CONDUCT.html @@ -191,7 +191,7 @@

    Attribution

    diff --git a/docs/file.CONTRIBUTING.html b/docs/file.CONTRIBUTING.html index bad3f60..c25b68f 100644 --- a/docs/file.CONTRIBUTING.html +++ b/docs/file.CONTRIBUTING.html @@ -295,7 +295,7 @@

    Manual process

    diff --git a/docs/file.FUNDING.html b/docs/file.FUNDING.html index 0cf42e0..fcef94f 100644 --- a/docs/file.FUNDING.html +++ b/docs/file.FUNDING.html @@ -104,7 +104,7 @@

    Another Way to Support Open diff --git a/docs/file.LICENSE.html b/docs/file.LICENSE.html index 836550a..457a3ab 100644 --- a/docs/file.LICENSE.html +++ b/docs/file.LICENSE.html @@ -60,7 +60,7 @@
    MIT License

    Copyright (c) 2025 Peter H. Boling, and omniauth-ldap contributors
    Copyright (c) 2011 by Ping Yu and Intridea, Inc.

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    diff --git a/docs/file.README.html b/docs/file.README.html index faddfcc..f747a0f 100644 --- a/docs/file.README.html +++ b/docs/file.README.html @@ -567,6 +567,89 @@

    Name processing and examples

    This trims alice@example.com to alice before searching.

    +

    Mounted under a subdirectory (SCRIPT_NAME)

    + +

    If your app is served from a path prefix (for example, behind a reverse proxy at /myapp, or mounted via Rack::URLMap, or Rails relative_url_root), the OmniAuth callback must include that subdirectory. This strategy uses callback_url for the form action and redirects, so it automatically includes any SCRIPT_NAME set by Rack/Rails. In other words, you typically do not need any special configuration beyond ensuring SCRIPT_NAME is correct in the request environment.

    + +
      +
    • Works out-of-the-box when: +
        +
      • You mount the app at a path using Rack’s map/URLMap.
      • +
      • You set Rails’ config.relative_url_root (or RAILS_RELATIVE_URL_ROOT) or deploy under a prefix with a reverse proxy that sets SCRIPT_NAME.
      • +
      +
    • +
    + +

    Rack example (mounted at /myapp):

    + +
    # config.ru
    +require "rack"
    +require "omniauth-ldap"
    +
    +app = Rack::Builder.new do
    +  use(Rack::Session::Cookie, secret: "change_me")
    +  use(OmniAuth::Builder) do
    +    provider(
    +      :ldap,
    +      host: "ldap.example.com",
    +      base: "dc=example,dc=com",
    +      uid: "uid",
    +      title: "Example LDAP",
    +    )
    +  end
    +
    +  run(->(env) { [404, {"Content-Type" => "text/plain"}, [env.key?("omniauth.auth").to_s]] })
    +end
    +
    +run Rack::URLMap.new(
    +  "/myapp" => app,
    +)
    +
    + +
      +
    • Visiting POST /myapp/auth/ldap renders the login form with action='http://host/myapp/auth/ldap/callback'.
    • +
    • Any redirects (including header-based SSO fast path) will also point to http://host/myapp/auth/ldap/callback.
    • +
    + +

    Rails example (relative_url_root):

    + +
    # config/environments/production.rb (or an initializer)
    +Rails.application.configure do
    +  config.relative_url_root = "/myapp"  # or set ENV["RAILS_RELATIVE_URL_ROOT"]
    +end
    +
    +# config/initializers/omniauth.rb
    +Rails.application.config.middleware.use(OmniAuth::Builder) do
    +  provider :ldap,
    +    title: "Acme LDAP",
    +    host: "ldap.acme.internal",
    +    base: "dc=acme,dc=corp",
    +    uid: "uid"
    +end
    +
    + +
      +
    • With relative_url_root set, Rails/Rack provide SCRIPT_NAME=/myapp, and this strategy will issue a form with action='.../myapp/auth/ldap/callback' and redirect accordingly.
    • +
    + +

    Behind proxies with unusual host/proto handling (optional):

    + +

    OmniAuth usually derives the correct scheme/host/prefix from Rack (and standard X-Forwarded-* headers). If your environment produces incorrect absolute URLs, you can override the computed host and prefix by setting OmniAuth.config.full_host:

    + +
    OmniAuth.config.full_host = lambda do |env|
    +  scheme = (env["HTTP_X_FORWARDED_PROTO"] || env["rack.url_scheme"]).to_s.split(",").first
    +  host = env["HTTP_X_FORWARDED_HOST"] || env["HTTP_HOST"] || [env["SERVER_NAME"], env["SERVER_PORT"]].compact.join(":")
    +  script = env["SCRIPT_NAME"].to_s
    +  "#{scheme}://#{host}#{script}"
    +end
    +
    + +

    Note: You generally do not need this override. Prefer configuring your proxy to pass standard X-Forwarded-Proto and X-Forwarded-Host headers and let Rack/OmniAuth compute the full URL.

    + +
      +
    • Header-based SSO (header_auth: true) also respects SCRIPT_NAME; when a trusted header is present on POST /myapp/auth/ldap, the strategy redirects to http://host/myapp/auth/ldap/callback.
    • +
    +

    Trusted header SSO (REMOTE_USER and friends)

    Some deployments terminate SSO at a reverse proxy or portal and forward the already-authenticated user identity via an HTTP header such as REMOTE_USER.
    @@ -814,7 +897,7 @@

    Please give the project a star ⭐ ♥ diff --git a/docs/file.REEK.html b/docs/file.REEK.html index db96dc8..cbbef16 100644 --- a/docs/file.REEK.html +++ b/docs/file.REEK.html @@ -61,7 +61,7 @@ diff --git a/docs/file.RUBOCOP.html b/docs/file.RUBOCOP.html index 0ea6cfc..535c4d0 100644 --- a/docs/file.RUBOCOP.html +++ b/docs/file.RUBOCOP.html @@ -161,7 +161,7 @@

    Benefits of rubocop_gradual

    diff --git a/docs/file.SECURITY.html b/docs/file.SECURITY.html index 93f628e..282d6cd 100644 --- a/docs/file.SECURITY.html +++ b/docs/file.SECURITY.html @@ -91,7 +91,7 @@

    Additional Support

    diff --git a/docs/file.adaptor.html b/docs/file.adaptor.html index aa339f2..ffab603 100644 --- a/docs/file.adaptor.html +++ b/docs/file.adaptor.html @@ -113,7 +113,7 @@ diff --git a/docs/file.ldap.html b/docs/file.ldap.html index 480a0d9..80cb27a 100644 --- a/docs/file.ldap.html +++ b/docs/file.ldap.html @@ -91,7 +91,7 @@ diff --git a/docs/file.net-ldap.html b/docs/file.net-ldap.html index cd043ae..d5781b4 100644 --- a/docs/file.net-ldap.html +++ b/docs/file.net-ldap.html @@ -78,7 +78,7 @@ diff --git a/docs/file.net-ntlm.html b/docs/file.net-ntlm.html index 9e05759..beea2ad 100644 --- a/docs/file.net-ntlm.html +++ b/docs/file.net-ntlm.html @@ -74,7 +74,7 @@ diff --git a/docs/file.omniauth-ldap-2.3.1.gem.html b/docs/file.omniauth-ldap-2.3.1.gem.html new file mode 100644 index 0000000..114d84a --- /dev/null +++ b/docs/file.omniauth-ldap-2.3.1.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: omniauth-ldap-2.3.1.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    69f8474644ce03850236011fe6579aca167b4fbaf69bdcbea648b3000737c7e46dcb0b63f61d6c4e045b138110187dec55941c5f56b2c8438df63ee472807813

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.omniauth-ldap.html b/docs/file.omniauth-ldap.html index a9ca408..3f250e0 100644 --- a/docs/file.omniauth-ldap.html +++ b/docs/file.omniauth-ldap.html @@ -65,7 +65,7 @@

    Th diff --git a/docs/file.sasl.html b/docs/file.sasl.html index 0e6e571..a015996 100644 --- a/docs/file.sasl.html +++ b/docs/file.sasl.html @@ -71,7 +71,7 @@ diff --git a/docs/file.version.html b/docs/file.version.html index 225e243..b5fd981 100644 --- a/docs/file.version.html +++ b/docs/file.version.html @@ -69,7 +69,7 @@ diff --git a/docs/file_list.html b/docs/file_list.html index fcada38..ec1fd71 100644 --- a/docs/file_list.html +++ b/docs/file_list.html @@ -92,6 +92,16 @@

    File List

    +
  • + +
  • + + +
  • + +
  • + +
  • diff --git a/docs/index.html b/docs/index.html index cdc8c27..be9533c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -567,6 +567,89 @@

    Name processing and examples

    This trims alice@example.com to alice before searching.

    +

    Mounted under a subdirectory (SCRIPT_NAME)

    + +

    If your app is served from a path prefix (for example, behind a reverse proxy at /myapp, or mounted via Rack::URLMap, or Rails relative_url_root), the OmniAuth callback must include that subdirectory. This strategy uses callback_url for the form action and redirects, so it automatically includes any SCRIPT_NAME set by Rack/Rails. In other words, you typically do not need any special configuration beyond ensuring SCRIPT_NAME is correct in the request environment.

    + +
      +
    • Works out-of-the-box when: +
        +
      • You mount the app at a path using Rack’s map/URLMap.
      • +
      • You set Rails’ config.relative_url_root (or RAILS_RELATIVE_URL_ROOT) or deploy under a prefix with a reverse proxy that sets SCRIPT_NAME.
      • +
      +
    • +
    + +

    Rack example (mounted at /myapp):

    + +
    # config.ru
    +require "rack"
    +require "omniauth-ldap"
    +
    +app = Rack::Builder.new do
    +  use(Rack::Session::Cookie, secret: "change_me")
    +  use(OmniAuth::Builder) do
    +    provider(
    +      :ldap,
    +      host: "ldap.example.com",
    +      base: "dc=example,dc=com",
    +      uid: "uid",
    +      title: "Example LDAP",
    +    )
    +  end
    +
    +  run(->(env) { [404, {"Content-Type" => "text/plain"}, [env.key?("omniauth.auth").to_s]] })
    +end
    +
    +run Rack::URLMap.new(
    +  "/myapp" => app,
    +)
    +
    + +
      +
    • Visiting POST /myapp/auth/ldap renders the login form with action='http://host/myapp/auth/ldap/callback'.
    • +
    • Any redirects (including header-based SSO fast path) will also point to http://host/myapp/auth/ldap/callback.
    • +
    + +

    Rails example (relative_url_root):

    + +
    # config/environments/production.rb (or an initializer)
    +Rails.application.configure do
    +  config.relative_url_root = "/myapp"  # or set ENV["RAILS_RELATIVE_URL_ROOT"]
    +end
    +
    +# config/initializers/omniauth.rb
    +Rails.application.config.middleware.use(OmniAuth::Builder) do
    +  provider :ldap,
    +    title: "Acme LDAP",
    +    host: "ldap.acme.internal",
    +    base: "dc=acme,dc=corp",
    +    uid: "uid"
    +end
    +
    + +
      +
    • With relative_url_root set, Rails/Rack provide SCRIPT_NAME=/myapp, and this strategy will issue a form with action='.../myapp/auth/ldap/callback' and redirect accordingly.
    • +
    + +

    Behind proxies with unusual host/proto handling (optional):

    + +

    OmniAuth usually derives the correct scheme/host/prefix from Rack (and standard X-Forwarded-* headers). If your environment produces incorrect absolute URLs, you can override the computed host and prefix by setting OmniAuth.config.full_host:

    + +
    OmniAuth.config.full_host = lambda do |env|
    +  scheme = (env["HTTP_X_FORWARDED_PROTO"] || env["rack.url_scheme"]).to_s.split(",").first
    +  host = env["HTTP_X_FORWARDED_HOST"] || env["HTTP_HOST"] || [env["SERVER_NAME"], env["SERVER_PORT"]].compact.join(":")
    +  script = env["SCRIPT_NAME"].to_s
    +  "#{scheme}://#{host}#{script}"
    +end
    +
    + +

    Note: You generally do not need this override. Prefer configuring your proxy to pass standard X-Forwarded-Proto and X-Forwarded-Host headers and let Rack/OmniAuth compute the full URL.

    + +
      +
    • Header-based SSO (header_auth: true) also respects SCRIPT_NAME; when a trusted header is present on POST /myapp/auth/ldap, the strategy redirects to http://host/myapp/auth/ldap/callback.
    • +
    +

    Trusted header SSO (REMOTE_USER and friends)

    Some deployments terminate SSO at a reverse proxy or portal and forward the already-authenticated user identity via an HTTP header such as REMOTE_USER.
    @@ -814,7 +897,7 @@

    Please give the project a star ⭐ ♥ diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html index fc1ae00..1df7fce 100644 --- a/docs/top-level-namespace.html +++ b/docs/top-level-namespace.html @@ -100,7 +100,7 @@

    Defined Under Namespace

    diff --git a/lib/omniauth/strategies/ldap.rb b/lib/omniauth/strategies/ldap.rb index ccd9f49..5ec29fa 100644 --- a/lib/omniauth/strategies/ldap.rb +++ b/lib/omniauth/strategies/ldap.rb @@ -111,9 +111,10 @@ def callback_phase end def filter(adaptor, username_override = nil) - if adaptor.filter && !adaptor.filter.empty? + flt = adaptor.filter + if flt && !flt.to_s.empty? username = Net::LDAP::Filter.escape(@options[:name_proc].call(username_override || request.params["username"])) - Net::LDAP::Filter.construct(adaptor.filter % {username: username}) + Net::LDAP::Filter.construct(flt % {username: username}) else Net::LDAP::Filter.equals(adaptor.uid, @options[:name_proc].call(username_override || request.params["username"])) end @@ -174,7 +175,7 @@ def valid_request_method? def missing_credentials? request.params["username"].nil? || request.params["username"].empty? || request.params["password"].nil? || request.params["password"].empty? - end # missing_credentials? + end # Extract a normalized username from a trusted header when enabled. # Returns nil when not configured or not present. @@ -193,9 +194,9 @@ def header_username # (bind_dn/password or anonymous). Does not attempt to bind as the user. def directory_lookup(adaptor, username) entry = nil - filter = filter(adaptor, username) + search_filter = filter(adaptor, username) adaptor.connection.open do |conn| - rs = conn.search(filter: filter, size: 1) + rs = conn.search(filter: search_filter, size: 1) entry = rs.first if rs && rs.first end entry diff --git a/spec/integration/middleware_spec.rb b/spec/integration/middleware_spec.rb index c812134..2ccfc0c 100644 --- a/spec/integration/middleware_spec.rb +++ b/spec/integration/middleware_spec.rb @@ -61,6 +61,22 @@ end end + it "honors SCRIPT_NAME when mounted under a subdirectory for redirect to callback" do + begin + OmniAuth.config.test_mode = true + OmniAuth.config.mock_auth[:ldap] = OmniAuth::AuthHash.new(provider: "ldap", uid: "bob", info: {"name" => "Bob"}) + + # Simulate subdirectory mount by setting SCRIPT_NAME and posting credentials to request phase + env = {"SCRIPT_NAME" => "/subdir"} + post "/auth/ldap", {"username" => "bob", "password" => "secret"}, env + expect(last_response.status).to eq 302 + expect(last_response.headers["Location"]).to eq "http://example.org/subdir/auth/ldap/callback" + ensure + OmniAuth.config.mock_auth.delete(:ldap) + OmniAuth.config.test_mode = false + end + end + unless defined?(TestCallbackSetter) class TestCallbackSetter def initialize(app) diff --git a/spec/omniauth/strategies/ldap_spec.rb b/spec/omniauth/strategies/ldap_spec.rb index 93fb5e1..e65160b 100644 --- a/spec/omniauth/strategies/ldap_spec.rb +++ b/spec/omniauth/strategies/ldap_spec.rb @@ -80,6 +80,33 @@ def make_env(path = "/auth/ldap", props = {}) it "has a label of the form title" do expect(last_response.body.scan("MyLdap Form").size).to be > 1 end + + context "when mounted under a subdirectory" do + let(:sub_env) do + make_env("/auth/ldap", { + "SCRIPT_NAME" => "/subdirectory", + "rack.session" => {csrf: csrf_token}, + "rack.input" => StringIO.new("authenticity_token=#{escaped_token}"), + }) + end + + it "renders form with full callback_url including subdirectory" do + post "/auth/ldap", nil, sub_env + expect(last_response.status).to eq 200 + expect(last_response.body).to include("action='http://example.org/subdirectory/auth/ldap/callback'") + end + + it "renders form with full callback_url including nested subdirectory" do + nested_env = make_env("/auth/ldap", { + "SCRIPT_NAME" => "/nested/app", + "rack.session" => {csrf: csrf_token}, + "rack.input" => StringIO.new("authenticity_token=#{escaped_token}"), + }) + post "/auth/ldap", nil, nested_env + expect(last_response.status).to eq 200 + expect(last_response.body).to include("action='http://example.org/nested/app/auth/ldap/callback'") + end + end end describe "post /auth/ldap/callback" do @@ -434,7 +461,21 @@ def connection_returning(entry) env = {"rack.session" => {}, "REQUEST_METHOD" => "POST", "PATH_INFO" => "/auth/ldap", "REMOTE_USER" => "alice"} post "/auth/ldap", nil, env expect(last_response).to be_redirect - expect(last_response.headers["Location"]).to eq "/auth/ldap/callback" + expect(last_response.headers["Location"]).to eq "http://example.org/auth/ldap/callback" + end + + it "redirects including subdirectory when header present and app is mounted under a subdirectory" do + env = {"rack.session" => {}, "REQUEST_METHOD" => "POST", "PATH_INFO" => "/auth/ldap", "SCRIPT_NAME" => "/subdir", "REMOTE_USER" => "alice"} + post "/auth/ldap", nil, env + expect(last_response).to be_redirect + expect(last_response.headers["Location"]).to eq "http://example.org/subdir/auth/ldap/callback" + end + + it "redirects including nested subdirectory when header present and app is mounted under a nested subdirectory" do + env = {"rack.session" => {}, "REQUEST_METHOD" => "POST", "PATH_INFO" => "/auth/ldap", "SCRIPT_NAME" => "/nested/app", "REMOTE_USER" => "alice"} + post "/auth/ldap", nil, env + expect(last_response).to be_redirect + expect(last_response.headers["Location"]).to eq "http://example.org/nested/app/auth/ldap/callback" end it "authenticates on callback without password using REMOTE_USER" do From 6fb160e328e99392e20ed2f9cc60f165445fc720 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 5 Nov 2025 20:24:49 -0700 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=91=B7=20Add=20more=20appraisals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - test against all minor versions of omniauth --- .github/workflows/ancient.yml | 51 ++++++++++++++++++- Appraisals | 46 ++++++++++++++++- gemfiles/ruby_2_3_omni_v1.0.gemfile | 11 ++++ ...2_3.gemfile => ruby_2_3_omni_v1.1.gemfile} | 0 gemfiles/ruby_2_3_omni_v1.2.gemfile | 11 ++++ gemfiles/ruby_2_3_omni_v1.3.gemfile | 11 ++++ gemfiles/ruby_2_3_omni_v1.4.gemfile | 11 ++++ gemfiles/ruby_2_3_omni_v1.5.gemfile | 11 ++++ gemfiles/ruby_2_3_omni_v1.6.gemfile | 11 ++++ gemfiles/ruby_2_3_omni_v1.7.gemfile | 11 ++++ gemfiles/ruby_2_4.gemfile | 2 +- 11 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 gemfiles/ruby_2_3_omni_v1.0.gemfile rename gemfiles/{ruby_2_3.gemfile => ruby_2_3_omni_v1.1.gemfile} (100%) create mode 100644 gemfiles/ruby_2_3_omni_v1.2.gemfile create mode 100644 gemfiles/ruby_2_3_omni_v1.3.gemfile create mode 100644 gemfiles/ruby_2_3_omni_v1.4.gemfile create mode 100644 gemfiles/ruby_2_3_omni_v1.5.gemfile create mode 100644 gemfiles/ruby_2_3_omni_v1.6.gemfile create mode 100644 gemfiles/ruby_2_3_omni_v1.7.gemfile diff --git a/.github/workflows/ancient.yml b/.github/workflows/ancient.yml index 3cc6e37..bd2ad10 100644 --- a/.github/workflows/ancient.yml +++ b/.github/workflows/ancient.yml @@ -36,7 +36,56 @@ jobs: include: # Ruby 2.3 - ruby: "ruby-2.3" - appraisal: "ruby-2-3" + appraisal: "ruby-2-3-omni-v1.0" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.1" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.2" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.3" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.4" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.5" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.6" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.7" exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: "3.3.27" diff --git a/Appraisals b/Appraisals index 27b567b..49caaa7 100644 --- a/Appraisals +++ b/Appraisals @@ -56,14 +56,56 @@ appraise "dep-heads" do eval_gemfile "modular/runtime_heads.gemfile" end -appraise "ruby-2-3" do +appraise "ruby-2-3-omni-v1.0" do + eval_gemfile "modular/omniauth/r2/v1.0.gemfile" + eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-3-omni-v1.1" do eval_gemfile "modular/omniauth/r2/v1.1.gemfile" eval_gemfile "modular/rack/r2.1/v1.6.gemfile" eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" end -appraise "ruby-2-4" do +appraise "ruby-2-3-omni-v1.2" do + eval_gemfile "modular/omniauth/r2/v1.2.gemfile" + eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-3-omni-v1.3" do + eval_gemfile "modular/omniauth/r2/v1.3.gemfile" + eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-3-omni-v1.4" do + eval_gemfile "modular/omniauth/r2/v1.4.gemfile" + eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-3-omni-v1.5" do eval_gemfile "modular/omniauth/r2/v1.5.gemfile" + eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-3-omni-v1.6" do + eval_gemfile "modular/omniauth/r2/v1.6.gemfile" + eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-3-omni-v1.7" do + eval_gemfile "modular/omniauth/r2/v1.7.gemfile" + eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-4" do + eval_gemfile "modular/omniauth/r2/v1.8.gemfile" eval_gemfile "modular/rack/r2.3/v2.1.gemfile" eval_gemfile "modular/x_std_libs/r2.4/libs.gemfile" end diff --git a/gemfiles/ruby_2_3_omni_v1.0.gemfile b/gemfiles/ruby_2_3_omni_v1.0.gemfile new file mode 100644 index 0000000..05416ec --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.0.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.0.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3.gemfile b/gemfiles/ruby_2_3_omni_v1.1.gemfile similarity index 100% rename from gemfiles/ruby_2_3.gemfile rename to gemfiles/ruby_2_3_omni_v1.1.gemfile diff --git a/gemfiles/ruby_2_3_omni_v1.2.gemfile b/gemfiles/ruby_2_3_omni_v1.2.gemfile new file mode 100644 index 0000000..3d4e5aa --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.2.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.2.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.3.gemfile b/gemfiles/ruby_2_3_omni_v1.3.gemfile new file mode 100644 index 0000000..321ede0 --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.3.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.3.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.4.gemfile b/gemfiles/ruby_2_3_omni_v1.4.gemfile new file mode 100644 index 0000000..5ee8d66 --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.4.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.4.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.5.gemfile b/gemfiles/ruby_2_3_omni_v1.5.gemfile new file mode 100644 index 0000000..a0ea50c --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.5.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.5.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.6.gemfile b/gemfiles/ruby_2_3_omni_v1.6.gemfile new file mode 100644 index 0000000..7a8ac6c --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.6.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.6.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.7.gemfile b/gemfiles/ruby_2_3_omni_v1.7.gemfile new file mode 100644 index 0000000..f812070 --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.7.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.7.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_4.gemfile b/gemfiles/ruby_2_4.gemfile index b4bc15f..8b40eb9 100644 --- a/gemfiles/ruby_2_4.gemfile +++ b/gemfiles/ruby_2_4.gemfile @@ -4,7 +4,7 @@ source "https://gem.coop" gemspec path: "../" -eval_gemfile("modular/omniauth/r2/v1.5.gemfile") +eval_gemfile("modular/omniauth/r2/v1.8.gemfile") eval_gemfile("modular/rack/r2.3/v2.1.gemfile") From 677ba9f8b25b32a28c9d8b195f7913853bf3255c Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 5 Nov 2025 20:26:17 -0700 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=92=B8=20There=20is=20no=20opencollec?= =?UTF-8?q?tive=20for=20omniauth=20(yet)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/opencollective.yml | 40 ---------------------------- 1 file changed, 40 deletions(-) delete mode 100644 .github/workflows/opencollective.yml diff --git a/.github/workflows/opencollective.yml b/.github/workflows/opencollective.yml deleted file mode 100644 index 6122df4..0000000 --- a/.github/workflows/opencollective.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Open Collective Backers - -on: - schedule: - # Run once a week on Sunday at 12:00 AM UTC - - cron: '0 0 * * 0' - workflow_dispatch: - -permissions: - contents: write - -jobs: - update-backers: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false - - name: Setup Ruby & RubyGems - uses: ruby/setup-ruby@v1 - with: - ruby-version: ruby - rubygems: default - bundler: default - bundler-cache: true - - - name: README Update - env: - # Keep GITHUB_TOKEN for any tools/scripts expecting it, mapped to the same secret - GITHUB_TOKEN: ${{ secrets.README_UPDATER_TOKEN }} - README_UPDATER_TOKEN: ${{ secrets.README_UPDATER_TOKEN }} - REPO: ${{ github.repository }} - run: | - git config user.name 'autobolt' - git config user.email 'autobots@9thbit.net' - # Use the configured token for authenticated pushes - git remote set-url origin "https://x-access-token:${README_UPDATER_TOKEN}@github.com/${REPO}.git" - bin/kettle-readme-backers - # Push back to the same branch/ref that triggered the workflow (default branch for schedule) - git push origin HEAD From 3ea1562004f1e7323acd199d07995471c8c232ec Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 5 Nov 2025 20:37:43 -0700 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=91=B7=20Add=20more=20appraisals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - test against all minor versions of rack --- .github/workflows/ancient.yml | 21 +++++++------------ Appraisals | 28 ++++++++++--------------- CHANGELOG.md | 3 +++ Gemfile.lock | 2 +- gemfiles/modular/rack/r2.1/v1.0.gemfile | 1 + gemfiles/modular/rack/r2.1/v1.1.gemfile | 1 + gemfiles/modular/rack/r2.1/v1.2.gemfile | 1 + gemfiles/modular/rack/r2.1/v1.3.gemfile | 1 + gemfiles/modular/rack/r2.1/v1.4.gemfile | 1 + gemfiles/modular/rack/r2.1/v1.5.gemfile | 1 + gemfiles/ruby_2_3_omni_v1.2.gemfile | 2 +- gemfiles/ruby_2_3_omni_v1.3.gemfile | 2 +- gemfiles/ruby_2_3_omni_v1.4.gemfile | 2 +- gemfiles/ruby_2_3_omni_v1.5.gemfile | 2 +- gemfiles/ruby_2_3_omni_v1.6.gemfile | 2 +- gemfiles/ruby_2_3_omni_v1.7.gemfile | 2 +- gemfiles/ruby_2_3_omni_v1.8.gemfile | 11 ++++++++++ omniauth-ldap.gemspec | 2 +- 18 files changed, 46 insertions(+), 39 deletions(-) create mode 100644 gemfiles/modular/rack/r2.1/v1.0.gemfile create mode 100644 gemfiles/modular/rack/r2.1/v1.1.gemfile create mode 100644 gemfiles/modular/rack/r2.1/v1.2.gemfile create mode 100644 gemfiles/modular/rack/r2.1/v1.3.gemfile create mode 100644 gemfiles/modular/rack/r2.1/v1.4.gemfile create mode 100644 gemfiles/modular/rack/r2.1/v1.5.gemfile create mode 100644 gemfiles/ruby_2_3_omni_v1.8.gemfile diff --git a/.github/workflows/ancient.yml b/.github/workflows/ancient.yml index bd2ad10..92cb484 100644 --- a/.github/workflows/ancient.yml +++ b/.github/workflows/ancient.yml @@ -35,20 +35,6 @@ jobs: matrix: include: # Ruby 2.3 - - ruby: "ruby-2.3" - appraisal: "ruby-2-3-omni-v1.0" - exec_cmd: "rake test" - gemfile: "Appraisal.root" - rubygems: "3.3.27" - bundler: "2.3.27" - - - ruby: "ruby-2.3" - appraisal: "ruby-2-3-omni-v1.1" - exec_cmd: "rake test" - gemfile: "Appraisal.root" - rubygems: "3.3.27" - bundler: "2.3.27" - - ruby: "ruby-2.3" appraisal: "ruby-2-3-omni-v1.2" exec_cmd: "rake test" @@ -91,6 +77,13 @@ jobs: rubygems: "3.3.27" bundler: "2.3.27" + - ruby: "ruby-2.3" + appraisal: "ruby-2-3-omni-v1.8" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + # Ruby 2.4 - ruby: "ruby-2.4" appraisal: "ruby-2-4" diff --git a/Appraisals b/Appraisals index 49caaa7..a9e20bf 100644 --- a/Appraisals +++ b/Appraisals @@ -56,50 +56,44 @@ appraise "dep-heads" do eval_gemfile "modular/runtime_heads.gemfile" end -appraise "ruby-2-3-omni-v1.0" do - eval_gemfile "modular/omniauth/r2/v1.0.gemfile" - eval_gemfile "modular/rack/r2.1/v1.6.gemfile" - eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" -end - -appraise "ruby-2-3-omni-v1.1" do - eval_gemfile "modular/omniauth/r2/v1.1.gemfile" - eval_gemfile "modular/rack/r2.1/v1.6.gemfile" - eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" -end - appraise "ruby-2-3-omni-v1.2" do eval_gemfile "modular/omniauth/r2/v1.2.gemfile" - eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/rack/r2.1/v1.0.gemfile" eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" end appraise "ruby-2-3-omni-v1.3" do eval_gemfile "modular/omniauth/r2/v1.3.gemfile" - eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/rack/r2.1/v1.1.gemfile" eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" end appraise "ruby-2-3-omni-v1.4" do eval_gemfile "modular/omniauth/r2/v1.4.gemfile" - eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/rack/r2.1/v1.2.gemfile" eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" end appraise "ruby-2-3-omni-v1.5" do eval_gemfile "modular/omniauth/r2/v1.5.gemfile" - eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/rack/r2.1/v1.3.gemfile" eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" end appraise "ruby-2-3-omni-v1.6" do eval_gemfile "modular/omniauth/r2/v1.6.gemfile" - eval_gemfile "modular/rack/r2.1/v1.6.gemfile" + eval_gemfile "modular/rack/r2.1/v1.4.gemfile" eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" end appraise "ruby-2-3-omni-v1.7" do eval_gemfile "modular/omniauth/r2/v1.7.gemfile" + eval_gemfile "modular/rack/r2.1/v1.5.gemfile" + eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" +end + +appraise "ruby-2-3-omni-v1.8" do + eval_gemfile "modular/omniauth/r2/v1.8.gemfile" eval_gemfile "modular/rack/r2.1/v1.6.gemfile" eval_gemfile "modular/x_std_libs/r2.3/libs.gemfile" end diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bef234..ca85c0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,9 @@ Please file a bug if you notice a violation of semantic versioning. ### Changed +- Make support for OmniAuth v1.2+ explicit + - Versions < 1.2 do not support SCRIPT_NAME properly, and may cause other issues + ### Deprecated ### Removed diff --git a/Gemfile.lock b/Gemfile.lock index 259b4c9..33b35d3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,7 +15,7 @@ PATH specs: omniauth-ldap (2.3.1) net-ldap (~> 0.16, < 1) - omniauth (>= 1, < 3) + omniauth (>= 1.2, < 3) pyu-ruby-sasl (>= 0.0.3.3, < 0.1) rack (>= 1, < 4) rubyntlm (~> 0.6.2, < 1) diff --git a/gemfiles/modular/rack/r2.1/v1.0.gemfile b/gemfiles/modular/rack/r2.1/v1.0.gemfile new file mode 100644 index 0000000..2fa0824 --- /dev/null +++ b/gemfiles/modular/rack/r2.1/v1.0.gemfile @@ -0,0 +1 @@ +gem "rack", "~> 1.0", ">= 1.0.1" diff --git a/gemfiles/modular/rack/r2.1/v1.1.gemfile b/gemfiles/modular/rack/r2.1/v1.1.gemfile new file mode 100644 index 0000000..66d0790 --- /dev/null +++ b/gemfiles/modular/rack/r2.1/v1.1.gemfile @@ -0,0 +1 @@ +gem "rack", "~> 1.1", ">= 1.1.6" diff --git a/gemfiles/modular/rack/r2.1/v1.2.gemfile b/gemfiles/modular/rack/r2.1/v1.2.gemfile new file mode 100644 index 0000000..f3326b8 --- /dev/null +++ b/gemfiles/modular/rack/r2.1/v1.2.gemfile @@ -0,0 +1 @@ +gem "rack", "~> 1.2", ">= 1.2.8" diff --git a/gemfiles/modular/rack/r2.1/v1.3.gemfile b/gemfiles/modular/rack/r2.1/v1.3.gemfile new file mode 100644 index 0000000..c428315 --- /dev/null +++ b/gemfiles/modular/rack/r2.1/v1.3.gemfile @@ -0,0 +1 @@ +gem "rack", "~> 1.3", ">= 1.3.10" diff --git a/gemfiles/modular/rack/r2.1/v1.4.gemfile b/gemfiles/modular/rack/r2.1/v1.4.gemfile new file mode 100644 index 0000000..da0e01c --- /dev/null +++ b/gemfiles/modular/rack/r2.1/v1.4.gemfile @@ -0,0 +1 @@ +gem "rack", "~> 1.4", ">= 1.4.7" diff --git a/gemfiles/modular/rack/r2.1/v1.5.gemfile b/gemfiles/modular/rack/r2.1/v1.5.gemfile new file mode 100644 index 0000000..7b3744a --- /dev/null +++ b/gemfiles/modular/rack/r2.1/v1.5.gemfile @@ -0,0 +1 @@ +gem "rack", "~> 1.5", ">= 1.5.5" diff --git a/gemfiles/ruby_2_3_omni_v1.2.gemfile b/gemfiles/ruby_2_3_omni_v1.2.gemfile index 3d4e5aa..add5661 100644 --- a/gemfiles/ruby_2_3_omni_v1.2.gemfile +++ b/gemfiles/ruby_2_3_omni_v1.2.gemfile @@ -6,6 +6,6 @@ gemspec path: "../" eval_gemfile("modular/omniauth/r2/v1.2.gemfile") -eval_gemfile("modular/rack/r2.1/v1.6.gemfile") +eval_gemfile("modular/rack/r2.1/v1.0.gemfile") eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.3.gemfile b/gemfiles/ruby_2_3_omni_v1.3.gemfile index 321ede0..7069009 100644 --- a/gemfiles/ruby_2_3_omni_v1.3.gemfile +++ b/gemfiles/ruby_2_3_omni_v1.3.gemfile @@ -6,6 +6,6 @@ gemspec path: "../" eval_gemfile("modular/omniauth/r2/v1.3.gemfile") -eval_gemfile("modular/rack/r2.1/v1.6.gemfile") +eval_gemfile("modular/rack/r2.1/v1.1.gemfile") eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.4.gemfile b/gemfiles/ruby_2_3_omni_v1.4.gemfile index 5ee8d66..0608efa 100644 --- a/gemfiles/ruby_2_3_omni_v1.4.gemfile +++ b/gemfiles/ruby_2_3_omni_v1.4.gemfile @@ -6,6 +6,6 @@ gemspec path: "../" eval_gemfile("modular/omniauth/r2/v1.4.gemfile") -eval_gemfile("modular/rack/r2.1/v1.6.gemfile") +eval_gemfile("modular/rack/r2.1/v1.2.gemfile") eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.5.gemfile b/gemfiles/ruby_2_3_omni_v1.5.gemfile index a0ea50c..51f922b 100644 --- a/gemfiles/ruby_2_3_omni_v1.5.gemfile +++ b/gemfiles/ruby_2_3_omni_v1.5.gemfile @@ -6,6 +6,6 @@ gemspec path: "../" eval_gemfile("modular/omniauth/r2/v1.5.gemfile") -eval_gemfile("modular/rack/r2.1/v1.6.gemfile") +eval_gemfile("modular/rack/r2.1/v1.3.gemfile") eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.6.gemfile b/gemfiles/ruby_2_3_omni_v1.6.gemfile index 7a8ac6c..02327b4 100644 --- a/gemfiles/ruby_2_3_omni_v1.6.gemfile +++ b/gemfiles/ruby_2_3_omni_v1.6.gemfile @@ -6,6 +6,6 @@ gemspec path: "../" eval_gemfile("modular/omniauth/r2/v1.6.gemfile") -eval_gemfile("modular/rack/r2.1/v1.6.gemfile") +eval_gemfile("modular/rack/r2.1/v1.4.gemfile") eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.7.gemfile b/gemfiles/ruby_2_3_omni_v1.7.gemfile index f812070..f4becd6 100644 --- a/gemfiles/ruby_2_3_omni_v1.7.gemfile +++ b/gemfiles/ruby_2_3_omni_v1.7.gemfile @@ -6,6 +6,6 @@ gemspec path: "../" eval_gemfile("modular/omniauth/r2/v1.7.gemfile") -eval_gemfile("modular/rack/r2.1/v1.6.gemfile") +eval_gemfile("modular/rack/r2.1/v1.5.gemfile") eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/ruby_2_3_omni_v1.8.gemfile b/gemfiles/ruby_2_3_omni_v1.8.gemfile new file mode 100644 index 0000000..5b09553 --- /dev/null +++ b/gemfiles/ruby_2_3_omni_v1.8.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal2 + +source "https://gem.coop" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.8.gemfile") + +eval_gemfile("modular/rack/r2.1/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") diff --git a/omniauth-ldap.gemspec b/omniauth-ldap.gemspec index aff328f..257b815 100644 --- a/omniauth-ldap.gemspec +++ b/omniauth-ldap.gemspec @@ -98,7 +98,7 @@ Gem::Specification.new do |spec| spec.executables = [] spec.add_dependency("net-ldap", "~> 0.16", "< 1") # ruby >= 2.0 - spec.add_dependency("omniauth", ">= 1", "< 3") # ruby >= 0.0 + spec.add_dependency("omniauth", ">= 1.2", "< 3") # ruby >= 0.0 spec.add_dependency("pyu-ruby-sasl", ">= 0.0.3.3", "< 0.1") # ruby >= 0.0 spec.add_dependency("rack", ">= 1", "< 4") # ruby >= 0.0 spec.add_dependency("rubyntlm", "~> 0.6.2", "< 1") # ruby >= 1.8.7