siyuan-note/siyuan · error

OAuth token endpoint returned unsupported token type

Error message

OAuth token endpoint returned unsupported token type %q

What it means

This client only accepts Bearer access tokens (comparison is case-insensitive; an empty token_type is tolerated). If the token endpoint returns a token of another type (e.g. 'N_A', 'pop', 'DPoP', or a MAC token), the obtained token cannot be used as a bearer credential and the flow fails with the offending type in the message.

Solutions

  1. Configure the authorization server to issue Bearer (access) tokens for this client
  2. If the server sends a nonstandard constant like N_A while tokens are effectively bearer tokens, normalize/patch the token endpoint response or file upstream for tolerance
  3. Switch to an authorization server that supports standard RFC 6750 bearer tokens
  4. Check server token profile settings (e.g. JWT vs reference token type settings) and set them to bearer
Defensive patterns

Strategy: validation

Validate before calling

// Inspect the token endpoint response profile during server onboarding
// and confirm token_type is bearer:
if tt := token.TokenType; tt != "" && !strings.EqualFold(tt, "Bearer") {
    return fmt.Errorf("server issues %q tokens; bearer required", tt)
}

Try / catch

if err := h.Authorize(ctx, true); err != nil {
    if strings.Contains(err.Error(), "unsupported token type") {
        // reconfigure the IdP to issue bearer tokens or choose a different server
    }
}

Prevention

When it happens

Trigger: config.Exchange succeeds, but token.TokenType is non-empty and not equal (case-insensitively) to "Bearer".

Common situations: Non-standard IdPs that return token_type values like N_A (some legacy Azure AD responses), MAC tokens, or DPoP-bound tokens; server misconfiguration returning wrong token_type in the JSON response.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/466d789b14739c2d. Report an issue: GitHub.

Appendix: source

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

	if callback.Error != "" {
		return fmt.Errorf("OAuth authorization failed: %s", callback.Error)
	}
	if callback.State != state {
		return fmt.Errorf("OAuth state mismatch")
	}
	if callback.Code == "" {
		return fmt.Errorf("OAuth callback did not include an authorization code")
	}

	exchangeCtx := context.WithValue(ctx, oauth2.HTTPClient, h.client)
	token, err := config.Exchange(exchangeCtx, callback.Code,
		oauth2.VerifierOption(verifier),
		oauth2.SetAuthURLParam("resource", prm.Resource))
	if err != nil {
		return fmt.Errorf("exchange OAuth authorization code: %w", err)
	}
	if token.TokenType != "" && !strings.EqualFold(token.TokenType, "Bearer") {
		return fmt.Errorf("OAuth token endpoint returned unsupported token type %q", token.TokenType)
	}
	credential = registrationCredential
	credential.TokenAuthMethod = authMethod
	credential.AccessToken = token.AccessToken
	credential.RefreshToken = token.RefreshToken
	credential.TokenType = token.TokenType
	credential.Expiry = token.Expiry
	credential.Scopes = scopes
	credential.Rejected = false
	if err = putOAuthCredential(credential); err != nil {
		return fmt.Errorf("save OAuth credentials: %w", err)
	}
	h.sourceMu.Lock()
	h.source = &storedOAuthTokenSource{credential: credential, client: h.client}
	h.sourceMu.Unlock()
	setMCPRuntimeStateForContext(ctx, h.server.ID, "oauth_retrying", 0, "", "")
	return nil
}

View on GitHub (pinned to 9f775e8a12)