fix(oidc): 同步认证中心用户资料到本地用户
从已验证的 OIDC Claim 提取用户名、显示名称、邮箱、手机号和头像,并覆盖单租户、多租户及平台用户的 JIT 创建与重复登录同步。\n\n保留 metadata.manualProfile 标记下的人工资料,限制字段长度且仅接收已验证联系方式与 HTTPS 头像。已通过 auth、httpapi、store 测试及临时 PostgreSQL 集成验证。
This commit is contained in:
@@ -252,18 +252,51 @@ func (v *OIDCVerifier) Verify(ctx context.Context, raw string) (*User, error) {
|
||||
return nil, oidcUnauthorized("TOKEN_INACTIVE", "token is inactive", err)
|
||||
}
|
||||
}
|
||||
username := stringClaim(claims, "preferred_username")
|
||||
username := oidcProfileText(claims, "preferred_username", 320)
|
||||
if username == "" {
|
||||
username = stringClaim(claims, "username")
|
||||
username = oidcProfileText(claims, "username", 320)
|
||||
}
|
||||
return &User{
|
||||
ID: stringClaim(claims, "sub"), Username: username, Roles: roles,
|
||||
ID: stringClaim(claims, "sub"), Username: username,
|
||||
DisplayName: oidcProfileText(claims, "name", 200),
|
||||
Email: oidcVerifiedProfileText(claims, "email", "email_verified", 320),
|
||||
Phone: oidcVerifiedProfileText(claims, "phone_number", "phone_number_verified", 64),
|
||||
AvatarURL: safeOIDCProfileURL(oidcProfileText(claims, "picture", 2048)),
|
||||
Roles: roles,
|
||||
ContextType: contextType, TenantID: tenantID, Source: "oidc",
|
||||
TokenExpiresAt: expiresAt, TokenIssuedAt: issuedAt, Issuer: v.config.Issuer,
|
||||
ApplicationID: v.config.ApplicationID, OIDCClientID: clientID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func oidcProfileText(claims jwt.MapClaims, key string, limit int) string {
|
||||
value := strings.TrimSpace(stringClaim(claims, key))
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
runes := []rune(value)
|
||||
if len(runes) > limit {
|
||||
return string(runes[:limit])
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func oidcVerifiedProfileText(claims jwt.MapClaims, key, verifiedKey string, limit int) string {
|
||||
verified, ok := claims[verifiedKey].(bool)
|
||||
if !ok || !verified {
|
||||
return ""
|
||||
}
|
||||
return oidcProfileText(claims, key, limit)
|
||||
}
|
||||
|
||||
func safeOIDCProfileURL(value string) string {
|
||||
parsed, err := url.Parse(value)
|
||||
if err != nil || parsed.Scheme != "https" || parsed.Host == "" || parsed.User != nil {
|
||||
return ""
|
||||
}
|
||||
return parsed.String()
|
||||
}
|
||||
|
||||
type oidcValidationError struct {
|
||||
category string
|
||||
reason string
|
||||
|
||||
Reference in New Issue
Block a user