Tencent/WeKnora · error
OIDC provider returned no user claims
Error message
OIDC provider returned no user claims
What it means
resolveOIDCUserInfo merges claims from the OIDC ID token and/or the userinfo endpoint. If the resulting claims map is completely empty, the provider returned nothing usable, so the service refuses to construct an OIDCUserInfo rather than fabricating an identity. This guards against misconfigured or broken providers yielding unauthenticated-but-successful logins.
Source
Thrown at internal/application/service/user.go:1615
}
}
if strings.TrimSpace(cfg.UserInfoEndpoint) != "" && strings.TrimSpace(tokenResp.AccessToken) != "" {
userInfoClaims, err := s.fetchOIDCUserInfo(ctx, cfg.UserInfoEndpoint, tokenResp.AccessToken)
if err != nil {
if !verifiedFromIDToken {
return nil, fmt.Errorf("failed to fetch OIDC userinfo: %w", err)
}
logger.Warnf(ctx, "Failed to fetch OIDC userinfo, using verified id_token claims: %v", err)
} else {
for k, v := range userInfoClaims {
claims[k] = v
}
}
}
if len(claims) == 0 {
return nil, errors.New("OIDC provider returned no user claims")
}
info := &types.OIDCUserInfo{Claims: claims}
if sub, _ := claims["sub"].(string); sub != "" {
info.Subject = sub
}
info.Username = extractClaimAsString(claims, cfg.UserInfoMapping.Username)
info.Email = extractClaimAsString(claims, cfg.UserInfoMapping.Email)
if info.Username == "" {
info.Username = extractClaimAsString(claims, "preferred_username")
}
if info.Username == "" {
info.Username = extractClaimAsString(claims, "name")
}
if info.Username == "" && info.Email != "" {
info.Username = strings.Split(info.Email, "@")[0]
}
return info, nilView on GitHub (pinned to 988cbb0330)
Solutions
- Check the provider's userinfo endpoint and id_token actually contain claims (test with curl or jwt.io).
- Verify the OIDC discovery/userinfo URL is correct and returns application/json.
- Ensure required scopes (openid, profile, email) are requested so claims are populated.
- Inspect proxy/gateway middleware that may drop or truncate response bodies.
Example fix
// before: provider userinfo returns {}
GET /userinfo -> {}
// after: request proper scopes so claims are issued
authURL.Query().Set("scope", "openid profile email") Defensive patterns
Strategy: validation
Validate before calling
if info == nil || len(info.Claims) == 0 {
return fmt.Errorf("oidc login failed: provider returned no user claims")
} Type guard
func hasOIDCClaims(info *types.OIDCUserInfo) bool {
return info != nil && len(info.Claims) > 0 && info.Subject != ""
} Prevention
- Always request the openid scope (plus profile/email as needed).
- Log (redacted) userinfo response length in development to detect empty bodies early.
- Test the provider's userinfo endpoint directly with curl before integrating.
When it happens
Trigger: LoginWithOIDC calls resolveOIDCUserInfo; both the verified id_token claims and the userinfo endpoint response decode to empty maps (e.g. token has no claims and userinfo returned {}), so len(claims)==0.
Common situations: Provider returns a userinfo response with no body or '{}'; a test/broken provider issues a minimal id_token with no claims; middleware upstream strips the userinfo JSON body; misconfigured userinfo endpoint pointing at an empty page.
Related errors
- id_token missing sub claim
- empty JWK modulus or exponent
- invalid JWK exponent value
- no matching JWKS key for id_token
- JWKS document contains no keys
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/64309114b64b10a2.
Report an issue: GitHub.