I’m currently trying to build a little Slack app. The (Botkit based) app is a “slash command” that also needs access to the team and user info Slack web API methods.
I ran into a problem where I needed an access token that Botkit stores in its users object store. The issue is that when I need to use the access token to call the Slack web API methods, I need to find that token. I wanted to lookup that access token via the team_id that is passed in through the slash command message, but I couldn’t if the token is in the users object store, with the install user’s ID as the key.
Here is an example of what I had in the Botkit users and teams object stores after a user installed my app:
botkit:store:teams
{"id":"T1DDTABCD","createdBy":"U1DDKABCD","url":"https://someslackteam.slack.com/","name":"slack-team-name"}
botkit:store:users
{"id":"U1DDKABCD","access_token":"xoxp-49999999999-49999999999-59999999999-7e05d2266c","scopes":["identify","commands"],"team_id":"T1DDTABCD","user":"johndoe"}
When my app gets a message, it doesn’t have access to the install user’s ID, but it does have the team ID. I needed to pass in that “access_token” for the web API calls like this:
var token = ''; //Need the access token var options = { user: message.user, token: token } bot.api.users.info(options, function (err, response) { var user = response.user; var username = user.name; });
My workaround was to get the access_token from the install user during the install process and store it with the team. This is what that code looks like:
controller.setupWebserver(process.env.PORT, function(err, webserver) { controller.createWebhookEndpoints(controller.webserver); // Used for app install url/login controller.createOauthEndpoints(controller.webserver, function(err, req, res) { if (err) { res.status(500).send('ERROR: ' + err); } else { // Need to store the user access_token with the team for easy access later var teamID = req.identity.team_id; var userID = req.identity.user_id; controller.storage.users.get(userID, function(err, user) { var token = user.access_token; if (err) { console.error('users get err: ' + err); } controller.storage.teams.get(teamID, function (err, team) { if (err) { console.error('teams get error: ' + err); } team.access_token = token; controller.storage.teams.save(team, function(err) { if (err) { console.error('teams save err: ' + err); } }); }); }); res.send(templates.appInstallSuccess); } }); });
That happens once during install and adds the access token to the teams record:
botkit:store:teams
{"id":"T1DDTABCD","createdBy":"U1DDKABCD","url":"https://someslackteam.slack.com/","name":"slack-team-name", "access_token":"xoxp-49999999999-49999999999-59999999999-7e05d2266c"}
botkit:store:users
{"id":"U1DDKABCD","access_token":"xoxp-49999999999-49999999999-59999999999-7e05d2266c","scopes":["identify","commands"],"team_id":"T1DDTABCD","user":"johndoe"}
I could then call the Slack web API like this:
controller.storage.teams.get(message.team_id, function(err, team) { var token = team.access_token; var options = { user: message.user, token: token } // Call users.info Slack web API to look up user info bot.api.users.info(options, function (err, response) { var user = response.user; var username = user.name; });
Notice I’m calling the teams storage and passing in the message.team_id to look up the team for the user who submitted the command.