{"record":{"id":"e7c7a25fea3290c6","repo":"siyuan-note/siyuan","slug":"oidc-redirect-url-is-required","errorCode":null,"errorMessage":"OIDC redirect URL is required","messagePattern":"OIDC redirect URL is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc_provider/provider.go","lineNumber":43,"sourceCode":"const (\n\tgoogleIssuer = \"https://accounts.google.com\"\n)\n\ntype Provider struct {\n\tkind         string\n\toauth2Config *oauth2.Config\n\tverifier     *oidc.IDTokenVerifier\n}\n\nfunc New(ctx context.Context, config *conf.OIDC, redirectURL string) (*Provider, error) {\n\tif config == nil {\n\t\treturn nil, errors.New(\"OIDC configuration is missing\")\n\t}\n\tif config.ClientID == \"\" {\n\t\treturn nil, errors.New(\"OIDC client ID is required\")\n\t}\n\tif redirectURL == \"\" {\n\t\treturn nil, errors.New(\"OIDC redirect URL is required\")\n\t}\n\tif config.Provider == conf.OIDCProviderGitHub && config.ClientSecret == \"\" {\n\t\treturn nil, errors.New(\"GitHub OAuth client secret is required\")\n\t}\n\tissuerURL := strings.TrimSpace(config.IssuerURL)\n\tswitch config.Provider {\n\tcase conf.OIDCProviderGoogle:\n\t\tissuerURL = googleIssuer\n\tcase conf.OIDCProviderMicrosoft:\n\t\t// Microsoft 多租户端点的 issuer 会随租户变化，必须使用租户专属 issuer。\n\tcase conf.OIDCProviderCustom:\n\tcase conf.OIDCProviderGitHub:\n\t\treturn newGitHub(config, redirectURL), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported OIDC provider [%s]\", config.Provider)\n\t}\n\tif issuerURL == \"\" {\n\t\treturn nil, errors.New(\"OIDC issuer URL is required\")","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/oidc_provider/provider.go#L25-L61","documentation":"Provider.New validates the OAuth2/OIDC construction inputs and refuses to build a Provider when the redirect URL argument is empty. The redirect URL is mandatory because every provider (Google, Microsoft, GitHub, custom) embeds it into the oauth2.Config used for the authorization-code flow; without it the AuthCodeURL and token exchange cannot work. This is a fail-fast guard rather than a runtime failure.","triggerScenarios":"Calling New(config, redirectURL) with redirectURL == \"\" — e.g. building the callback URL from a config field (conf.OIDC / model conf endpoint) that was never filled in, or from a request/HTTP host value that was empty at boot time.","commonSituations":"Self-hosted instances where the admin never set the external/callback URL; deployments behind a reverse proxy where the forwarded-host header is missing so the code computes an empty redirect URL; fresh configs saved before the callback field was populated; tests constructing a Provider with only a config struct.","solutions":["Set the redirect/callback URL in the OIDC configuration before calling New (must match the URI registered with the identity provider).","If the redirect URL is derived from request state, ensure the reverse proxy forwards Host / X-Forwarded-* headers and the code reads them before validation.","Validate the field at configuration-save time so an empty value can never reach New.","Update the saved conf via the settings API and retry the sign-in flow."],"exampleFix":"// before\nprovider, err := New(cfg, cfg.RedirectURL) // cfg.RedirectURL is \"\"\n// after\nif cfg.RedirectURL == \"\" {\n    cfg.RedirectURL = \"https://example.com/api/oidc/callback\"\n}\nprovider, err := New(cfg, cfg.RedirectURL)","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(redirectURL) == \"\" {\n    return errors.New(\"redirect URL must be configured before starting OIDC sign-in\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"redirect URL is required\") {\n        // surface a configuration error to the admin UI\n    }\n    return err\n}","preventionTips":["Make the callback/redirect URL a required field in the settings form with validation on save","Derive the redirect URL from explicit config, not from request-time headers that can be empty","Add a pre-flight config check on boot that logs all missing OIDC fields"],"tags":["oidc","oauth2","configuration","validation"],"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"}