Installing with OAuth

The rundown
Read this if:You're still experimenting, prototyping, and exploring.
Read first:Installation & permissions
Read next:Verifying requests from Slack
Open beta for new Slack apps

This sneaky preview gives you access to new features in Slack apps. Since we're still finalizing these apps, a few features may not yet have arrived. We expect the final version of new Slack apps to be available within a few months.

New 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 new 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.

Overview

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: that implementing an OAuth flow is discouragingly hard.

Here are some things about that feel hard about OAuth:

  1. There are a lot of steps, with multiple participants.
  2. Your app has to be able to redirect a user to Slack, and your app also has to handle a user being redirected back to the app.

Here are some corresponding, comforting facts:

  1. There are a lot of steps, but... Your app only has to worry about three steps to make OAuth work: Asking for scopes, waiting for a user to give the okay, and exchanging a temporary code for a full access token.
  2. Your app has to handle redirects, but... Redirecting a user to Slack can be done with a single Add to Slack button! For example:
<a href="https://slack.com/oauth/v2/authorize?scope=incoming-webhook&client_id=33336676.569200954261"><img alt=""Add to Slack"" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/add_to_slack@2x.png 2x" /></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 button like this that initiates an OAuth install:

Add to Slack

Obtaining access tokens with OAuth 2.0

Your app gains an access token in three steps:

  1. Asking for scopes
  2. Waiting for a user to approve your requested scopes
  3. Exchanging a temporary authorization code for an access token

Negotiating tokens with Slack's OAuth 2.0 authorization flow

Asking for scopes

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 a Slack user to https://slack.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 or to access Real Time Messaging), provide a user_scope parameter with requested user scopes instead of, or in addition to, the scope parameter.

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.

Alternatively, you can configure a Redirect URL in the App Management page under OAuth & Permissions.

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 one of the Redirect URLs configured in your App Management page.

Waiting for a user to approve your requested scopes

This step's the easiest: your app doesn't really have to do anything.

Simply prepare for the return of a user by listening for HTTP requests at whatever Redirect URL you specified in the above step.

Exchanging a temporary authorization code for an access token

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.

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.

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.

Extra credit

A little motivation

Here's a pop quiz: Why is there a third Exchanging step in OAuth at all? Why doesn't Slack simply 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.

Perspectival scopes

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.

Revoking tokens

API access tokens are still revoked in the same way, via the auth.revoke method. When that happens:

  • The bot token no longer works.
  • The bot user is removed from the workspace.
  • Slash commands associated with the bot token will be removed from the workspace if no user tokens for the same app exist and carry the commands scope.
  • Incoming webhooks that were installed and associated with the bot token will be removed.
  • If no user tokens for the same app exist, the app will appear to be uninstalled from the workspace.

Storing tokens securely

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.