siyuan-note/siyuan · error

OAuth authorization server does not support PKCE S256

Error message

OAuth authorization server does not support PKCE S256

What it means

Thrown during interactive OAuth authorization after the authorization server metadata (ASM) is fetched. The check at oauth.go:251 verifies that 'S256' is present in asm.CodeChallengeMethodsSupported. SiYuan's MCP OAuth client hard-requires PKCE with the S256 challenge method (it always calls oauth2.S256ChallengeOption), so an AS that omits or only offers 'plain' is rejected before any user-facing flow starts.

Source

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

			setMCPRuntimeStateForContext(ctx, h.server.ID, "oauth_retrying", 0, "", "")
			return nil
		}
		if !permanent {
			return fmt.Errorf("refresh OAuth credentials: %w", refreshErr)
		}
		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

View on GitHub (pinned to 251596fc0d)

Solutions

  1. On the authorization server, enable and advertise S256 in code_challenge_methods_supported (e.g. Authelia, Keycloak, hydra all support it by default — verify the field is present in the metadata JSON).
  2. Confirm the discovered issuer URL is the intended AS by checking the runtime-state / logs for which AuthorizationServers[0] was used; a wrong resource can pull the wrong AS metadata.
  3. If the AS genuinely cannot support S256, switch to a different authorization server or have the operator upgrade it; SiYuan cannot fall back to 'plain' PKCE by design.
Defensive patterns

Strategy: validation

Validate before calling

// Before launching interactive Authorize, fetch and inspect AS metadata once
// to fail fast with an actionable message rather than mid-flow.
asm, err := auth.GetAuthServerMetadata(ctx, issuerURL, http.DefaultClient)
if err != nil { return err }
if !slices.Contains(asm.CodeChallengeMethodsSupported, "S256") {
    return fmt.Errorf("AS %s must enable PKCE S256 in code_challenge_methods_supported", issuerURL)
}

Prevention

When it happens

Trigger: Calling mcpOAuthHandler.Authorize in interactive mode against a server whose /.well-known/oauth-authorization-server advertises code_challenge_methods_supported without 'S256' (e.g. only ['plain'], or the field absent). Non-interactive mode returns earlier with errOAuthAuthorizationRequired and never reaches this check.

Common situations: Legacy OAuth2 servers that predate RFC 7636; servers that only allow 'plain' PKCE; a custom AS that forgot to list S256; AS metadata fetched from a stale/incorrect issuer URL that returns a different document.

Related errors


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