mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-13 04:07:37 +00:00
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
package providers
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// ProviderFactory encapsulates the logic for creating and configuring OIDC providers.
|
|
type ProviderFactory struct {
|
|
registry *ProviderRegistry
|
|
}
|
|
|
|
// NewProviderFactory creates a new factory with a pre-configured registry.
|
|
func NewProviderFactory() *ProviderFactory {
|
|
registry := NewProviderRegistry()
|
|
|
|
// Register all available providers
|
|
registry.RegisterProvider(NewGenericProvider())
|
|
registry.RegisterProvider(NewGoogleProvider())
|
|
registry.RegisterProvider(NewAzureProvider())
|
|
|
|
return &ProviderFactory{
|
|
registry: registry,
|
|
}
|
|
}
|
|
|
|
// CreateProvider creates and returns the appropriate provider for the given issuer URL.
|
|
// It automatically detects the provider type and returns a configured instance.
|
|
func (f *ProviderFactory) CreateProvider(issuerURL string) (OIDCProvider, error) {
|
|
if issuerURL == "" {
|
|
return nil, fmt.Errorf("issuer URL cannot be empty")
|
|
}
|
|
|
|
// Validate URL format
|
|
if _, err := url.Parse(issuerURL); err != nil {
|
|
return nil, fmt.Errorf("invalid issuer URL format: %w", err)
|
|
}
|
|
|
|
provider := f.registry.DetectProvider(issuerURL)
|
|
if provider == nil {
|
|
return nil, fmt.Errorf("unable to detect provider for issuer URL: %s", issuerURL)
|
|
}
|
|
|
|
// Validate the provider configuration if it implements config validation
|
|
if err := provider.ValidateConfig(); err != nil {
|
|
return nil, fmt.Errorf("provider configuration validation failed: %w", err)
|
|
}
|
|
|
|
return provider, nil
|
|
}
|
|
|
|
// CreateProviderByType creates a provider instance for a specific provider type.
|
|
// This is useful when you want to force a specific provider type regardless of URL.
|
|
func (f *ProviderFactory) CreateProviderByType(providerType ProviderType) (OIDCProvider, error) {
|
|
var provider OIDCProvider
|
|
|
|
switch providerType {
|
|
case ProviderTypeGeneric:
|
|
provider = NewGenericProvider()
|
|
case ProviderTypeGoogle:
|
|
provider = NewGoogleProvider()
|
|
case ProviderTypeAzure:
|
|
provider = NewAzureProvider()
|
|
default:
|
|
return nil, fmt.Errorf("unsupported provider type: %d", providerType)
|
|
}
|
|
|
|
if err := provider.ValidateConfig(); err != nil {
|
|
return nil, fmt.Errorf("provider configuration validation failed: %w", err)
|
|
}
|
|
|
|
return provider, nil
|
|
}
|
|
|
|
// GetSupportedProviders returns a list of all supported provider types and their detection patterns.
|
|
func (f *ProviderFactory) GetSupportedProviders() map[ProviderType][]string {
|
|
return map[ProviderType][]string{
|
|
ProviderTypeGeneric: {"*"}, // Generic supports any issuer
|
|
ProviderTypeGoogle: {"accounts.google.com"},
|
|
ProviderTypeAzure: {"login.microsoftonline.com", "sts.windows.net"},
|
|
}
|
|
}
|
|
|
|
// DetectProviderType returns the provider type that would be used for a given issuer URL.
|
|
// This is useful for diagnostic purposes or UI display.
|
|
func (f *ProviderFactory) DetectProviderType(issuerURL string) (ProviderType, error) {
|
|
provider, err := f.CreateProvider(issuerURL)
|
|
if err != nil {
|
|
return ProviderTypeGeneric, err
|
|
}
|
|
return provider.GetType(), nil
|
|
}
|
|
|
|
// IsProviderSupported checks if a given issuer URL is supported by any registered provider.
|
|
func (f *ProviderFactory) IsProviderSupported(issuerURL string) bool {
|
|
if issuerURL == "" {
|
|
return false
|
|
}
|
|
|
|
normalizedURL, err := url.Parse(issuerURL)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
host := strings.ToLower(normalizedURL.Host)
|
|
supportedProviders := f.GetSupportedProviders()
|
|
|
|
for _, patterns := range supportedProviders {
|
|
for _, pattern := range patterns {
|
|
if pattern == "*" || strings.Contains(host, strings.ToLower(pattern)) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|