{"record":{"id":"d2d0f29b94909fa4","repo":"siyuan-note/siyuan","slug":"oidc-client-id-is-required-d2d0f2","errorCode":null,"errorMessage":"OIDC client ID is required","messagePattern":"OIDC client ID is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc_provider/provider.go","lineNumber":40,"sourceCode":"\t\"golang.org/x/oauth2\"\n)\n\nconst (\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)","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/oidc_provider/provider.go#L22-L58","documentation":"oidc_provider.New requires a non-empty ClientID because the OAuth2 client cannot build authorize/token requests without it. This is an upfront constructor validation alongside the redirect URL and GitHub client-secret checks.","triggerScenarios":"OIDCValidateStart, ValidateOIDCProviderConfiguration, or getOIDCProvider passes a conf.OIDC whose ClientID is empty — settings saved incompletely (client secret set but client ID blank), config edited by hand, or a config reset cleared the field.","commonSituations":"Admin saved the OIDC panel after clearing the client ID field; migrating config between workspaces lost the client ID; GitHub provider mode with secret but no ID; config file hand-edited with wrong JSON keys so ClientID unmarshals to empty.","solutions":["Fill in the Client ID in the OIDC settings panel (from the IdP/console) and save, then retry","Inspect the workspace conf to confirm the OIDC ClientID key is spelled correctly and non-empty","Call ValidateOIDCProviderConfiguration before starting login to get precise field-level errors in the UI","If using GitHub provider mode, also ensure ClientSecret is set (next check in the constructor)"],"exampleFix":"// before\nConf.OIDC = {ClientID: \"\", ClientSecret: \"abc\", Provider: \"generic\"}\n// after\nConf.OIDC = {ClientID: \"my-client-id\", ClientSecret: \"abc\", Provider: \"generic\"}","handlingStrategy":"validation","validationCode":"if cfg == nil || strings.TrimSpace(cfg.ClientID) == \"\" { return errors.New(\"OIDC client ID must be set in settings\") }","typeGuard":"func hasClientID(c *conf.OIDC) bool { return c != nil && c.ClientID != \"\" }","tryCatchPattern":"provider, err := oidcprovider.New(ctx, cfg, redirectURL)\nif err != nil && strings.Contains(err.Error(), \"client ID is required\") {\n    return nil, fmt.Errorf(\"open Settings - Auth and enter the client ID from your identity provider\")\n}","preventionTips":["Preflight-validate the settings form (client ID required) before saving","Watch for hand-edited configs with misspelled JSON keys silently emptying ClientID","When copying config between workspaces, verify client ID/secret survive the move"],"tags":["oidc","config","validation","client-id"],"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"}