knadh/listmonk · error
error getting user from OIDC
Error message
error getting user from OIDC
What it means
This error is returned by ExchangeOIDCToken when the verified OIDC ID token's claims cannot be unmarshalled into the internal OIDCclaim struct via idTk.Claims(&claims). It means the token verified cryptographically but its JSON payload does not fit the expected claim shape, so the user identity cannot be extracted. The library discards the underlying cause, so the real reason (unexpected types, missing fields) is hidden.
Source
Thrown at internal/auth/auth.go:260
}
verifier, err := o.getVerifier()
if err != nil {
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("error getting verifier: %v", err))
}
idTk, err := verifier.Verify(context.TODO(), rawIDTk)
if err != nil {
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("error verifying ID token: %v", err))
}
if idTk.Nonce != nonce {
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, "nonce did not match")
}
var claims OIDCclaim
if err := idTk.Claims(&claims); err != nil {
return "", OIDCclaim{}, errors.New("error getting user from OIDC")
}
// If claims doesn't have the e-mail, attempt to fetch it from the userinfo endpoint.
if claims.Email == "" {
provider, err := o.getProvider()
if err != nil {
return "", OIDCclaim{}, fmt.Errorf("error getting provider: %v", err)
}
userInfo, err := provider.UserInfo(context.TODO(), oauth2.StaticTokenSource(tk))
if err != nil {
return "", OIDCclaim{}, errors.New("error fetching user info from OIDC")
}
// Parse the UserInfo claims into the claims struct
if err := userInfo.Claims(&claims); err != nil {
return "", OIDCclaim{}, errors.New("error parsing user info claims")
}View on GitHub (pinned to 670c01717d)
Solutions
- Check the raw ID token payload (decode at jwt.io or idToken.Claims into map[string]interface{}) and compare its types against the OIDCclaim struct field types.
- Fix the OIDCclaim struct (or add custom json tags / use json.RawMessage for flexible fields) to match what your IdP actually sends.
- Wrap the error with %w or log the underlying err before returning so the real mismatch is diagnosable.
- Verify the expected OIDC scopes are requested so standard claims (email, name) are present and well-typed.
Example fix
// before
var claims OIDCclaim
if err := idTk.Claims(&claims); err != nil {
return "", OIDCclaim{}, errors.New("error getting user from OIDC")
}
// after
var claims OIDCclaim
if err := idTk.Claims(&claims); err != nil {
return "", OIDCclaim{}, fmt.Errorf("error getting user from OIDC: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
var probe map[string]interface{}
if err := json.Unmarshal(rawIDTokenPayload, &probe); err != nil {
// token claims are not valid JSON; do not call ExchangeOIDCToken flow
} Type guard
func hasWellTypedClaims(m map[string]interface{}) bool {
for _, k := range []string{"email", "name", "sub"} {
if v, ok := m[k]; ok {
if _, ok := v.(string); !ok {
return false
}
}
}
return true
} Try / catch
if _, claims, err := auth.ExchangeOIDCToken(code, nonce); err != nil {
if strings.Contains(err.Error(), "error getting user from OIDC") {
log.Printf("OIDC claim parse failure: %v", err) // 500, not retryable
}
return err
} Prevention
- Keep OIDCclaim field types aligned with your IdP's claim types; test with a real token from the IdP.
- Request standard scopes (openid, email, profile) so claims are well-formed.
- Decode a sample ID token payload and diff it against the struct when upgrading IdPs.
- Preserve the wrapped error (%w) in custom builds to aid debugging.
When it happens
Trigger: The ID token's claims JSON contains fields whose types do not match OIDCclaim (e.g. email as a non-string, numeric claims as floats vs ints) or is malformed, causing the go-oidc Claims() json.Unmarshal into *OIDCclaim to fail after successful token verification and nonce check.
Common situations: An identity provider emits non-standard claim types (e.g. a claim that is an object or number where OIDCclaim expects a string); a provider update changes claim shapes; a misconfigured custom claim mapping produces type mismatches.
Related errors
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/41b9f24203287769.
Report an issue: GitHub.