@@ -45,17 +45,22 @@ undo it.
4545Connecting is the same decision as disconnecting, because ` replaceSlackConnection `
4646deletes every other Slack account row: a second person connecting * replaces* the
4747workspace's Slack, and every deployed agent then reads from and posts to whichever
48- Slack they installed. Hiding the button is not enough — ` authClient.oauth2.link `
49- is one POST.
48+ Slack they installed. Hiding the button is not enough. ` authClient.linkSocial `
49+ sends one POST.
5050
5151` slackConnectGuard ` (` packages/auth/src/slack-connect.ts ` ) is Better Auth's
5252` hooks.before ` , and it asks the same ` canManageConnections ` the API does. It
53- covers all three doors: ` /oauth2/link ` , ` /sign-in/oauth2 ` (Slack is a connection,
54- never a sign-in method, and that endpoint needs no session) and
55- ` /oauth2/callback/slack ` . The callback is the one that matters — refusing there
56- happens ** before the code is exchanged** , so a refused attempt writes no
53+ guards Slack account-linking starts through ` /link-social ` . Public Slack sign-in
54+ starts through ` /sign-in/social ` remain available to Better Auth. The guard also
55+ reads the server-generated OAuth state before ` /callback/slack ` . It guards the
56+ callback only when that state identifies an account-linking transaction. A
57+ normal Slack sign-in callback remains available to Better Auth. The callback
58+ check happens before Better Auth exchanges the code. A refused link writes no
5759` SlackWorkspaceGrant ` user token and deletes no bot token. Google and Microsoft
58- sign in on different paths and never reach the guard.
60+ callbacks never reach the Slack guard.
61+
62+ Existing Slack applications must replace ` /api/auth/oauth2/callback/slack ` with
63+ ` /api/auth/callback/slack ` before this upgrade reaches production.
5964
6065A workspace with no owner and no admin lets any member connect. There is nobody
6166left to ask, and a fresh install must not be locked out of its first connection.
0 commit comments