The new Slack platform is in beta. Your feedback is most welcome.

External authentication

Write Functions that integrate with third-party applications to increase the functionality of your next-generation Slack app.

Whether you are creating a new Jira ticket, aggregating data into a Google Document, receiving notifications or taking action on tasks, integrating with third-party apps puts the ease of your workflows all-into-one, seamlessly with the new CLI.

This guide will walk-through the following steps you need to integrate a third-party app with your new Slack app using the OAuth2 authentication framework.

  1. Add external auth info to your app manifest
  2. Add client secrets to your deployed app
  3. Add OAuth2 to your function
  4. Initialize the OAuth flow

1. Add external auth info to your app manifest

The first thing you'll need to do is define key information about your third-party application provider and your third-party app in the DefineOAuth2Provider method construct inside your manifest.ts file.

Create an application on your provider site and use that information to fill in the DefineOAuth2Provider method parameters, like token_url.

Redirect URL
When creating an app on your third-party provider site, set the redirect URL to https://oauth2.slack.com/external/auth/callback.

The example we'll be using throughout this guide is a common external authentication provider, Google:

// manifest.ts 

import {
  DefineFunction,
  DefineOAuth2Provider,
  DefineWorkflow,
  Manifest,
  Schema,
} from "deno-slack-sdk/mod.ts";

// ...

const GoogleProvider = DefineOAuth2Provider({
  provider_key: "google",
  provider_type: Schema.providers.oauth2.CUSTOM,
  options: {
    "provider_name": "Google",
    "authorization_url": "https://accounts.google.com/o/oauth2/auth",
    "token_url": "https://oauth2.googleapis.com/token",
    "client_id":
      "<your_client_id>.apps.googleusercontent.com",
    "scope": [
      "https://www.googleapis.com/auth/spreadsheets.readonly",
      "https://www.googleapis.com/auth/userinfo.email",
      "https://www.googleapis.com/auth/userinfo.profile",
    ],
    "authorization_url_extras": {
      "prompt": "consent",
      "access_type": "offline",
    },
    "identity_config": {
      "url": "https://www.googleapis.com/oauth2/v1/userinfo",
      "account_identifier": "$.email",
    },
  },
});
// ...

DefineOAuth2Provider requires the following fields:

Parameter Type Description
provider_key string The unique string identifier for a provider. An app cannot have two providers with the same unique identifier. Changing unique identifier will be treated like deletion of a provider. Providers cannot be deleted if there are active tokens tied to providers.
provider_type string The only supported provider type value at this time is CUSTOM.
provider_name string The name of your provider.
client_id string The client ID from your external authentication provider.
authorization_url string This is an OAuth2 requirement to complete the oauth flow and to direct the user to the provider consent screen.
token_url string This is an OAuth2 requirement to complete the oauth flow and to exchange the code with an access token.
scope array This is an OAuth2 requirement to complete the oauth flow and to grant only the scopes provided to the access token.
identity_config object Used to obtain user identity by finding the account associated with the email. Must include url (the endpoint the provider exposes to fetch user identity) and account_identifier (the field in the response that represents the identity).
authorization_url_extras object (Optional) This is for providers who require additional query parameters in their authorize_url.

After defining your OAuth2 provider, add it to the manifest definition.

Locate the externalAuthProviders property and add it there. This property will house all auth providers. For example, your manifest definition might look something like this:

export default Manifest({
  name: "Reverse string with external auth",
  description: "Reverse a string",
  icon: "assets/icon.png",
  functions: [ReverseFunction],
  outgoingDomains: [],
  botScopes: ["commands", "chat:write", "chat:write.public"],
  externalAuthProviders: [GoogleProvider],
  workflows: [MyWorkflow],
});

2. Add client secrets to your deployed app

With your Oauth2 provider configured, you'll need to deploy your app with slack deploy.

After the app is deployed with the provider configuration, use slack external-auth add-secret to add client secrets for the configured provider:

slack external-auth add-secret --provider the_provider_key --secret secret_for_provider

In our example, our provider is google and our secret key is 123abc. Therefore, the command would be:

