The new Slack platform and the features described below are in beta and under active development.

External authentication

Make Slack your own digital HQ by writing custom functions that integrate with third-party applications, allowing you to personalize your workflows with accounts on compatible services!

With this, you can create new Jira tickets, aggregate data into Google Documents, and take action on tasks across other apps, all made possible with the OAuth 2.0 authorization framework.

Adding external auth to your app

The following steps will take you through integrating a third-party app with your new Slack app (with a little help by the Slack CLI):

  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 information about your third-party application provider and your third-party app in the DefineOAuth2Provider method, located inside your manifest.ts file.

Create an application on your provider site to fill in parameters, like token_url or client_id.

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

Using Google as an example, a very common external authentication provider, let's define the DefineOAuth2Provider method:

// 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",
    },
  },
});
// ...

Parameters

Field 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.

Update your app's configuration by declaring the externalAuthProviders field in your app's manifest:

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 using 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 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 access token in a custom function. In order to successfully complete this, the access token must be defined as an input paramter of type Schema.slack.types.oauth2 in your function definition.

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",
      },
      // Define token here
      googleAccessTokenId: {
        type: Schema.slack.types.oauth2,
        oauth2_provider_key: "google",
      },
      user: {
        type: Schema.slack.types.user_id,
        description: "The user invoking the workflow",
      },
    },
    required: ["message"],
  },
  output_parameters: {
    properties: {
      updatedMsg: {
        type: Schema.types.string,
        description: "Updated message to be posted",
      },
    },
    required: ["updatedMsg"],
  },
});

export default SlackFunction(
  SampleFunctionDefinition, // Define custom function
  async ({ inputs, client }) => {

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

    let updatedMsg = `:newspaper: Message for <@${inputs.user}>!\n\n>`;

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

    } else {
      // handle error response
    }

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

When running in the context of a workflow, retrieving your external access token will look a bit different. Pass the googleAccessTokenId as an empty input object to the workflow step within the function below:

const sampleFunctionStep = SampleWorkflow.addStep(SampleFunctionDefinition, {
  user: SampleWorkflow.inputs.user,
  googleAccessTokenId: {},
});

This input object will be automatically populated with the access token id created in the next step.

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.

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.

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

Run the command in the CLI, then choose the provider you are currently authenticating:

$ slack external-auth add

? Select a provider  [Use arrows to move, type to filter]
> Provider Key: google
  Provider Name: Google
  Client ID: <your_id>.apps.googleusercontent.com
  Client Secret Exists? Yes
  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  [Use arrows to move, type to filter]
> Provider Key: google
  Provider Name: Google
  Client ID: <your_id>.apps.googleusercontent.com
  Client Secret Exists? Yes
  Token Exists? Yes

If you see Token Exists? Yes, then a valid auth token has been created, meaning you're 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.

Command Description
$ slack external-auth remove Choose a provider to delete tokens for from 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.