siyuan-note/siyuan · error

OAuth authorization server does not support the authorizatio

Error message

OAuth authorization server does not support the authorization code grant

What it means

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.

Source

Thrown at kernel/mcp/client/oauth.go:258

		credential.AccessToken = ""
		credential.RefreshToken = ""
		credential.Expiry = time.Time{}
		if saveErr := putOAuthCredential(credential); saveErr != nil {
			logging.LogWarnf("mcp oauth: clear invalid credentials failed: %s", saveErr)
		}
	}
	if !interactive {
		setMCPRuntimeStateForContext(ctx, h.server.ID, "authorization_required", 0, "", "")
		return errOAuthAuthorizationRequired
	}
	if !slices.Contains(asm.CodeChallengeMethodsSupported, "S256") {
		return fmt.Errorf("OAuth authorization server does not support PKCE S256")
	}
	if len(asm.ResponseTypesSupported) > 0 && !slices.Contains(asm.ResponseTypesSupported, "code") {
		return fmt.Errorf("OAuth authorization server does not support the authorization code response type")
	}
	if len(asm.GrantTypesSupported) > 0 && !slices.Contains(asm.GrantTypesSupported, "authorization_code") {
		return fmt.Errorf("OAuth authorization server does not support the authorization code grant")
	}

	flowID := reusableOAuthFlowID(credential)
	if flowID == "" {
		flowID, err = secureRandomString(24)
		if err != nil {
			return err
		}
	}
	state, err := secureRandomString(24)
	if err != nil {
		return err
	}
	callbackURL := fmt.Sprintf("http://127.0.0.1:%s/api/ai/mcp/oauth/callback/%s", util.ServerPort, flowID)
	scopes := append([]string(nil), prm.ScopesSupported...)
	if len(scopes) == 0 {
		scopes = append(scopes, asm.ScopesSupported...)
	}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Enable the authorization_code grant on the AS and include 'authorization_code' in grant_types_supported.
  2. Confirm the discovered issuer matches the AS meant for interactive user login (check the resource's authorization_servers list).
  3. Use a different AS if the current one is intentionally client-credentials-only.
Defensive patterns

Strategy: validation

Validate before calling

asm, err := auth.GetAuthServerMetadata(ctx, issuerURL, http.DefaultClient)
if err != nil { return err }
if len(asm.GrantTypesSupported) > 0 && !slices.Contains(asm.GrantTypesSupported, "authorization_code") {
    return fmt.Errorf("AS must support the authorization_code grant")
}

Prevention

When it happens

Trigger: 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).

Common situations: Machine-to-machine only AS; service-account-only client configuration; metadata pointing at a different AS than the one intended for user login.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/edd75cb8bd37fdb1. Report an issue: GitHub.