{"record":{"id":"edd75cb8bd37fdb1","repo":"siyuan-note/siyuan","slug":"oauth-authorization-server-does-not-support-the-au-edd75c","errorCode":null,"errorMessage":"OAuth authorization server does not support the authorization code grant","messagePattern":"OAuth authorization server does not support the authorization code grant","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/client/oauth.go","lineNumber":258,"sourceCode":"\t\tcredential.AccessToken = \"\"\n\t\tcredential.RefreshToken = \"\"\n\t\tcredential.Expiry = time.Time{}\n\t\tif saveErr := putOAuthCredential(credential); saveErr != nil {\n\t\t\tlogging.LogWarnf(\"mcp oauth: clear invalid credentials failed: %s\", saveErr)\n\t\t}\n\t}\n\tif !interactive {\n\t\tsetMCPRuntimeStateForContext(ctx, h.server.ID, \"authorization_required\", 0, \"\", \"\")\n\t\treturn errOAuthAuthorizationRequired\n\t}\n\tif !slices.Contains(asm.CodeChallengeMethodsSupported, \"S256\") {\n\t\treturn fmt.Errorf(\"OAuth authorization server does not support PKCE S256\")\n\t}\n\tif len(asm.ResponseTypesSupported) > 0 && !slices.Contains(asm.ResponseTypesSupported, \"code\") {\n\t\treturn fmt.Errorf(\"OAuth authorization server does not support the authorization code response type\")\n\t}\n\tif len(asm.GrantTypesSupported) > 0 && !slices.Contains(asm.GrantTypesSupported, \"authorization_code\") {\n\t\treturn fmt.Errorf(\"OAuth authorization server does not support the authorization code grant\")\n\t}\n\n\tflowID := reusableOAuthFlowID(credential)\n\tif flowID == \"\" {\n\t\tflowID, err = secureRandomString(24)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tstate, err := secureRandomString(24)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcallbackURL := fmt.Sprintf(\"http://127.0.0.1:%s/api/ai/mcp/oauth/callback/%s\", util.ServerPort, flowID)\n\tscopes := append([]string(nil), prm.ScopesSupported...)\n\tif len(scopes) == 0 {\n\t\tscopes = append(scopes, asm.ScopesSupported...)\n\t}","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/mcp/client/oauth.go#L240-L276","documentation":"Thrown at oauth.go:257-258 when grant_types_supported is non-empty and excludes 'authorization_code'. SiYuan's flow is built exclusively on the authorization-code grant (with optional refresh_token), so an AS that advertises only client_credentials/implicit/etc. is rejected up front.","triggerScenarios":"Interactive Authorize against an AS whose metadata has grant_types_supported = ['client_credentials'] or ['implicit'] without 'authorization_code'. The check is skipped when the field is absent (treated as permissive).","commonSituations":"Machine-to-machine only AS; service-account-only client configuration; metadata pointing at a different AS than the one intended for user login.","solutions":["Enable the authorization_code grant on the AS and include 'authorization_code' in grant_types_supported.","Confirm the discovered issuer matches the AS meant for interactive user login (check the resource's authorization_servers list).","Use a different AS if the current one is intentionally client-credentials-only."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"asm, err := auth.GetAuthServerMetadata(ctx, issuerURL, http.DefaultClient)\nif err != nil { return err }\nif len(asm.GrantTypesSupported) > 0 && !slices.Contains(asm.GrantTypesSupported, \"authorization_code\") {\n    return fmt.Errorf(\"AS must support the authorization_code grant\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate grant_types_supported at onboarding.","Ensure 'refresh_token' is also enabled to benefit from SiYuan's silent refresh path."],"tags":["oauth","mcp","grant-type","metadata","authorization-server"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}