fix(auth): harden oauth identity upgrade paths
This commit is contained in:
@@ -211,25 +211,27 @@ type WeChatConnectConfig struct {
|
||||
}
|
||||
|
||||
type OIDCConnectConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
ProviderName string `mapstructure:"provider_name"` // 显示名: "Keycloak" 等
|
||||
ClientID string `mapstructure:"client_id"`
|
||||
ClientSecret string `mapstructure:"client_secret"`
|
||||
IssuerURL string `mapstructure:"issuer_url"`
|
||||
DiscoveryURL string `mapstructure:"discovery_url"`
|
||||
AuthorizeURL string `mapstructure:"authorize_url"`
|
||||
TokenURL string `mapstructure:"token_url"`
|
||||
UserInfoURL string `mapstructure:"userinfo_url"`
|
||||
JWKSURL string `mapstructure:"jwks_url"`
|
||||
Scopes string `mapstructure:"scopes"` // 默认 "openid email profile"
|
||||
RedirectURL string `mapstructure:"redirect_url"` // 后端回调地址(需在提供方后台登记)
|
||||
FrontendRedirectURL string `mapstructure:"frontend_redirect_url"` // 前端接收 token 的路由(默认:/auth/oidc/callback)
|
||||
TokenAuthMethod string `mapstructure:"token_auth_method"` // client_secret_post / client_secret_basic / none
|
||||
UsePKCE bool `mapstructure:"use_pkce"`
|
||||
ValidateIDToken bool `mapstructure:"validate_id_token"`
|
||||
AllowedSigningAlgs string `mapstructure:"allowed_signing_algs"` // 默认 "RS256,ES256,PS256"
|
||||
ClockSkewSeconds int `mapstructure:"clock_skew_seconds"` // 默认 120
|
||||
RequireEmailVerified bool `mapstructure:"require_email_verified"` // 默认 false
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
ProviderName string `mapstructure:"provider_name"` // 显示名: "Keycloak" 等
|
||||
ClientID string `mapstructure:"client_id"`
|
||||
ClientSecret string `mapstructure:"client_secret"`
|
||||
IssuerURL string `mapstructure:"issuer_url"`
|
||||
DiscoveryURL string `mapstructure:"discovery_url"`
|
||||
AuthorizeURL string `mapstructure:"authorize_url"`
|
||||
TokenURL string `mapstructure:"token_url"`
|
||||
UserInfoURL string `mapstructure:"userinfo_url"`
|
||||
JWKSURL string `mapstructure:"jwks_url"`
|
||||
Scopes string `mapstructure:"scopes"` // 默认 "openid email profile"
|
||||
RedirectURL string `mapstructure:"redirect_url"` // 后端回调地址(需在提供方后台登记)
|
||||
FrontendRedirectURL string `mapstructure:"frontend_redirect_url"` // 前端接收 token 的路由(默认:/auth/oidc/callback)
|
||||
TokenAuthMethod string `mapstructure:"token_auth_method"` // client_secret_post / client_secret_basic / none
|
||||
UsePKCE bool `mapstructure:"use_pkce"`
|
||||
ValidateIDToken bool `mapstructure:"validate_id_token"`
|
||||
UsePKCEExplicit bool `mapstructure:"-" yaml:"-"`
|
||||
ValidateIDTokenExplicit bool `mapstructure:"-" yaml:"-"`
|
||||
AllowedSigningAlgs string `mapstructure:"allowed_signing_algs"` // 默认 "RS256,ES256,PS256"
|
||||
ClockSkewSeconds int `mapstructure:"clock_skew_seconds"` // 默认 120
|
||||
RequireEmailVerified bool `mapstructure:"require_email_verified"` // 默认 false
|
||||
|
||||
// 可选:用于从 userinfo JSON 中提取字段的 gjson 路径。
|
||||
// 为空时,服务端会尝试一组常见字段名。
|
||||
@@ -329,6 +331,14 @@ func shouldApplyLegacyWeChatEnv(configKey, envKey string) bool {
|
||||
return !hasNewEnv
|
||||
}
|
||||
|
||||
func hasExplicitConfigOrEnv(configKey, envKey string) bool {
|
||||
if viper.InConfig(configKey) {
|
||||
return true
|
||||
}
|
||||
_, ok := os.LookupEnv(envKey)
|
||||
return ok
|
||||
}
|
||||
|
||||
func applyLegacyWeChatConnectEnvCompatibility(cfg *WeChatConnectConfig) {
|
||||
if cfg == nil {
|
||||
return
|
||||
@@ -1262,6 +1272,8 @@ func load(allowMissingJWTSecret bool) (*Config, error) {
|
||||
cfg.OIDC.UserInfoEmailPath = strings.TrimSpace(cfg.OIDC.UserInfoEmailPath)
|
||||
cfg.OIDC.UserInfoIDPath = strings.TrimSpace(cfg.OIDC.UserInfoIDPath)
|
||||
cfg.OIDC.UserInfoUsernamePath = strings.TrimSpace(cfg.OIDC.UserInfoUsernamePath)
|
||||
cfg.OIDC.UsePKCEExplicit = hasExplicitConfigOrEnv("oidc_connect.use_pkce", "OIDC_CONNECT_USE_PKCE")
|
||||
cfg.OIDC.ValidateIDTokenExplicit = hasExplicitConfigOrEnv("oidc_connect.validate_id_token", "OIDC_CONNECT_VALIDATE_ID_TOKEN")
|
||||
cfg.Dashboard.KeyPrefix = strings.TrimSpace(cfg.Dashboard.KeyPrefix)
|
||||
cfg.CORS.AllowedOrigins = normalizeStringSlice(cfg.CORS.AllowedOrigins)
|
||||
cfg.Security.ResponseHeaders.AdditionalAllowed = normalizeStringSlice(cfg.Security.ResponseHeaders.AdditionalAllowed)
|
||||
|
||||
@@ -254,6 +254,21 @@ func TestLoadDefaultOIDCSecurityDefaults(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, cfg.OIDC.UsePKCE)
|
||||
require.True(t, cfg.OIDC.ValidateIDToken)
|
||||
require.False(t, cfg.OIDC.UsePKCEExplicit)
|
||||
require.False(t, cfg.OIDC.ValidateIDTokenExplicit)
|
||||
}
|
||||
|
||||
func TestLoadExplicitOIDCSecurityDefaultsFromEnvMarksFlagsExplicit(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
t.Setenv("OIDC_CONNECT_USE_PKCE", "false")
|
||||
t.Setenv("OIDC_CONNECT_VALIDATE_ID_TOKEN", "false")
|
||||
|
||||
cfg, err := Load()
|
||||
require.NoError(t, err)
|
||||
require.False(t, cfg.OIDC.UsePKCE)
|
||||
require.False(t, cfg.OIDC.ValidateIDToken)
|
||||
require.True(t, cfg.OIDC.UsePKCEExplicit)
|
||||
require.True(t, cfg.OIDC.ValidateIDTokenExplicit)
|
||||
}
|
||||
|
||||
func TestLoadForcedCodexInstructionsTemplate(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user