{"record":{"id":"f0171dc2db847b69","repo":"siyuan-note/siyuan","slug":"oidc-claim-s-is-not-allowed","errorCode":null,"errorMessage":"OIDC claim [%s] is not allowed","messagePattern":"OIDC claim \\[(.+?)\\] is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc.go","lineNumber":971,"sourceCode":"\t\tmatched := false\n\t\tfor _, claimValue := range claimValues {\n\t\t\tfor _, allowedValue := range rule.Values {\n\t\t\t\tswitch rule.Operator {\n\t\t\t\tcase conf.OIDCClaimOperatorEquals:\n\t\t\t\t\tmatched = claimValue == allowedValue\n\t\t\t\tcase conf.OIDCClaimOperatorContains:\n\t\t\t\t\tmatched = strings.Contains(claimValue, allowedValue)\n\t\t\t\t}\n\t\t\t\tif matched {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif matched {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !matched {\n\t\t\treturn fmt.Errorf(\"OIDC claim [%s] is not allowed\", rule.Claim)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc oidcClaimValues(value any) []string {\n\tswitch typed := value.(type) {\n\tcase string:\n\t\treturn []string{typed}\n\tcase bool, float64, float32, int, int64, json.Number:\n\t\treturn []string{fmt.Sprint(typed)}\n\tcase []string:\n\t\treturn typed\n\tcase []any:\n\t\tret := make([]string, 0, len(typed))\n\t\tfor _, item := range typed {\n\t\t\tvalues := oidcClaimValues(item)\n\t\t\tif len(values) == 1 {","sourceCodeStart":953,"sourceCodeEnd":989,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/oidc.go#L953-L989","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nClaimRules: [{Claim:\"groups\", Operator:\"equals\", Values:[\"staff\"]}]\n// user has group \"contractors\" and is rejected\n// after - broaden allowed values\nClaimRules: [{Claim:\"groups\", Operator:\"equals\", Values:[\"staff\",\"contractors\"]}]","handlingStrategy":"validation","validationCode":"// Pre-check claim policy against a sample of the user's claims before requiring login.\nfunc claimsSatisfy(config *conf.OIDC, claims map[string]any) error {\n    if config.AllowAll {\n        return nil\n    }\n    for _, rule := range config.ClaimRules {\n        matched := false\n        for _, v := range oidcClaimValues(claims[rule.Claim]) {\n            for _, allowed := range rule.Values {\n                if rule.Operator == conf.OidcClaimOperatorEquals && v == allowed {\n                    matched = true\n                } else if rule.Operator == conf.OidcClaimOperatorContains && strings.Contains(v, allowed) {\n                    matched = true\n                }\n            }\n        }\n        if !matched {\n            return fmt.Errorf(\"claim %s not satisfied\", rule.Claim)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Map authorization failure to a 403 with the failing claim, not a 500.\nif err := authorizeOIDCClaims(config, claims); err != nil && strings.Contains(err.Error(), \"is not allowed\") {\n    respondForbidden(c, err.Error())\n}","preventionTips":["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."],"tags":["oidc","authorization","claims","security"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}