siyuan-note/siyuan · error
OIDC claim [%s] is not allowed
Error message
OIDC claim [%s] is not allowed
What it means
AllowAll is false and at least one ClaimRules entry found no matching value among the user's ID-token claims. %s names the claim (e.g. email, groups) that failed every rule. This is authorization failure - the user authenticated successfully but is not permitted to use this SiYuan.
Source
Thrown at kernel/model/oidc.go:971
matched := false
for _, claimValue := range claimValues {
for _, allowedValue := range rule.Values {
switch rule.Operator {
case conf.OIDCClaimOperatorEquals:
matched = claimValue == allowedValue
case conf.OIDCClaimOperatorContains:
matched = strings.Contains(claimValue, allowedValue)
}
if matched {
break
}
}
if matched {
break
}
}
if !matched {
return fmt.Errorf("OIDC claim [%s] is not allowed", rule.Claim)
}
}
return nil
}
func oidcClaimValues(value any) []string {
switch typed := value.(type) {
case string:
return []string{typed}
case bool, float64, float32, int, int64, json.Number:
return []string{fmt.Sprint(typed)}
case []string:
return typed
case []any:
ret := make([]string, 0, len(typed))
for _, item := range typed {
values := oidcClaimValues(item)
if len(values) == 1 {View on GitHub (pinned to 251596fc0d)
Solutions
- Inspect the user's actual claims at the IdP and confirm the claim name and values.
- Adjust ClaimRules (operator and/or Values) to match real claim data, or grant the user the required claim value at the IdP.
- Set AllowAll only if you intentionally want to bypass claim-based authorization.
Example fix
// before
ClaimRules: [{Claim:"groups", Operator:"equals", Values:["staff"]}]
// user has group "contractors" and is rejected
// after - broaden allowed values
ClaimRules: [{Claim:"groups", Operator:"equals", Values:["staff","contractors"]}] Defensive patterns
Strategy: validation
Validate before calling
// Pre-check claim policy against a sample of the user's claims before requiring login.
func claimsSatisfy(config *conf.OIDC, claims map[string]any) error {
if config.AllowAll {
return nil
}
for _, rule := range config.ClaimRules {
matched := false
for _, v := range oidcClaimValues(claims[rule.Claim]) {
for _, allowed := range rule.Values {
if rule.Operator == conf.OidcClaimOperatorEquals && v == allowed {
matched = true
} else if rule.Operator == conf.OidcClaimOperatorContains && strings.Contains(v, allowed) {
matched = true
}
}
}
if !matched {
return fmt.Errorf("claim %s not satisfied", rule.Claim)
}
}
return nil
} Try / catch
// Map authorization failure to a 403 with the failing claim, not a 500.
if err := authorizeOIDCClaims(config, claims); err != nil && strings.Contains(err.Error(), "is not allowed") {
respondForbidden(c, err.Error())
} Prevention
- Confirm the IdP actually emits the claim names referenced in ClaimRules.
- Test claim rules against a sample user before enforcing them.
- Keep an escape hatch for valid users by broadening Values rather than setting AllowAll.
When it happens
Trigger: A user authenticates at the IdP but their claims contain none of the allowed values for a configured rule; the configured claim name is not emitted by the IdP; the operator value does not match (e.g. wrong email domain).
Common situations: Rule expects groups:["staff"] but the user is not in staff; claim name typo in config; IdP does not emit the configured claim; email-domain contains rule with a wrong domain.
Related errors
- OIDC login requires at least one claim rule when Allow all u
- assetPath is not an image referenced by the document
- OIDC issuer URL must use HTTPS unless it is a loopback addre
- remote access requires at least one authentication method
- A public HTTPS OIDC redirect URL is required for remote acce
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/f0171dc2db847b69.
Report an issue: GitHub.