{"record":{"id":"10d06a96ca18f3c8","repo":"siyuan-note/siyuan","slug":"oidc-issuer-url-is-required","errorCode":null,"errorMessage":"OIDC issuer URL is required","messagePattern":"OIDC issuer URL is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc.go","lineNumber":466,"sourceCode":"\treturn\n}\n\nfunc validateOIDCConfiguration() error {\n\treturn ValidateOIDCConfiguration(Conf.GetOIDC())\n}\n\nfunc ValidateOIDCConfiguration(config *conf.OIDC) error {\n\tif config == nil || !config.Enabled {\n\t\treturn errors.New(\"OIDC login is not enabled\")\n\t}\n\tif config.ClientID == \"\" {\n\t\treturn errors.New(\"OIDC client ID is required\")\n\t}\n\tif config.Provider == conf.OIDCProviderGitHub && config.ClientSecret == \"\" {\n\t\treturn errors.New(\"GitHub OAuth client secret is required\")\n\t}\n\tif (config.Provider == conf.OIDCProviderCustom || config.Provider == conf.OIDCProviderMicrosoft) && config.IssuerURL == \"\" {\n\t\treturn errors.New(\"OIDC issuer URL is required\")\n\t}\n\tif (config.Provider == conf.OIDCProviderCustom || config.Provider == conf.OIDCProviderMicrosoft) && config.IssuerURL != \"\" {\n\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\")","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/oidc.go#L448-L484","documentation":"For Custom and Microsoft providers, discovery starts from the issuer URL, so ValidateOIDCConfiguration requires config.IssuerURL to be non-empty for those providers. Missing it fails validation with \"OIDC issuer URL is required\" before any HTTP request is attempted.","triggerScenarios":"Calling ValidateOIDCConfiguration with Provider == OIDCProviderCustom or OIDCProviderMicrosoft and IssuerURL == \"\" — e.g. selecting a custom provider, enabling OIDC, and filling only client ID/secret.","commonSituations":"Switching from GitHub (which needs no issuer URL) to a custom provider without adding one; forgetting the issuer endpoint of an internal Keycloak/Authentik/Dex deployment; mobile config that copied only the client credentials.","solutions":["Set the provider's issuer URL (base issuer, typically no /well-known suffix) in the OIDC settings, e.g. https://accounts.example.com.","For Microsoft use the tenant-specific issuer such as https://login.microsoftonline.com/<tenant>/v2.0.","Confirm the URL serves the OpenID discovery document at <issuer>/.well-known/openid-configuration.","Re-save settings and rerun validation to confirm the error is gone."],"exampleFix":"// before\nconfig := &conf.OIDC{Enabled: true, Provider: conf.OIDCProviderCustom, ClientID: \"app\"}\n// after\nconfig := &conf.OIDC{Enabled: true, Provider: conf.OIDCProviderCustom, ClientID: \"app\", IssuerURL: \"https://id.example.com\"}","handlingStrategy":"validation","validationCode":"// Go: require issuer for custom/microsoft providers before login\nif (cfg.Provider == conf.OIDCProviderCustom || cfg.Provider == conf.OIDCProviderMicrosoft) && cfg.IssuerURL == \"\" {\n\treturn errors.New(\"set the issuer URL (e.g. https://id.example.com) for this provider\")\n}","typeGuard":"func hasIssuer(cfg *conf.OIDC) bool {\n\tif cfg == nil { return false }\n\tswitch cfg.Provider {\n\tcase conf.OIDCProviderCustom, conf.OIDCProviderMicrosoft:\n\t\treturn strings.TrimSpace(cfg.IssuerURL) != \"\"\n\tdefault:\n\t\treturn true\n\t}\n}","tryCatchPattern":"// JavaScript caller\ntry {\n  await startOIDCLogin();\n} catch (e) {\n  if (e.msg.includes(\"issuer URL is required\")) {\n    focusField(\"oidcIssuerURL\");\n  } else { throw e; }\n}","preventionTips":["Record the issuer base URL when registering the app with your IdP","Remember GitHub needs no issuer but custom/Microsoft always do","Confirm <issuer>/.well-known/openid-configuration responds before saving","Carry the issuer URL over when migrating configs between workspaces"],"tags":["oidc","configuration","issuer-url"],"backgroundTag":"missing-required-config-field","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"}