Overview

copied

OAuth is an authorization protocol that allows a client web application to access a server web application on behalf of a user using the user's own access token. Commander has OAuth integration built-in, allowing you to create commands that require the user to obtain an access token from a server web application to run a command.

GitHub Example

copied

How it works is best described using an example.

Let’s say you wanted to run a GitHub command in Slack that listed a set of issues in a private GitHub repository. A user running the command would want to run the command using their own access token. Commander's built-in OAuth integration makes that easy.

Before Commander OAuth can be used with GitHub, an administrator first needs to log into GitHub and add Commander as an allowed GitHub OAuth App (client). The administrator should then add GitHub as an OAuth provider to Commander, using Slack commands, with the necessary configuration values.

A Commander command to "list issues" can then be set to require authorization with the GitHub OAuth provider when the command is executed.

When the "list issues" command is run the first time, the user will be asked to run the Commander oauth_login command so Commander can obtain the user's GitHub access token. After the user logs in through GitHub, GitHub redirects the user's web browser to a Commander URL endpoint, passing a code. Commander then calls GitHub to convert the code to an access token and Commander stores that token, associating it with that specific Slack user.

When the "list issues" command is then run in Slack, Commander passes the user's GitHub access token to the command function and that function can use the user's token to access the GitHub API.

The user's GitHub access token is stored by Commander until it expires which is either a default amount of time or until the expiration of the access token expiration, if an expiration is provided in the callback by the OAuth provider.

A user can list their currently stored OAuth access tokens and expirations with a Commander token_list command. User's also have the ability to add and delete access tokens manually with token_add and token_delete commands.

Adding GitHub as an OAuth Provider

copied

Let's go into detail showing how to create a GitHub command that uses OAuth and a user's access token to run a GitHub command.

To start with, let's create GitHub as an OAuth provider in Commander by running oauth_create. Run these two commands in Commander:

  • /nc oauth_create github
  • /nc oauth_list

Create GitHub as an OAuth provider in Commander

Next, let's go into GitHub and allow Commander as a GitHub OAuth App (client). You can add an OAuth App under your own GitHub user profile using:

  • Profile→ Settings → Developer settings → OAuth Apps

or under your GitHub Organization using:

  • Profile → Settings → Your Organizations → Developer Settings → OAuth Apps

The following image shows where you can find "OAuth Apps" if you want to create it under your GitHub user Profile:

Find OAuth Apps under GitHub user profile

And this page shows how to create a GitHub app under your GitHub Organization:

https://docs.github.com/en/developers/apps/building-github-apps/creating-a-github-app

After selecting "Register a new application", you can fill out the OAuth application registration form. Add an Application name CommanderGitHub, a Homepage URL of https://nimbella.com and an Application description.

Enter an Authorization callback URL of https://apigcp.nimbella.io/api/v1/web/nc/commander/oauth-callback

Note: If you are using the enterprise version of Commander, you will need to use your internal hostname instead of "apigcp.nimbella.io"

Register a new OAuth application

After registering the application, you should generate a Client secret:

Generate a new Client secret

You should copy the Client secret because you will need it to set up GitHub as an OAuth provider in Commander:

Copy Client secret

After you have copied the Client secret, press "Update Application" at the bottom of the page.

That completes the configuration in GitHub. Now, let's go back to Slack so we can configure the OAuth provider in Commander.

We already created the GitHub OAuth provider in Commander but we haven't configured it. To configure it we will need to set a oauth_url, the URL that a user clicks on to start the authorization process. We also need to set the token_url, the URL that Commander needs to access to convert a callback token to a a user's token.

Configuring an oauth_url and token_url

copied

The oauth_url will need the "Client ID" shown on the OAuth App configuration page in GitHub. Github's authorization URL is https://github.com/login/oauth/authorize

You will also want to add a scope. Scopes are described here:

https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps

When the user clicks on an authorization URL in Commander, they are asking to generate an access token valid for the given scope. In this example, we set the scope in the authorization URL to "repo" which is "Grants full access to repositories, including private repositories."

Run the oauth_prop command with your client_id as follows to set the OAuth authorization URL for the github provider in Commander, replacing the client_id value with your Client ID:

/nc oauth_prop github oauth_url https://github.com/login/oauth/authorize?client_id=5f054b79123123123dbf&scope=repo

Note: If you cut and paste the Client ID from Github directly into Slack, Slack may try and format it as a Slack block. This will confuse Commander. It is best to create the /nc command above in a text editor and then paste it all into Slack at once if you want to cut and paste to prevent Slack from formatting individual components of the line on its own.

We also need to set up a token_url, this is a URL that Commander contacts are part of OAuth to receive a user's access token from the information given to it by GitHub's OAuth callback. The token_url for GitHub is https://github.com/login/oauth/access_token and to get an access token, GitHub requires us to also pass the Client ID and the Client secret for the OAuth App.

Configure the token_url for Github with the following command, setting the client_id to your Client ID and the client_secret to your Client secret:

/nc oauth_prop github token_url https://github.com/login/oauth/access_token?client_id=5f054b79123123123dbf&client_secret=75efc17745f12312312300d60cd0fa2f42212573

The configuration values for the oauth_url and token_url are specific to GitHub. Other OAuth providers will require different values. Consult the documentation for their OAuth integration to determine what parameters they require for the oauth_url and token_url.

Note: You'll notice that we configuring the token_url using GET format parameters. OAuth requires the request to the token_url to be a POST format request with body parameters. Internally, Commander automatically converts the GET requests parameters into POST body parameters to allow the token_url to be specified in GET request parameter format.

