{"record":{"id":"910f209801dde44f","repo":"siyuan-note/siyuan","slug":"desktop-oidc-login-requires-a-loopback-listener","errorCode":null,"errorMessage":"Desktop OIDC login requires a loopback listener","messagePattern":"Desktop OIDC login requires a loopback listener","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc.go","lineNumber":549,"sourceCode":"\t\treturn nil\n\t}\n\tif requireRemoteRedirect {\n\t\tif _, err := validatePublicOIDCRedirectURL(config.RedirectURL); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn ValidateOIDCProviderConfiguration(ctx, config)\n}\n\nfunc effectiveOIDCRedirectURL(c *gin.Context, flow string) (string, error) {\n\tif flow == oidcFlowMobile {\n\t\treturn oidcMobileRedirectURL, nil\n\t}\n\tif flow == oidcFlowWeb && !IsLocalRequest(c) {\n\t\treturn validatePublicOIDCRedirectURL(Conf.GetOIDC().RedirectURL)\n\t}\n\tif !IsLocalRequest(c) {\n\t\treturn \"\", errors.New(\"Desktop OIDC login requires a loopback listener\")\n\t}\n\tscheme := \"http\"\n\tif c.Request.TLS != nil || c.GetHeader(\"X-Forwarded-Proto\") == \"https\" {\n\t\tscheme = \"https\"\n\t}\n\thost := c.Request.Host\n\tif !util.IsLocalHost(host) {\n\t\treturn \"\", errors.New(\"A loopback OIDC redirect URL is required for local access\")\n\t}\n\treturn scheme + \"://\" + host + \"/api/system/oidc/callback\", nil\n}\n\nfunc oidcValidationRedirectURL(c *gin.Context, config *conf.OIDC, mobile bool) (string, error) {\n\tif mobile {\n\t\treturn oidcMobileRedirectURL, nil\n\t}\n\tif config.RedirectURL != \"\" {\n\t\treturn validatePublicOIDCRedirectURL(config.RedirectURL)","sourceCodeStart":531,"sourceCodeEnd":567,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/oidc.go#L531-L567","documentation":"Desktop OIDC login intentionally only supports a loopback redirect: when the flow is desktop (not web/mobile) and the HTTP request originates from a non-local client, effectiveOIDCRedirectURL cannot build a safe redirect and returns this error instead of exposing the kernel to remote redirect manipulation.","triggerScenarios":"effectiveOIDCRedirectURL with flow == oidcFlowDesktop, IsLocalRequest(c) == false, and the request is neither the web flow nor using the mobile redirect URL; called from OIDCStart or oidcValidationRedirectURL.","commonSituations":"Starting desktop OIDC login from a browser on another machine pointed at the kernel's LAN/public address; reverse-proxy setup forwarding remote traffic without switching to the web flow or configuring a public redirect URL.","solutions":["Access SiYuan via localhost/127.0.0.1 when initiating desktop OIDC login","If remote access is intended, use the web flow so the configured public HTTPS RedirectURL is validated instead","Use the mobile flow, which has its own fixed redirect URL"],"exampleFix":"// before\nfetch(\"https://siyuan.example.com/api/system/oidc/start\") // desktop flow, remote\n// after\nfetch(\"http://127.0.0.1:6806/api/system/oidc/start\") // local loopback","handlingStrategy":"validation","validationCode":"const isLocal = ['127.0.0.1', 'localhost', '::1'].includes(location.hostname);\nif (!isLocal) console.warn('desktop OIDC start must be initiated from loopback');","typeGuard":null,"tryCatchPattern":"redirectURL, err := effectiveOIDCRedirectURL(c, oidcFlowDesktop)\nif err != nil {\n    http.Error(w, \"start OIDC login from http://127.0.0.1 or use the web/mobile flow\", 400)\n}","preventionTips":["Initiate desktop OIDC login from localhost only","Use the web flow with a public HTTPS redirect URL for remote access","Avoid reverse proxies on the desktop login path"],"tags":["oidc","network","redirect"],"backgroundTag":"insufficient-permissions","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"}