Oauth 2.0 Connection: Slack - Victorianuonuo/nudge_bot GitHub Wiki
Prerequisites
- Slack ID and Slack secret: More reference here
- npm install passport-slack-oauth2 to integrate Slack authentication in the chatbot application.
Access process: OAuth 2.0
After the user connects their account via Oauth2, an access token will be created. That access token must be included in each API request. The user can revoke access to a service at any time.
Trigger
There should be a starting point to allow users to begin the process. For our Slack chatbot, simply give users a button to click on to start the process.
function authenSlack(slackID){
bot.postMessage(slackID, 'Please click the following button to add Slack as a data source.' , {
as_user:true,
"attachments": [
{
"fallback": "activate",
"actions": [
{
"type": "button",
"text": "connect",
"url": process.env.DOMAIN + '/apikey/slack/oauth?auth_id='+slackID
}
]
}
]
});
}
This is a function to generate a link button in Slack chatbot. The Slack button format could be seen here. In order to map each user's access token to their Slack IDs (slackID), we will add a new query after the url.
Configure Slack strategy with Passport
The Slack authentication strategy authenticates users using a Slack account and OAuth 2.0 tokens. The strategy requires a verify
callback, which accepts these credentials and calls done
providing a user, as well as options
specifying a client ID, client secret, and callback URL.
passport.use(new SlackStrategy({
clientID: process.env.SLACK_ID,
clientSecret: process.env.SLACK_SECRET,
callbackURL: process.env.DOMAIN+"/apikey/slack/callback",
skipUserProfile: false, // default
passReqToCallback: true,
scope: ['users:read', 'identity.basic']
},
(req, accessToken, refreshToken, profile, done) => {
// save user data into the database
SlackKey.findOne({slackID: req.query.state}).exec(function(err, apikey){
if(err){
done(err, apikey);
} else {
if(apikey){
var newApikey = apikey;
newApikey.access_token = accessToken;
}else{
var newApikey = new SlackKey({
slackID: req.query.state,
access_token: accessToken,
});
}
newApikey.save()
.then( () => {
done(err, newApikey);
})
.catch((err) => {
done(err, newApikey);
});
}
});
}
));
Authenticate Requests
Use passport.authenticate()
, specifying the 'rescuetime'
strategy, to authenticate requests.
router.get('/slack/oauth', function(req, res, next) {
var slackID = req.query.auth_id;
passport.authenticate('Slack', {state: slackID})(req, res, next);
});
router.get('/slack/callback',
passport.authenticate('Slack', { failureRedirect: '/apikey/slack/callback', session: false }),
function(req, res) {
var slackID = req.query.state;
// Successful authentication, redirect home.
if(slackID){
bot.postMessage(slackID, "Congratulations! You successfully add slack.", {as_user:true});
res.status(200).send("Your account was successfully authenticated");
}else{
bot.postMessage(slackID, "Ooops! Something went wrong! Please try again!", {as_user:true});
res.status(400).send("Your slackID is missing when call back!");
}
});