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, nil

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the provider's userinfo endpoint and id_token actually contain claims (test with curl or jwt.io).
  2. Verify the OIDC discovery/userinfo URL is correct and returns application/json.
  3. Ensure required scopes (openid, profile, email) are requested so claims are populated.
  4. 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

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


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/64309114b64b10a2. Report an issue: GitHub.