feat(auth): add option to disable built-in login when using OIDC (#1908)

* feat(auth): disable built-in login by config

* cleanup config

* fix(web): prevent login form flash by waiting for OIDC config

* refactor(config): standardize OIDC TOML format

- Adds camelCase TOML tags to OIDC config struct while keeping mapstructure tags for backward compatibility
- Updates config template to use camelCase format

* refactor: kyles changes

* refactor: prefix disablebuiltinlogin with oidc

* docs: revert format change

---------

Co-authored-by: ze0s <43699394+zze0s@users.noreply.github.com>
This commit is contained in:
soup 2025-01-26 15:25:34 +01:00 committed by GitHub
parent 9eff694a5f
commit 024371e4eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 192 additions and 172 deletions

View file

@ -21,12 +21,13 @@ import (
)
type OIDCConfig struct {
Enabled bool
Issuer string
ClientID string
ClientSecret string
RedirectURL string
Scopes []string
Enabled bool
Issuer string
ClientID string
ClientSecret string
RedirectURL string
DisableBuiltInLogin bool
Scopes []string
}
type OIDCHandler struct {
@ -124,12 +125,13 @@ func NewOIDCHandler(cfg *domain.Config, log zerolog.Logger) (*OIDCHandler, error
handler := &OIDCHandler{
log: log,
config: &OIDCConfig{
Enabled: cfg.OIDCEnabled,
Issuer: cfg.OIDCIssuer,
ClientID: cfg.OIDCClientID,
ClientSecret: cfg.OIDCClientSecret,
RedirectURL: cfg.OIDCRedirectURL,
Scopes: scopes,
Enabled: cfg.OIDCEnabled,
Issuer: cfg.OIDCIssuer,
ClientID: cfg.OIDCClientID,
ClientSecret: cfg.OIDCClientSecret,
RedirectURL: cfg.OIDCRedirectURL,
DisableBuiltInLogin: cfg.OIDCDisableBuiltInLogin,
Scopes: scopes,
},
provider: provider,
verifier: provider.Verifier(oidcConfig),
@ -282,27 +284,30 @@ func (h *OIDCHandler) GetAuthorizationURL() string {
}
type GetConfigResponse struct {
Enabled bool `json:"enabled"`
AuthorizationURL string `json:"authorizationUrl"`
State string `json:"state"`
Enabled bool `json:"enabled"`
AuthorizationURL string `json:"authorizationUrl"`
State string `json:"state"`
DisableBuiltInLogin bool `json:"disableBuiltInLogin"`
}
func (h *OIDCHandler) GetConfigResponse() GetConfigResponse {
if h == nil {
return GetConfigResponse{
Enabled: false,
Enabled: false,
DisableBuiltInLogin: false,
}
}
state := generateRandomState()
authURL := h.oauthConfig.AuthCodeURL(state)
h.log.Debug().Bool("enabled", h.config.Enabled).Str("authorization_url", authURL).Str("state", state).Msg("returning OIDC config response")
h.log.Debug().Bool("enabled", h.config.Enabled).Str("authorization_url", authURL).Str("state", state).Bool("disable_built_in_login", h.config.DisableBuiltInLogin).Msg("returning OIDC config response")
return GetConfigResponse{
Enabled: h.config.Enabled,
AuthorizationURL: authURL,
State: state,
Enabled: h.config.Enabled,
AuthorizationURL: authURL,
State: state,
DisableBuiltInLogin: h.config.DisableBuiltInLogin,
}
}

View file

@ -112,19 +112,22 @@ sessionSecret = "{{ .sessionSecret }}"
# OpenID Connect Configuration
#
# Enable OIDC authentication
#oidc_enabled = false
#oidcEnabled = false
#
# OIDC Issuer URL (e.g. https://auth.example.com)
#oidc_issuer = ""
#oidcIssuer = ""
#
# OIDC Client ID
#oidc_client_id = ""
#oidcClientId = ""
#
# OIDC Client Secret
#oidc_client_secret = ""
#oidcClientSecret = ""
#
# OIDC Redirect URL (e.g. http://localhost:7474/api/auth/oidc/callback)
#oidc_redirect_url = ""
#oidcRedirectUrl = ""
#
# Disable Built In Login Form (only works when using external auth)
#oidcDisableBuiltInLogin = false
# Metrics
#
@ -432,6 +435,10 @@ func (c *AppConfig) loadFromEnv() {
c.Config.OIDCRedirectURL = v
}
if v := os.Getenv(prefix + "OIDC_DISABLE_BUILT_IN_LOGIN"); v != "" {
c.Config.OIDCDisableBuiltInLogin = strings.EqualFold(strings.ToLower(v), "true")
}
if v := os.Getenv(prefix + "METRICS_ENABLED"); v != "" {
c.Config.MetricsEnabled = strings.EqualFold(strings.ToLower(v), "true")
}

View file

@ -4,41 +4,42 @@
package domain
type Config struct {
Version string
ConfigPath string
Host string `toml:"host"`
Port int `toml:"port"`
LogLevel string `toml:"logLevel"`
LogPath string `toml:"logPath"`
LogMaxSize int `toml:"logMaxSize"`
LogMaxBackups int `toml:"logMaxBackups"`
BaseURL string `toml:"baseUrl"`
BaseURLModeLegacy bool `toml:"baseUrlModeLegacy"`
SessionSecret string `toml:"sessionSecret"`
CustomDefinitions string `toml:"customDefinitions"`
CheckForUpdates bool `toml:"checkForUpdates"`
DatabaseType string `toml:"databaseType"`
DatabaseMaxBackups int `toml:"databaseMaxBackups"`
PostgresHost string `toml:"postgresHost"`
PostgresPort int `toml:"postgresPort"`
PostgresDatabase string `toml:"postgresDatabase"`
PostgresUser string `toml:"postgresUser"`
PostgresPass string `toml:"postgresPass"`
PostgresSSLMode string `toml:"postgresSSLMode"`
PostgresExtraParams string `toml:"postgresExtraParams"`
ProfilingEnabled bool `toml:"profilingEnabled"`
ProfilingHost string `toml:"profilingHost"`
ProfilingPort int `toml:"profilingPort"`
OIDCEnabled bool `mapstructure:"oidc_enabled"`
OIDCIssuer string `mapstructure:"oidc_issuer"`
OIDCClientID string `mapstructure:"oidc_client_id"`
OIDCClientSecret string `mapstructure:"oidc_client_secret"`
OIDCRedirectURL string `mapstructure:"oidc_redirect_url"`
OIDCScopes string `mapstructure:"oidc_scopes"`
MetricsEnabled bool `toml:"metricsEnabled"`
MetricsHost string `toml:"metricsHost"`
MetricsPort int `toml:"metricsPort"`
MetricsBasicAuthUsers string `toml:"metricsBasicAuthUsers"`
Version string
ConfigPath string
Host string `toml:"host"`
Port int `toml:"port"`
LogLevel string `toml:"logLevel"`
LogPath string `toml:"logPath"`
LogMaxSize int `toml:"logMaxSize"`
LogMaxBackups int `toml:"logMaxBackups"`
BaseURL string `toml:"baseUrl"`
BaseURLModeLegacy bool `toml:"baseUrlModeLegacy"`
SessionSecret string `toml:"sessionSecret"`
CustomDefinitions string `toml:"customDefinitions"`
CheckForUpdates bool `toml:"checkForUpdates"`
DatabaseType string `toml:"databaseType"`
DatabaseMaxBackups int `toml:"databaseMaxBackups"`
PostgresHost string `toml:"postgresHost"`
PostgresPort int `toml:"postgresPort"`
PostgresDatabase string `toml:"postgresDatabase"`
PostgresUser string `toml:"postgresUser"`
PostgresPass string `toml:"postgresPass"`
PostgresSSLMode string `toml:"postgresSSLMode"`
PostgresExtraParams string `toml:"postgresExtraParams"`
ProfilingEnabled bool `toml:"profilingEnabled"`
ProfilingHost string `toml:"profilingHost"`
ProfilingPort int `toml:"profilingPort"`
OIDCEnabled bool `toml:"oidcEnabled" mapstructure:"oidc_enabled"`
OIDCIssuer string `toml:"oidcIssuer" mapstructure:"oidc_issuer"`
OIDCClientID string `toml:"oidcClientId" mapstructure:"oidc_client_id"`
OIDCClientSecret string `toml:"oidcClientSecret" mapstructure:"oidc_client_secret"`
OIDCRedirectURL string `toml:"oidcRedirectUrl" mapstructure:"oidc_redirect_url"`
OIDCScopes string `toml:"oidcScopes" mapstructure:"oidc_scopes"`
OIDCDisableBuiltInLogin bool `toml:"oidcDisableBuiltInLogin" mapstructure:"disable_built_in_login"`
MetricsEnabled bool `toml:"metricsEnabled"`
MetricsHost string `toml:"metricsHost"`
MetricsPort int `toml:"metricsPort"`
MetricsBasicAuthUsers string `toml:"metricsBasicAuthUsers"`
}
type ConfigUpdate struct {