Skip to content

fix: echo the authorize redirect_uri when exchanging the Slack install code - #327

Merged
fclairamb merged 1 commit into
mainfrom
fix/slack-install-redirect-uri
Sep 5, 2026
Merged

fclairamb merged 1 commit into
mainfrom
fix/slack-install-redirect-uri

Conversation

@fclairamb

Copy link
Copy Markdown
Owner

The bug

Installing Slack from the dashboard (/dash0/orgs/<org>/integrations/new) fails on production right after the user clicks Allow, bouncing to https://www.solidping.io/saas/install-error?reason=oauth_failed.

Production logs name the cause exactly:

level=ERROR msg="Failed to exchange OAuth code" error="slack API error: bad_redirect_uri"
level=ERROR msg="Slack OAuth exchange failed" error="OAuth exchange failed: slack API error: bad_redirect_uri"

Root cause

BuildInstallURL always sent a redirect_uri on the authorize request, but exchangeCodeAndFetchUser passed "" to oauth.v2.access, with a comment asserting the parameter was optional.

It is optional only when authorize did not use one. When authorize did send one, Slack requires the exchange to echo the identical value and rejects the install otherwise.

Why it went unnoticed

Two reasons, both worth recording:

  • Slack login was never affected. auth/slack_service.go:326 passes the callback URL at both ends, so signing in with Slack kept working and masked a completely broken install path. Discord was never affected either — it already funnels both call sites through one installRedirectURI() helper (discord/service.go:256,323).
  • No test ever drove a successful exchange. The only other test through this path (TestHandleOAuthCallback_StateConsumedOnReuse) deliberately relies on the exchange failing, and the sole redirect_uri assertion was on the authorize URL. The asymmetry was structurally invisible.

The fix

Both call sites now go through a single installRedirectURI() helper — the same shape Discord and Slack login already use, so they cannot drift again.

Test

TestHandleOAuthCallback_EchoesAuthorizeRedirectURIAtExchange asserts the exchange request, not just the authorize URL. It was confirmed to fail on the old code:

expected: "http://localhost:4000/api/v1/integrations/slack/oauth"
actual  : ""

It also carries a positive control pinning the concrete value, so a helper that returned "" on both sides would still fail.

QA

make build-backend lint-back test — all green (lint 0 issues, full backend suite passing).

Note for the deploy

This is a production fix; prod has silently lagged releases before, so it is worth confirming the running image actually picks this up rather than assuming the tag deployed.

🤖 Generated with Claude Code

…l code

Installing Slack from the dashboard died right after the user clicked
Allow, redirecting to /saas/install-error?reason=oauth_failed. Production
logs name the cause exactly:

    msg="Failed to exchange OAuth code" error="slack API error: bad_redirect_uri"

BuildInstallURL always sent a redirect_uri on the authorize request, but
exchangeCodeAndFetchUser passed "" to oauth.v2.access, with a comment
claiming the parameter was optional. It is optional only when authorize
did not use one — when it did, Slack requires the exchange to echo the
identical value, and rejects the whole install otherwise.

Both call sites now go through a single installRedirectURI() helper, the
same shape Discord already uses (discord/service.go:256,323) and the same
one Slack *login* uses (auth/slack_service.go:326) — which is why login
kept working and masked this for months.

The reason no test caught it: nothing ever drove a successful exchange.
The only other test through this path deliberately relies on the exchange
failing. The new test asserts the exchange REQUEST, not just the authorize
URL, and was confirmed to fail on the old code with
expected "http://localhost:4000/api/v1/integrations/slack/oauth", actual "".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fclairamb
fclairamb merged commit 7eed9a2 into main Sep 5, 2026
13 checks passed
@fclairamb
fclairamb deleted the fix/slack-install-redirect-uri branch September 5, 2026 15:42
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.

1 participant