{"record":{"id":"288bb1901a748925","repo":"AlistGo/alist","slug":"invalid-request","errorCode":null,"errorMessage":"invalid request","messagePattern":"invalid request","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"server/handles/ssologin.go","lineNumber":296,"sourceCode":"\t\t\t\t</body>`, token)\n\t\tc.Data(200, \"text/html; charset=utf-8\", []byte(html))\n\t\treturn\n\t}\n}\n\nfunc SSOLoginCallback(c *gin.Context) {\n\tenabled := setting.GetBool(conf.SSOLoginEnabled)\n\tusecompatibility := setting.GetBool(conf.SSOCompatibilityMode)\n\tif !enabled {\n\t\tcommon.ErrorResp(c, errors.New(\"sso login is disabled\"), 500)\n\t\treturn\n\t}\n\targument := c.Query(\"method\")\n\tif usecompatibility {\n\t\targument = path.Base(c.Request.URL.Path)\n\t}\n\tif !utils.SliceContains([]string{\"get_sso_id\", \"sso_get_token\"}, argument) {\n\t\tcommon.ErrorResp(c, errors.New(\"invalid request\"), 500)\n\t\treturn\n\t}\n\tclientId := setting.GetStr(conf.SSOClientId)\n\tplatform := setting.GetStr(conf.SSOLoginPlatform)\n\tclientSecret := setting.GetStr(conf.SSOClientSecret)\n\tvar tokenUrl, userUrl, scope, authField, idField, usernameField string\n\tadditionalForm := make(map[string]string)\n\tswitch platform {\n\tcase \"Github\":\n\t\ttokenUrl = \"https://github.com/login/oauth/access_token\"\n\t\tuserUrl = \"https://api.github.com/user\"\n\t\tauthField = \"code\"\n\t\tscope = \"read:user\"\n\t\tidField = \"id\"\n\t\tusernameField = \"login\"\n\tcase \"Microsoft\":\n\t\ttokenUrl = \"https://login.microsoftonline.com/common/oauth2/v2.0/token\"\n\t\tuserUrl = \"https://graph.microsoft.com/v1.0/me\"","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/server/handles/ssologin.go#L278-L314","documentation":"Returned by SSOLoginCallback when the requested method is neither 'get_sso_id' nor 'sso_get_token'. The method argument comes from the ?method= query parameter, or — in SSO compatibility mode — from the last path segment of the callback URL. The two allowed values correspond to the two callback phases: fetch the SSO user id vs. exchange it for an application token.","triggerScenarios":"Hitting the callback URL with ?method=missing/typo'd, or in compatibility mode with a path like /api/auth/sso_callback/get-user that does not end in one of the two allowed segments.","commonSituations":"IdP configured with a callback URL whose final path segment is wrong for compatibility mode; frontend updated to the query-string protocol against an older backend; manual testing of the endpoint with arbitrary paths.","solutions":["Call the endpoint with ?method=get_sso_id (phase 1) or ?method=sso_get_token (phase 2)","In compatibility mode, make the callback URL end with /get_sso_id or /sso_get_token (e.g. /api/auth/sso_callback/get_sso_id)","Match the frontend and backend versions so both use the same method-passing convention"],"exampleFix":"// before\nGET /api/auth/sso_callback?method=get_user\n// after\nGET /api/auth/sso_callback?method=get_sso_id","handlingStrategy":"validation","validationCode":"allowed := map[string]bool{\"get_sso_id\": true, \"sso_get_token\": true}\nmethod := c.Query(\"method\")\nif useCompatibility {\n    method = path.Base(c.Request.URL.Path)\n}\nif !allowed[method] {\n    return errors.New(\"method must be get_sso_id or sso_get_token\")\n}","typeGuard":null,"tryCatchPattern":"if resp.StatusCode() == 500 && strings.Contains(resp.String(), \"invalid request\") {\n    // wrong method name/path — re-issue with ?method=get_sso_id or the compatibility path suffix\n}","preventionTips":["Construct callback URLs from constants, not string literals scattered in config","In compatibility mode, end the IdP callback URL with /get_sso_id or /sso_get_token","Pin frontend and backend versions so both agree on query-param vs path-segment method passing"],"tags":["sso","auth","http-api","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}