Testing GitHub OAuth Integration

copied

That completes the configuration of GitHub as an OAuth provider. We can test the integration by running:

/nc oauth_login github

You should get an GitHub authorization URL to click on that leads you through the authorization process. When the authorization process is complete, your webpage should show "Authorization complete." At that point, you can close the page and you can see if you have a GitHub access token in Commander by running:

/nc token_list

to show your current OAuth access tokens:

Show current OAuth access token

You can list the set of known OAuth providers in Commander with:

/nc oauth_list

Using OAuth tokens in a Command

copied

Let's create a command that uses the GitHub access token we created above with: /nc command_create testcmd

You can click the link to "edit the code"

In the code, you'll notice the function signature as:

async function _command(params, commandText, secrets = {}, token = null) {

The "token" parameter will contain the user's OAuth token. You can use that in your code to call the various GitHub APIs that require an OAuth access token.

We must tell Commander that the command requires an OAuth provider and which OAuth provider it requires using command_oauth:

/nc command_oauth testcmd github

Now, delete any existing github token you have:

/nc token_delete github

And run the command:

/nc testcmd

You'll notice that Commander asks you to run the /nc oauth_login github command to obtain an access token to run the command.

Once you have gone through the authorization process, you will be able to run the command. You can then change the code to access the GitHub API using the "token" parameter passed and have the function return results personalized to the Slack user running the command.

Creating a GitHub Command

copied

Let's create a GitHub command in Slack that uses OAuth to list the GitHub repos for a given GitHub organization:

/nc command_create repos <org>

Click on the "edit the code" link. Then change this code:

return {
  response_type: 'in_channel', // or `ephemeral` for private response  
  text: 'This is a default response for a newly created command with text: ' + commandText
};

to this:

const axios = require('axios');
let msg;
try {
  const response = await axios.get('https://api.github.com/orgs/' + org + '/repos', { 
    headers: { 
      Authorization: `Bearer ${token}`, 
      'accept': 'application/vnd.github.v3+json' 
    }
  });
  for (let i in response.data) {
    msg += response.data[i].name + "\n";
  }
} catch (err) {
  msg = 'ERROR: ' + JSON.stringify(err);
}
return {
  response_type: 'in_channel', // or `ephemeral` for private response
  text: '```' + msg + '```' // the backticks are used to format output as a Slack code block
};

We need to tell Commander that the repos command requires the GitHub OAuth provider:

/nc command_oauth repos github

You can then use that command to list the GitHub repos for the Nimbella organization:

/nc repos nimbella

If you want to give everyone in your workspace access to the repos command:

/nc command_runners repos + anyone

Note: The GitHub repos API call has a per_page parameter that by default is set to 30, to return 30 items per page. A different per_page can be set and/or a page parameter can be passed, to show items other than those that appear on the first page of results.

DigitalOcean Example

copied

DigitalOcean has an API that is accessed using OAuth access tokens. The documentation for the DigitalOcean OAuth protocol is available at:

https://docs.digitalocean.com/reference/api/oauth-api/

From their documentation, you can see the oauth_url (token request endpoint) for DigitalOcean is:

https://cloud.digitalocean.com/v1/oauth/authorize

The oauth-api reference page describes what parameters are required to be passed to that oauth_url. Specifically, the oauth_url requires: client_id, redirect-url and response_type.

Let's create an OAuth provider in Commander for DigitalOcean:

/nc oauth_create digitalocean

Next, we navigate to the API section of the DigitalOcean portal on the DigitalOcean website and we click "OAuth Applications."

There we can "Register OAuth Application" to create a Commander OAuth integration.

Register OAuth Application

Enter a callback URL of:

https://apigcp.nimbella.io/api/v1/web/nc/commander/oauth-callback

Note: If you are using the enterprise version of Commander, you will need to use your internal hostname instead of "apigcp.nimbella.io"

After registering the OAuth Application, we can click on it in the list to get the Client ID, Client Secret and authorization code link we need to complete configuration in Commander.

Complete Client Secret and authorization code link

Now in Commander, we can copy the "Link to authorization code" and set it as the oauth_url:

/nc oauth_prop digitalocean oauth_url https://cloud.digitalocean.com/v1/oauth/authorize?client_id=89e718cf&redirect_uri=https://apigcp.nimbella.io/api/v1/web/nc/commander/oauth-callback&response_type=code

And we can configure the token_url.

Note: In the examples here, we've shortened the client_id and client_secret for brevity

/nc oauth_prop digitalocean token_url https://cloud.digitalocean.com/v1/oauth/token?grant_type=authorization_code&client_id=89e718cf&client_secret=9b08d9&redirect_uri=https://apigcp.nimbella.io/api/v1/web/nc/commander/oauth-callback

That completes the setup of an OAuth provider for DigitalOcean. A command function can then be set to require a DigitalOcean access token using:

/nc command_oauth <command> digitalocean

When the command is run, it will ask the user to go through OAuth to obtain a DigitalOcean access token. The access token will be passed as an input parameter to the function where it can be used by the function to make requests to the DigitalOcean API.

Notice that DigitalOcean requires us to pass the redirect_uri in the oauth_url. GitHub does not require us to do that. DigitalOcean also requires the redirect_uri and grant_type to be passed in the token_url. OAuth providers are different on what they require for the oauth_url and token_url and that is why Commander allows them to be fully configured.