mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-17 04:37:48 +00:00
fix(config): wire introspectionURL override and repair dead endpoint overrides (#152)
Issue #152 asks for a manual introspection endpoint because some IdPs
omit introspection_endpoint from discovery. Analysis found the two
documented overrides revocationURL and oidcEndSessionURL were dead
code: the 1b49e13 rebuild dropped their constructor wiring.
Add the IntrospectionURL config field and wire all three overrides.
The overrides apply inside updateMetadataEndpoints, so they survive
every metadata refresh. A manual value always wins over discovery.
The constructor also seeds the live fields, so a failed discovery
does not lose operator configuration.
Manual values skip the poisoned-discovery defences on purpose. They
sit at the same trust tier as providerURL and isValidSecureURL gates
them at config time.
Add issue152_regression_test.go: 8 tests pin precedence, refresh
survival, cold-start seeding, end-to-end introspection over HTTP,
and the validation contract.
This commit is contained in:
@@ -271,6 +271,21 @@ func NewWithContext(ctx context.Context, config *Config, next http.Handler, name
|
||||
allowOpaqueTokens: config.AllowOpaqueTokens,
|
||||
requireTokenIntrospection: config.RequireTokenIntrospection,
|
||||
disableReplayDetection: config.DisableReplayDetection,
|
||||
// Operator-configured endpoint overrides (issue #152). Applied inside
|
||||
// updateMetadataEndpoints so the override survives every metadata
|
||||
// refresh, not just construction.
|
||||
configRevocationURL: config.RevocationURL,
|
||||
configEndSessionURL: config.OIDCEndSessionURL,
|
||||
configIntrospectionURL: config.IntrospectionURL,
|
||||
// Cold-start seed: discovery failure must not lose operator-configured
|
||||
// endpoints; updateMetadataEndpoints re-applies these on every refresh.
|
||||
// Seeding introspectionURL here does not populate metadataSnapshot
|
||||
// (only updateMetadataEndpoints does); all three consumers
|
||||
// (token_introspection.go, token_manager.go, helpers.go) read these
|
||||
// metadataMu-guarded fields directly, not the snapshot.
|
||||
revocationURL: config.RevocationURL,
|
||||
endSessionURL: config.OIDCEndSessionURL,
|
||||
introspectionURL: config.IntrospectionURL,
|
||||
scopes: func() []string {
|
||||
userProvidedScopes := deduplicateScopes(config.Scopes)
|
||||
|
||||
@@ -602,6 +617,20 @@ func (t *TraefikOidc) updateMetadataEndpoints(metadata *ProviderMetadata) {
|
||||
t.logger.Errorf("Ignoring discovered issuer %q: host does not match configured providerURL", discoveredIssuer)
|
||||
discoveredIssuer = ""
|
||||
}
|
||||
// Operator-configured endpoint overrides take precedence over discovered
|
||||
// values. They deliberately skip validateDiscoveredEndpoint and the
|
||||
// sameHost pin: those defend against a poisoned discovery document, while
|
||||
// operator config sits at the same trust tier as providerURL itself and is
|
||||
// already gated by isValidSecureURL at config time.
|
||||
if t.configRevocationURL != "" {
|
||||
metadata.RevokeURL = t.configRevocationURL
|
||||
}
|
||||
if t.configEndSessionURL != "" {
|
||||
metadata.EndSessionURL = t.configEndSessionURL
|
||||
}
|
||||
if t.configIntrospectionURL != "" {
|
||||
metadata.IntrospectionURL = t.configIntrospectionURL
|
||||
}
|
||||
|
||||
t.metadataMu.Lock()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user