Skip to content

Accept HTTP Basic client authentication at the token endpoint - #13

Merged
ebeigarts merged 1 commit into
mainfrom
bugfix/token-client-secret-basic
Oct 12, 2026
Merged

ebeigarts merged 1 commit into
mainfrom
bugfix/token-client-secret-basic

Conversation

@ebeigarts

Copy link
Copy Markdown
Member

Problem

POST /oauth/token read client_id and client_secret only from the request body, and /.well-known/oauth-authorization-server didn't list token_endpoint_auth_methods_supported. Without that field, clients default to client_secret_basic (RFC 8414) and send the credentials in an Authorization: Basic header. The server then saw an empty secret and answered 401 invalid_client.

RubyLLM 2.1 follows that default, so connecting the Mail connector from the AI platform fails with "Failed to complete OAuth authorization". The older ruby_llm-mcp gem sent the secret in the body, which is why it worked before.

Fix

  • Read client credentials from HTTP Basic auth when present (RFC 6749 §2.3.1, with the form-encoded user and password), falling back to the request body.
  • Advertise token_endpoint_auth_methods_supported: ["client_secret_basic", "client_secret_post"].

Tests

  • Added specs for a successful token exchange with HTTP Basic, a wrong secret over HTTP Basic, and the advertised methods; the first and last fail without the fix.
  • bundle exec rspec (Ruby 3.4.9): 86 examples, 0 failures. RuboCop: no offenses in the changed files.

After merging, this needs a release (1.0.4) and a bump of mcp/mail/Gemfile in the AI platform.

🤖 Generated with Claude Code

The token endpoint only read client_id and client_secret from the request
body, and the server metadata did not list token_endpoint_auth_methods_supported.
Clients then default to client_secret_basic (RFC 8414), which this server
rejected with invalid_client. RubyLLM 2.1 does exactly that, so connecting
from the AI platform failed.

Accept HTTP Basic credentials (RFC 6749 section 2.3.1) alongside the request
body, and advertise both methods.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 12, 2026 09:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Malformed credentials can cause a 500, and Basic authentication failures omit the required challenge header.

4 open findings
What changed in this PR

Adds HTTP Basic client authentication support to the OAuth token endpoint.

Changes:

  • Advertises Basic and POST client authentication methods.
  • Parses form-encoded Basic credentials.
  • Adds authentication and metadata specs.
File Description
lib/​mail_mcp/​app.rb Implements and advertises Basic authentication.
spec/​mail_mcp/​app_spec.rb Tests Basic authentication and discovery metadata.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/mail_mcp/app.rb
Comment on lines +153 to +154
auth = Rack::Auth::Basic::Request.new(request.env)
return [params[:client_id], params[:client_secret]] unless auth.provided? && auth.basic?
Comment thread lib/mail_mcp/app.rb
auth = Rack::Auth::Basic::Request.new(request.env)
return [params[:client_id], params[:client_secret]] unless auth.provided? && auth.basic?

auth.credentials.map { |part| URI.decode_www_form_component(part) }
Comment thread spec/mail_mcp/app_spec.rb
Comment on lines +101 to +102
it "accepts client credentials sent with HTTP Basic authentication" do
basic_authorize URI.encode_www_form_component(client_id), URI.encode_www_form_component(client_secret)
Comment thread spec/mail_mcp/app_spec.rb
Comment on lines +107 to +108
redirect_uri: redirect_uri,
client_id: client_id
@ebeigarts
ebeigarts merged commit 7f84d83 into main Oct 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants