mirror of
https://github.com/we-promise/sure.git
synced 2026-08-05 16:42:18 +00:00
* fix(oidc): honor http issuer scheme during OIDC discovery Self-hosted IdPs served over plain HTTP (no SSL) failed OIDC login with "Failed to open TCP connection to <issuer>:443 (Connection refused)". The openid_connect/swd gems hardcode discovery to HTTPS: SWD.url_builder defaults to URI::HTTPS, and OpenIDConnect::Discovery::Provider::Config::Resource drops the issuer's scheme, rebuilding the .well-known URL from host/port only. So an http:// issuer is upgraded to https:443 and never connects. (This is why the in-app "Test connection" passes -- it uses Faraday against the raw issuer URL and never goes through the gem.) Patch Config::Resource to remember the issuer's scheme and build the discovery endpoint with URI::HTTP or URI::HTTPS accordingly. Per-request, no global mutable state, so mixed http/https providers coexist. Only discovery needs patching: the endpoints it returns are absolute and rack-oauth2 preserves an existing scheme, so the token/userinfo/jwks calls follow over http automatically. Verified against openid_connect 2.3.1 / swd 2.0.3. Fixes #2844 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(oidc): scheme-aware port and discovery cache key Address automated review feedback on the OIDC http-discovery patch: - Preserve explicitly configured non-default ports (http on 443, https on 80) by omitting only the scheme's own default port instead of both 80 and 443. - Override the discovery cache_key to include scheme/port/path (the gem keyed on host alone), so an http:// issuer can't reuse an https:// issuer's cached metadata on the same host. Latent today (default SWD cache is a no-op) but removed to keep the override self-consistent. Adds regression tests for both cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(oidc): cover port and path as cache-key components Extend the discovery cache-key test to assert scheme, port, and path each produce a distinct key on the same host, per review feedback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
57 lines
2.2 KiB
Ruby
57 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "test_helper"
|
|
|
|
# Regression coverage for https://github.com/we-promise/sure/issues/2844 - a
|
|
# self-hosted IdP served over plain HTTP was upgraded to https:443 during discovery.
|
|
class OpenIDConnectHttpDiscoveryTest < ActiveSupport::TestCase
|
|
Resource = OpenIDConnect::Discovery::Provider::Config::Resource
|
|
|
|
test "http issuer builds an http discovery endpoint" do
|
|
endpoint = Resource.new(URI.parse("http://auth.example")).endpoint
|
|
|
|
assert_equal "http://auth.example/.well-known/openid-configuration", endpoint.to_s
|
|
end
|
|
|
|
test "https issuer still builds an https discovery endpoint" do
|
|
endpoint = Resource.new(URI.parse("https://auth.example")).endpoint
|
|
|
|
assert_equal "https://auth.example/.well-known/openid-configuration", endpoint.to_s
|
|
end
|
|
|
|
test "custom http port is preserved" do
|
|
endpoint = Resource.new(URI.parse("http://auth.example:9000")).endpoint
|
|
|
|
assert_equal "http://auth.example:9000/.well-known/openid-configuration", endpoint.to_s
|
|
end
|
|
|
|
test "explicit non-default port is preserved per scheme" do
|
|
http_443 = Resource.new(URI.parse("http://auth.example:443")).endpoint
|
|
https_80 = Resource.new(URI.parse("https://auth.example:80")).endpoint
|
|
|
|
assert_equal "http://auth.example:443/.well-known/openid-configuration", http_443.to_s
|
|
assert_equal "https://auth.example:80/.well-known/openid-configuration", https_80.to_s
|
|
end
|
|
|
|
test "cache key varies by scheme, port, and path on the same host" do
|
|
baseline = cache_key_for("http://auth.example")
|
|
other_scheme = cache_key_for("https://auth.example")
|
|
other_port = cache_key_for("http://auth.example:9000")
|
|
other_path = cache_key_for("http://auth.example/application/o/sure")
|
|
|
|
keys = [ baseline, other_scheme, other_port, other_path ]
|
|
assert_equal keys.length, keys.uniq.length, "each of scheme/port/path must produce a distinct cache key"
|
|
end
|
|
|
|
test "issuer path prefix is preserved" do
|
|
endpoint = Resource.new(URI.parse("http://auth.example/application/o/sure")).endpoint
|
|
|
|
assert_equal "http://auth.example/application/o/sure/.well-known/openid-configuration", endpoint.to_s
|
|
end
|
|
|
|
private
|
|
def cache_key_for(issuer)
|
|
Resource.new(URI.parse(issuer)).send(:cache_key)
|
|
end
|
|
end
|