Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Add feature: refresh MSTeams token before it expires #1230

Merged
merged 10 commits into from Jan 29, 2018
61 changes: 61 additions & 0 deletions __test__/lib/Teams.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict';
let teamsBot;
let teamsApi;
let config = {
clientId: 'client',
clientSecret: 'secret',
debug: false
};

describe('authentication', () => {
beforeEach(() => {
jest.doMock('../../lib/TeamsAPI', () => {
return jest.fn((configuration) => {
return {
getToken: jest.fn((cb) => {
configuration.token = 'token';
configuration.token_expires_in = '3600';
cb(null);
})
};
});
});

jest.useFakeTimers();
teamsApi = require('../../lib/TeamsAPI');
});

afterEach(() => {
jest.resetModules();
jest.clearAllTimers();
});

test('get token', () => {
let bot = require('../../lib/Teams')(config);
expect(bot.api.getToken).toHaveBeenCalledTimes(1);
});

test('refresh token before expiry', () => {
let bot = require('../../lib/Teams')(config);
expect(bot.api.getToken).toHaveBeenCalledTimes(1);
jest.runOnlyPendingTimers();
expect(bot.api.getToken).toHaveBeenCalledTimes(2);
});

test('token valid for 20 mins should refresh after 10 mins', () => {
teamsApi.mockImplementation(jest.fn((configuration) => {
return {
getToken: jest.fn((cb) => {
configuration.token = 'token';
configuration.token_expires_in = '20';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configuration.token_expires_in value will be in seconds
https://tools.ietf.org/html/rfc6749#section-4.2.2

cb(null);
})
};
}));
let bot = require('../../lib/Teams')(config);
expect(bot.config.token_expires_in).toBe('20');
expect(bot.api.getToken).toHaveBeenCalledTimes(1);
jest.runTimersToTime(1000 * 60 * 11);
expect(bot.api.getToken).toHaveBeenCalledTimes(2);
});
});
11 changes: 7 additions & 4 deletions lib/Teams.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ function TeamsBot(configuration) {
var controller = Botkit(configuration || {});

controller.api = TeamsAPI(configuration || {});

controller.api.getToken(function(err) {
function tokenHandler(err) {
if (err) {
// this is a fatal error - could not create a Teams API client
throw new Error(err);
}
});

//use the expires_in value, convert to ms and remove 10 mins in ms
let tokenExpiresIn = 1000 * 60 * (configuration.token_expires_in || 60);
Copy link

@narenderpal narenderpal Jan 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expires_in unit is seconds, for example the value "3600" will denote that token will expire in one hour (60 * 60).
You may have to change the above line and update tests
let tokenExpiresIn = 1000 * (configuration.token_expires_in || 3600)

Example of json token - {"token_type":"Bearer","expires_in":3599,"ext_expires_in":0,"access_token":" eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjJLVmN1enFBaWRPTHFXU2FvbDd3Z0ZSR0NZbyIsImtpZCI6IjJLVmN1enFBaWRPTHFXU2FvbDd3Z0ZSR0NZbyJ9.eyJhdWQiOiJodHRwczovL2FwaS5ib3RmcmFtZXdvcmsuY29tIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZDZkNDk0MjAtZjM5Yi00ZGY3LWExZGMtZDU5YTkzNTg3MWRiLyIsImlhdCI6MTUxMTc1OTExNCwibmJmIjoxNTExNzU5MTE0LCJleHAiOjE1MTE3NjMwMTQsImFpbyI6IlkyTmdZSWhZdVBmYnQ1cUhWd0tuL2JCNDE3ejhDd0E9IiwiYXBwaWQiOiI1ZjVlMDAyMS1lNTNjLTQ1NDktOWE1NC0wNDMyNDAwM2EyM2YiLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9kNmQ0OTQyMC1mMzliLTRkZjctYTFkYy1kNTlhOTM1ODcxZGIvIiwidGlkIjoiZDZkNDk0MjAtZjM5Yi00ZGY3LWExZGMtZDU5YTkzNTg3MWRiIiwidXRpIjoiLTk4UE1scU5xay1LeWxTaGdTMWFBQSIsInZlciI6IjEuMCJ9.IG_qHoN9WIZDH2hZCGDKW3EYl_7z8G2VwgxXHGWQR_9ZmHAMIUVM8uxqYR8cJTCRwgWOBXSMKS4yKGM8jdvchevJf0xndhvx_iocFun3_TBCWOzIpBWW_vUScNv1W70iM-CcXYvXo9CFHnsM_w7S8DMVov-_p0QEj-U-IHU_sls5hFIDaqpTZtqG_h6ZaK7KmIJtPFcxSM2uf8tUmWL7bdFPTBUzo-rM4yuzV3SewrzWl_EiXccnSEfi3fq5QWnWElwBXNt9VIQ2FqLmob2YHa3B5JLrd7vCtcJGSKZ6yUSphRGTyfq75grwdGrZ1lfPUWfzHVa1hp8vXKvVnSyIyg"}

let expiryCheckDelta = 1000 * 60 * 10;
setTimeout(controller.api.getToken, (tokenExpiresIn - expiryCheckDelta), tokenHandler);
};
controller.api.getToken(tokenHandler);

controller.defineBot(function(botkit, config) {
var bot = {
Expand Down
1 change: 1 addition & 0 deletions lib/TeamsAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ module.exports = function(configuration) {
return cb(json.error_description);
}
configuration.token = json.access_token;
configuration.token_expires_in = json.expires_in;
cb(null);
}
}
Expand Down