You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An app that can start a Slack install from more than one place — a public landing page and some other page, say — can't send the user back to where they started. Every install ends on the one configured SuccessRedirectUri, so an admin who installs a workspace from an admin screen is dropped on the public success page and has to navigate back by hand.
Slack round-trips the standard OAuth state parameter untouched (per its docs — worth confirming on a real install), but SlackbotCodeTokenExchangeMiddleware never reads it, so a host has no way to carry any context of its own through the flow.
The scope is only the callback half. The host already builds its own slack.com/oauth/v2/authorize?... url and can append &state= today; the value just gets dropped on the way back in source/src/Slackbot.Net.Endpoints/Middlewares/SlackbotCodeTokenExchangeMiddleware.cs.
What would solve it: on a successful install, redirect to state when it holds a site-relative path, resolved against SuccessRedirectUri's origin so it stays on the same site, and fall back to SuccessRedirectUri otherwise. Absolute and protocol-relative (//host) values need to be ignored, or the callback turns into an open redirect.
state is also OAuth's CSRF parameter, so this has to leave apps already using it that way alone. A random nonce doesn't start with /, so it falls through to SuccessRedirectUri and nothing changes for them — with one exception worth guarding: standard base64 includes /, so a base64 nonce starting with one would be mistaken for a path. Either require an opt-in on OAuthOptions, or demand more of the value than a leading slash.
Handing the raw state to IWorkspaceInstallationHandler and letting the host decide what it means would work just as well, though it changes the handler contract and so needs a major bump — the only real requirement is that the value survives the callback instead of being dropped.
SuccessRedirectUri, so an admin who installs a workspace from an admin screen is dropped on the public success page and has to navigate back by hand.stateparameter untouched (per its docs — worth confirming on a real install), butSlackbotCodeTokenExchangeMiddlewarenever reads it, so a host has no way to carry any context of its own through the flow.slack.com/oauth/v2/authorize?...url and can append&state=today; the value just gets dropped on the way back insource/src/Slackbot.Net.Endpoints/Middlewares/SlackbotCodeTokenExchangeMiddleware.cs.statewhen it holds a site-relative path, resolved againstSuccessRedirectUri's origin so it stays on the same site, and fall back toSuccessRedirectUriotherwise. Absolute and protocol-relative (//host) values need to be ignored, or the callback turns into an open redirect.stateis also OAuth's CSRF parameter, so this has to leave apps already using it that way alone. A random nonce doesn't start with/, so it falls through toSuccessRedirectUriand nothing changes for them — with one exception worth guarding: standard base64 includes/, so a base64 nonce starting with one would be mistaken for a path. Either require an opt-in onOAuthOptions, or demand more of the value than a leading slash.statetoIWorkspaceInstallationHandlerand letting the host decide what it means would work just as well, though it changes the handler contract and so needs a major bump — the only real requirement is that the value survives the callback instead of being dropped.