{"record":{"id":"343e080ed4c4aa0d","repo":"siyuan-note/siyuan","slug":"unsupported-oidc-claim-rule-operator","errorCode":null,"errorMessage":"Unsupported OIDC claim rule operator","messagePattern":"Unsupported OIDC claim rule operator","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc.go","lineNumber":487,"sourceCode":"\t\tissuer, err := url.Parse(config.IssuerURL)\n\t\tif err != nil || issuer.Host == \"\" || issuer.User != nil || issuer.RawQuery != \"\" || issuer.Fragment != \"\" ||\n\t\t\t(issuer.Scheme != \"https\" && !util.IsLocalHostname(issuer.Hostname())) {\n\t\t\treturn errors.New(\"OIDC issuer URL must use HTTPS unless it is a loopback address\")\n\t\t}\n\t}\n\tif config.Provider != conf.OIDCProviderCustom && config.Provider != conf.OIDCProviderGoogle &&\n\t\tconfig.Provider != conf.OIDCProviderMicrosoft && config.Provider != conf.OIDCProviderGitHub {\n\t\treturn errors.New(\"Unsupported OIDC provider\")\n\t}\n\tif !config.AllowAll && len(config.ClaimRules) == 0 {\n\t\treturn errors.New(\"OIDC login requires at least one claim rule when Allow all users is disabled\")\n\t}\n\tfor _, rule := range config.ClaimRules {\n\t\tif rule == nil || rule.Claim == \"\" || len(rule.Values) == 0 {\n\t\t\treturn errors.New(\"OIDC claim rules must include a claim and at least one value\")\n\t\t}\n\t\tif rule.Operator != conf.OIDCClaimOperatorEquals && rule.Operator != conf.OIDCClaimOperatorContains {\n\t\t\treturn errors.New(\"Unsupported OIDC claim rule operator\")\n\t\t}\n\t\tfor _, value := range rule.Values {\n\t\t\tif value == \"\" {\n\t\t\t\treturn errors.New(\"OIDC claim rule values cannot be empty\")\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc ValidateOIDCMobileConfiguration(config *conf.OIDC) error {\n\tif err := ValidateOIDCConfiguration(config); err != nil {\n\t\treturn err\n\t}\n\tif config.Provider == conf.OIDCProviderGoogle {\n\t\treturn errors.New(\"Google does not support the fixed SiYuan mobile OIDC callback URI\")\n\t}\n\treturn nil","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/oidc.go#L469-L505","documentation":"Claim rule operators are restricted to the whitelisted set conf.OIDCClaimOperatorEquals and conf.OIDCClaimOperatorContains; any other operator string is rejected because the login check cannot evaluate it.","triggerScenarios":"ValidateOIDCConfiguration encounters a rule whose Operator differs from both OIDCClaimOperatorEquals and OIDCClaimOperatorContains (e.g. misspelled or custom operator value sent via the settings API).","commonSituations":"Hand-editing the config JSON with an operator like 'regex' or 'eq'; upgrading from an older/other schema with different operator names; typos when constructing rules programmatically.","solutions":["Set rule.Operator to conf.OIDCClaimOperatorEquals (\"equals\") for exact matching","Or use conf.OIDCClaimOperatorContains (\"contains\") for substring/list-contains matching","Check the constant values in kernel/conf to send the exact expected string over the API"],"exampleFix":"// before\nrule.Operator = \"regex\"\n// after\nrule.Operator = conf.OIDCClaimOperatorContains","handlingStrategy":"validation","validationCode":"const ops = ['equals', 'contains'];\nconst ok = rules.every(r => ops.includes(r.operator));","typeGuard":"const isKnownOperator = (op) => op === conf.OIDCClaimOperatorEquals || op === conf.OIDCClaimOperatorContains;","tryCatchPattern":"if err := ValidateOIDCConfiguration(cfg); err != nil {\n    if strings.Contains(err.Error(), \"operator\") { /* reset operator to a supported constant */ }\n}","preventionTips":["Only use the exported conf.OIDCClaimOperator* constants, never raw strings","Render the operator as a fixed dropdown instead of free text","Re-check constants when upgrading SiYuan versions"],"tags":["oidc","validation","enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}