mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-14 04:07:46 +00:00
110 lines
3.1 KiB
Go
110 lines
3.1 KiB
Go
package providers
|
|
|
|
import (
|
|
"net/url"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// ProviderRegistry holds and manages the available OIDC provider implementations.
|
|
// It provides thread-safe access to provider instances and caches detection results.
|
|
type ProviderRegistry struct {
|
|
mu sync.RWMutex
|
|
providers []OIDCProvider
|
|
cache map[string]OIDCProvider
|
|
typeMap map[ProviderType]OIDCProvider // Maps provider type to instance
|
|
}
|
|
|
|
// NewProviderRegistry creates and initializes a new ProviderRegistry.
|
|
func NewProviderRegistry() *ProviderRegistry {
|
|
return &ProviderRegistry{
|
|
providers: make([]OIDCProvider, 0),
|
|
cache: make(map[string]OIDCProvider),
|
|
typeMap: make(map[ProviderType]OIDCProvider),
|
|
}
|
|
}
|
|
|
|
// RegisterProvider adds a new provider to the registry.
|
|
// It maintains both a list of providers and a type-to-provider mapping for efficient lookups.
|
|
func (r *ProviderRegistry) RegisterProvider(provider OIDCProvider) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.providers = append(r.providers, provider)
|
|
r.typeMap[provider.GetType()] = provider
|
|
}
|
|
|
|
// GetProviderByType returns a provider instance for the specified type.
|
|
// Returns nil if the provider type is not registered.
|
|
func (r *ProviderRegistry) GetProviderByType(providerType ProviderType) OIDCProvider {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
return r.typeMap[providerType]
|
|
}
|
|
|
|
// GetRegisteredProviders returns a slice of all registered provider types.
|
|
func (r *ProviderRegistry) GetRegisteredProviders() []ProviderType {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
types := make([]ProviderType, 0, len(r.typeMap))
|
|
for providerType := range r.typeMap {
|
|
types = append(types, providerType)
|
|
}
|
|
return types
|
|
}
|
|
|
|
// ClearCache removes all cached provider detection results.
|
|
// This can be useful for testing or when provider configuration changes.
|
|
func (r *ProviderRegistry) ClearCache() {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.cache = make(map[string]OIDCProvider)
|
|
}
|
|
|
|
// DetectProvider determines the most appropriate provider for a given issuer URL.
|
|
// It iterates through the registered providers and returns the first one that matches.
|
|
// Detection is based on URL patterns and other provider-specific criteria.
|
|
func (r *ProviderRegistry) DetectProvider(issuerURL string) OIDCProvider {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
// Check cache first for performance
|
|
if provider, found := r.cache[issuerURL]; found {
|
|
return provider
|
|
}
|
|
|
|
// Normalize issuer URL for consistent matching
|
|
normalizedURL, err := url.Parse(issuerURL)
|
|
if err != nil {
|
|
// Log error or handle it appropriately
|
|
return nil
|
|
}
|
|
host := normalizedURL.Host
|
|
|
|
// Iterate through registered providers to find a match
|
|
for _, p := range r.providers {
|
|
switch p.GetType() {
|
|
case ProviderTypeGoogle:
|
|
if strings.Contains(host, "accounts.google.com") {
|
|
r.cache[issuerURL] = p
|
|
return p
|
|
}
|
|
case ProviderTypeAzure:
|
|
if strings.Contains(host, "login.microsoftonline.com") || strings.Contains(host, "sts.windows.net") {
|
|
r.cache[issuerURL] = p
|
|
return p
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback to the generic provider if no specific provider is detected
|
|
for _, p := range r.providers {
|
|
if p.GetType() == ProviderTypeGeneric {
|
|
r.cache[issuerURL] = p
|
|
return p
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|