patchbay audit
·5 min read

Why MCP OAuth login hangs after you click Allow and how to fix it

You add a remote MCP server to Claude Code, Claude Desktop or another native client. The browser opens, you sign in, you click Allow. Then nothing. The client keeps waiting, or the browser shows an invalid_redirect_uri error and the server never shows up as connected.

If the server uses OAuth, the most likely cause is on the server side: its authorization server does not accept loopback redirect URIs with an arbitrary port. This post explains why that breaks every native client, how to confirm it in one command and what to change.

Why native clients need a loopback redirect

A web app finishes the OAuth authorization code flow on a public HTTPS callback URL. A CLI or desktop app has no such URL. Instead it opens a temporary HTTP listener on the local machine and tells the authorization server to redirect there:

http://127.0.0.1:53124/callback

The port is assigned by the operating system when the login starts, so it is different every time. The client cannot know it in advance and cannot pre-register it.

RFC 8252 section 7.3 covers exactly this case. It says the authorization server must allow any port to be specified at the time of the request for loopback IP redirect URIs, so that clients can use an ephemeral port. OAuth 2.1 carries the same rule forward.

Where it goes wrong

Many authorization servers validate redirect URIs by exact string match. That is the right default for web clients and it is wrong for loopback. There are two places it bites:

  • At registration. MCP clients register themselves through Dynamic Client Registration (RFC 7591). If the registration endpoint rejects http://127.0.0.1:PORT/callback outright, the client never gets a client_id and the flow stops before the browser opens.
  • At authorization. Registration succeeds with one port, but the next login uses a different one. Exact matching now fails and the user sees the error only after clicking Allow.

Both look the same from the outside: login does not complete in any CLI or desktop client, while the same server may work fine from a web-based client with a fixed callback URL.

Confirm it in one command

patchbay audit has an opt-in probe for this. It attempts a client registration with loopback redirect URIs and reports whether the server accepted them:

npx -y @patchbay-nebius/agent audit https://mcp.example.com/mcp --probe-dcr-loopback

If the registration endpoint refuses loopback URIs you get finding AUTH-006 at high severity, with the HTTP status the server returned. The probe is opt-in because it sends a real registration request, so run it against servers you operate or have permission to test. If the server has no registration endpoint at all, that is a different finding, AUTH-005.

For the checks that need no flags, you can also paste the URL into the browser scanner.

The fix

The rule to implement in redirect URI validation is short:

  1. If the registered redirect URI has scheme http and host 127.0.0.1 or [::1], compare scheme, host and path and ignore the port.
  2. Accept those URIs in Dynamic Client Registration, with any port.
  3. Keep exact matching for everything else and keep rejecting plain http:// for every non-loopback host.

On localhost: RFC 8252 section 8.3 recommends the IP literal over the hostname, because localhost can resolve to something unexpected. Many clients still send http://localhost:PORT/callback, so in practice you want to accept both forms and treat them the same. A server that accepts one and rejects the other is its own interop bug, covered by REDIRECT-001.

If you use a hosted identity provider, look for a setting named something like "native application", "loopback redirect" or "allow any port" before writing custom validation. Most providers support this; it is often just not enabled for clients created through dynamic registration.

If it is not your server

As a user you cannot work around this from the client side. What helps the maintainer most is a precise report: the client you used, the fact that login hangs after consent and a link to RFC 8252 section 7.3. If you run the audit with --publish, you get a report URL you can attach to the issue.

Keep it from regressing

Redirect validation tends to get tightened again during later security reviews. Put the audit in CI so the build fails if loopback registration stops working:

npx -y @patchbay-nebius/agent audit https://mcp.example.com/mcp --probe-dcr-loopback --ci --fail-on=high

The CLI is MIT licensed and runs locally: github.com/GodSmasher/patchbay. The full list of checks is in the findings reference.