Modern Slack apps are installed with a V2 OAuth 2.0 flow.
We're sorry about the double V2s: OAuth 2.0 refers to the 2.0 version of the OAuth spec, and this is our second version of OAuth 2.0. For the rest of this guide, we'll just call it OAuth and drop all the 2s.
The OAuth flow for Slack apps works exactly the same way as the OAuth flow for classic Slack apps. Only a few details have changed slightly: URL and method names have gained a v2
, and the shape of the OAuth access response now puts bot access tokens first.
We've created this V2 OAuth flow because it provides more granular Slack scopes, especially for bot users. With the new OAuth flow, your app can act with its own identity, instead of acting on behalf of users—all without requesting excessive permissions that could cause installs to be rejected.
OAuth lets a user in any Slack workspace install your app. At the end of OAuth, your app gains an access token.
Your app's access token opens the door to Slack API methods, events, and other features. During the OAuth flow, you specify which scopes your app needs. Those scopes determine exactly which doors (methods, events, and features) your app can unlock.
But first, let's talk about the elephant in the room: implementing an OAuth flow can feel discouragingly hard.
Here are some things that feel hard about OAuth:
Here are some corresponding, comforting facts:
<a href="https://slack.com/oauth/v2/authorize?scope=incoming-webhook&client_id=33336676.569200954261">Add to Slack</a>
Replace the scope=
with the scopes you'd like, and the client_id
with your app's Client ID, and you've already got the redirect down. You'll have a link that can initiate an OAuth install.
You can even turn that link into an Add to Slack button as we'll show later.
Your app gains an access token in three steps:
While developing your app, you'll figure out a minimum list of scopes that your app requires to work. When a user installs your app on their workspace, you'll request those same scopes.
To ask for scopes, redirect Slack users to https://slack.com/oauth/v2/authorize
.
If you're developing a GovSlack app for use by public sector customers, redirect users to https://slack-gov.com/oauth/v2/authorize
.
Include both your app's Client ID, found in the App Management page, and a comma-separated list of scopes: scope=incoming-webhook,commands
.
The full redirect URL will look something like:
https://slack.com/oauth/v2/authorize?scope=incoming-webhook,commands&client_id=3336676.569200954261
The scope
list requests scopes for your app's bot user. If you have specific need for a user token (say, to act on behalf of a user), provide a user_scope
parameter with requested user scopes instead of, or in addition to, the scope
parameter.
Consider the following: progressive permissions
Each trip through installation can result in additive scopes. For example, if a user installs your app into a workspace while you request channels:history
but then installs your app again while you ask for channels:read
then both channels:history
and channels:read
will be assigned to the token. There is no way to remove scopes from an existing token without revoking it entirely.
When you ask for scopes, you also need to tell Slack where to send your temporary authorization code afterward. Include a redirect_uri
parameter in the URL above. The redirect_uri
is where Slack will send the user back to, along with the temporary authorization code, once the user okays your app. The redirect_uri
must use HTTPS.
Alternatively, you can configure a Redirect URL in the App Management page under OAuth & Permissions. A Redirect URL must also use HTTPS.
If there are multiple Redirect URL values configured in the App Management page, and no redirect_uri
parameter is sent, then the OAuth flow will use the first Redirect URL listed on the App Management page.
You can even do both: use the redirect_uri
parameter in your oauth/v2/authorize
redirect, and configure a Redirect URL in the App Management page! If you do choose both, your redirect_uri
must match, or be a subdirectory, of a Redirect URL configured in your App Management page. A Redirect URL can not contain an anchor (#
).
REDIRECT_URL: https://example.com/path
GOOD redirect_uri: https://example.com/path
GOOD: https://example.com/path/subdir/other
BAD: http://example.com/bar
BAD: http://example.com/
BAD: http://example.com:8080/path
BAD: http://oauth.example.com:8080/path
BAD: http://example.org
Also, consider including the optional state
parameter. The state
parameter should be used to avoid forgery attacks—pass in a value that's unique to the user you're authenticating and check it when you receive a temporary authorization code.
team
parameter behavesWhen a valid team ID is passed to team
and the authenticating user is already signed in to that workspace, passing this parameter ensures the user will auth against that workspace.
If the user is not signed in yet, the user will be asked to specify a workspace to sign in to. That workspace will then be used as they complete the authorization flow, regardless of any team
parameter you provided when the flow began.
If you omit the optional team
parameter, the user will be allowed to choose which workspace they are authenticating against.
Good news: your app doesn't really have to do anything.
Prepare for the return of a user by listening for HTTP requests at whatever Redirect URL you specified in the above step.
If all's well, a user goes through the Slack app installation UI and okays your app with all the scopes that it requests. After that happens, Slack redirects the user back to your specified Redirect URL.
Parse the HTTP request that lands at your Redirect URL for a code
field. That's your temporary authorization code, which expires after ten minutes.
Check the state
parameter if you sent one along with your initial user redirect. If it doesn't match what you sent, consider the authorization a forgery.
Now you just have to exchange the code for an access token. You'll do this by calling the oauth.v2.access
method:
curl -F code=1234 -F client_id=3336676.569200954261 -F client_secret=ABCDEFGH https://slack.com/api/oauth.v2.access
Note: If you initiate an install with the v2/authorize
URL, it must be completed with oauth.v2.access
, not the old oauth.access
method.
After you complete your access call, Slack sends you an HTTP request response containing an access token. It looks like this:
{
"ok": true,
"access_token": "xoxb-17653672481-19874698323-pdFZKVeTuE8sk7oOcBrzbqgy",
"token_type": "bot",
"scope": "commands,incoming-webhook",
"bot_user_id": "U0KRQLJ9H",
"app_id": "A0KRD7HC3",
"team": {
"name": "Slack Softball Team",
"id": "T9TK3CUKW"
},
"enterprise": {
"name": "slack-sports",
"id": "E12345678"
},
"authed_user": {
"id": "U1234",
"scope": "chat:write",
"access_token": "xoxp-1234",
"token_type": "user"
}
}
If you requested scopes for a user token, you'll find them with a user access token under the authed_user
property.
Will my token expire? OAuth tokens do not expire. If they are no longer needed, they can be revoked. Revocation of an OAuth token happens if a workspace owner fully uninstalls the app; if users individually remove their configurations; or if the account of the user who initially authenticated the Slack app is deactivated.
With that, you've reached the OAuth finish line. After you show your installing user a joyful success message, your app can get to work.
Encapsulate the start of your OAuth flow into a neat and tidy "Add to Slack" button by using our generator below.
Looks like you don't have any apps yet.
Create an AppHere's a pop quiz: Why is there a third Exchanging step in OAuth at all? Why doesn't Slack send your app an access token directly after the user okays your app?
The reason is two-factor authentication. You have to prove both that you have the right temporary authorization code, and that you have your app's Client Secret, at the same time. It's like showing a passport to enter a new country: your visa (auth code) states a fact about the person described in the passport, but you still need the photo ID (Client Secret, in this case) to prove that you're the rightful owner of the passport.
One more note: show a user a nice message when the user is redirected back to you and you successfully gain an access token. Or, if there's been an error, transparently report that error to the user. The reason the user is redirected back to your app at the end of OAuth is exactly for the purpose of transparency: the user deserves to know the end of the story, whether your app successfully was installed or not.
Nearly all app actions are now performed from the perspective of the identity associated with your token: that's a bot user for a bot token, or regular user for a user token. Perspectival scopes (for example, chat:write:user
, chat:write:bot
, files:write:user
, files:write:bot
) are disappearing. Just use chat:write
and files:write
.
The best way to communicate your access tokens—also known as bearer tokens—to Slack is by presenting them in a request's Authorization
HTTP header where the full value, including "Bearer", is case-sensitive:
GET /api/conversations.list?limit=50
Authorization: Bearer xoxb-1234-abcdefgh
This approach is required when using application/json
with a write method.
Alternatively, you may send the token as a POST body attribute of the application/x-www-form-urlencoded
variety:
POST body:
POST /api/conversations.list
Content-type: application/x-www-form-urlencoded
token=xoxb-1234-abcdefgh&limit=50
Note: We no longer allow new apps to send the token as a querystring.
API access tokens are still revoked in the same way, via the auth.revoke
method. When that happens:
commands
scope.Store your application's credentials and user tokens with care. Read our article on safely storing credentials.
Restrict Web API access to only IP addresses you trust by whitelisting specific IP addresses.
If you still need to create a classic Slack app, either to use the rtm.connect
method, or for any other reason, click here:
You can continue to distribute it via the first version of OAuth 2.0.