slack external-auth add-secret --provider google --secret 123abc

Reissue the command to update any previously created client secret for the provider.

Once your provider's client secret has been added or updated, you can view more details about the providers you have configured with external-auth add:

slack external-auth add

This will show you a list of providers, along with each client_id, whether a client secret exists, and whether valid tokens exist, which help to ensure that the app is able to communicate with the configured provider smoothly via OAuth2.

3. Add OAuth2 to your Function

Access your provider key in a Custom function by adding a Schema.slack.types.oauth2](/future/types) type as an input parameter.

To do this, you need to create a SlackAPI client in order to make a call to apps.auth.external.get. This will retrieve your key to be used later in your function.

As an example, let's modify the sample function that comes with the Starter App template:

import { DefineFunction, Schema, SlackFunction } from "deno-slack-sdk/mod.ts";
import { SlackAPI } from "deno-slack-api/mod.ts";

export const SampleFunctionDefinition = DefineFunction({
  callback_id: "sample_function",
  title: "Sample function",
  description: "A sample function",
  source_file: "functions/sample_function.ts",
  input_parameters: {
    properties: {
      message: {
        type: Schema.types.string,
        description: "Message to be posted",
      },
      // Note how we add it here:
      googleAccessToken: {
        type: Schema.slack.types.oauth2,
        oauth2_provider_key: "google",
      },
    },
    required: ["message"],
  },
  output_parameters: {
    properties: {
      updatedMsg: {
        type: Schema.types.string,
        description: "Updated message to be posted",
      },
    },
    required: ["updatedMsg"],
  },
});

export default SlackFunction(
  SampleFunctionDefinition,
  ({ inputs, env, token }) => {

    const client = SlackAPI(token, { slackApiUrl: env["SLACK_API_URL"] });

    // Get the token:
    const res = await client.apiCall("apps.auth.external.get", {
      external_token_id: inputs.googleAccessToken,
    });

    let updatedMsg = `:wave: Here's what I have to say: \n\n>`;

    // If the token was retrieved successfully, use it:
    if (res.ok) {
      const externalToken = res.external_token;
      // Make external API call with externalToken
      // let myApiResponse = await fetch(...)
      updatedMsg += myApiResponse.message

    } else {
      // handle error response
    }

    return { outputs: { updatedMsg } };
  },
);

4. Initialize the OAuth2 flow

The final step is to initialize the OAuth2 sign-in flow, which will connect your external provider account to your Slack app.

The provider key, name, and the client ID defined in your manifest will be listed out, along with any other providers you've authenticated.

On the CLI, run the command slack external-auth add, then choose the provider you are currently authenticating:

$ slack external-auth add

? Select a provider to connect your account to  [Use arrows to move, type to filter]
> Provider Key: google
  Provider Name: Google
  Client ID: <your_id>.apps.googleusercontent.com
  client_secret exists? yes
  valid token exists? no

Once selected, you'll be redirected to a browser window where Slack will ask for permission to use your credentials to authenticate your provider account.

Grant the permissions by accepting or continuing the flow in the browser.

When finished, verify that a valid token has been created by re-running the external-auth add command:

$ slack external-auth add

? Select a provider to connect your account to  [Use arrows to move, type to filter]
> Provider Key: google
  Provider Name: Google
  Client ID: <your_id>.apps.googleusercontent.com
  client_secret exists? yes
  valid token exists? yes

If you see valid token exists? yes, then a valid auth token is available and you are set up and ready to rely on OAuth2 in your app.

Delete external auth tokens

If you'd like to delete your tokens and remove authentication from your Slack app, the following commands will help you do so.

Select a provider to delete tokens for via terminal:

Command Description
$ slack external-auth remove Choose a provider to delete tokens for form the list displayed
$ slack external-auth remove --all Delete all tokens for the app by specifying the --all flag
$ slack external-auth remove --provider provider_name --<app_name> Delete all tokens for a provider by specifying the --provider flag

Have 2 minutes to provide some feedback?

We'd love to hear about your experience with the new Slack platform. Please complete our short survey so we can use your feedback to improve.