mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-16 04:29:15 +00:00
multiple realms fix (#102)
* Allow to use multiple realms This change is a ressurection of PR #88 which can't be merged due to significant refactor of the codebase. * Fix the autocleanup routine to handle multiple realms correctly, update tests. * Metadata rediscovery when provider is unavailable for any reason during the start. This one prevents the permanent 503 from the plugin when OIDC provider was for some reason unavailable during the start.
This commit is contained in:
@@ -5,6 +5,8 @@ package traefikoidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -392,11 +394,15 @@ func (t *TraefikOidc) updateMetadataEndpoints(metadata *ProviderMetadata) {
|
||||
t.introspectionURL = metadata.IntrospectionURL // OAuth 2.0 Token Introspection endpoint (RFC 7662)
|
||||
t.registrationURL = metadata.RegistrationURL // OIDC Dynamic Client Registration endpoint (RFC 7591)
|
||||
|
||||
// Copy values for logging after unlock to avoid race conditions
|
||||
introspectionURL := t.introspectionURL
|
||||
registrationURL := t.registrationURL
|
||||
|
||||
t.metadataMu.Unlock()
|
||||
|
||||
// Log introspection endpoint availability for opaque token support
|
||||
if t.introspectionURL != "" {
|
||||
t.logger.Debugf("Token introspection endpoint discovered: %s", t.introspectionURL)
|
||||
if introspectionURL != "" {
|
||||
t.logger.Debugf("Token introspection endpoint discovered: %s", introspectionURL)
|
||||
if t.allowOpaqueTokens {
|
||||
t.logger.Debugf("Opaque token support enabled with introspection endpoint")
|
||||
}
|
||||
@@ -405,8 +411,8 @@ func (t *TraefikOidc) updateMetadataEndpoints(metadata *ProviderMetadata) {
|
||||
}
|
||||
|
||||
// Log registration endpoint availability
|
||||
if t.registrationURL != "" {
|
||||
t.logger.Debugf("Dynamic client registration endpoint discovered: %s", t.registrationURL)
|
||||
if registrationURL != "" {
|
||||
t.logger.Debugf("Dynamic client registration endpoint discovered: %s", registrationURL)
|
||||
}
|
||||
|
||||
// Perform Dynamic Client Registration if enabled and ClientID is not set
|
||||
@@ -474,7 +480,10 @@ func (t *TraefikOidc) performDynamicClientRegistration() {
|
||||
func (t *TraefikOidc) startMetadataRefresh(providerURL string) {
|
||||
// Use singleton resource manager for metadata refresh
|
||||
rm := GetResourceManager()
|
||||
taskName := "singleton-metadata-refresh"
|
||||
// Use last 6 chars of provider URL hash to create unique task name per realm
|
||||
// This fixes multi-realm support where different Keycloak realms need separate refresh tasks
|
||||
hash := sha256.Sum256([]byte(providerURL))
|
||||
taskName := "singleton-metadata-refresh-" + hex.EncodeToString(hash[:])[0:6]
|
||||
|
||||
// Create refresh function
|
||||
refreshFunc := func() {
|
||||
@@ -510,6 +519,27 @@ func (t *TraefikOidc) startMetadataRefresh(providerURL string) {
|
||||
}
|
||||
}
|
||||
|
||||
// attemptMetadataRecovery tries to fetch provider metadata when the system is in a failed state.
|
||||
// This is called periodically (every 30s) when requests come in and metadata is unavailable.
|
||||
// It allows automatic recovery when the OIDC provider becomes available again.
|
||||
func (t *TraefikOidc) attemptMetadataRecovery() {
|
||||
if t.metadataCache == nil || t.httpClient == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Try to fetch metadata (single attempt, no aggressive retry here since this runs every 30s)
|
||||
metadata, err := t.metadataCache.GetMetadata(t.providerURL, t.httpClient, t.logger)
|
||||
if err != nil {
|
||||
t.safeLogDebugf("Metadata recovery attempt failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if metadata != nil {
|
||||
t.updateMetadataEndpoints(metadata)
|
||||
t.safeLogInfo("Successfully recovered OIDC provider metadata - service restored")
|
||||
}
|
||||
}
|
||||
|
||||
// createCaseInsensitiveStringMap creates a map with lowercase keys for case-insensitive matching.
|
||||
// This is used for case-insensitive matching of email addresses.
|
||||
// Parameters:
|
||||
|
||||
Reference in New Issue
Block a user