Skip to content

Commit

Permalink
Merge branch 'release-1.19.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
btamas committed May 3, 2022
2 parents dc01801 + 7a4e81c commit a731b07
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 12 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@oat-sa/tao-core-sdk",
"version": "1.18.2",
"version": "1.19.0",
"displayName": "TAO Core SDK",
"description": "Core libraries of TAO",
"homepage": "https://github.com/oat-sa/tao-core-sdk-fe#readme",
Expand Down
56 changes: 46 additions & 10 deletions src/core/jwt/jwtTokenHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import TokenError from 'core/error/TokenError';
* @param {Boolean} [options.usePerTokenTTL] if true, accessToken TTL should be extractable from JWT payload, and accessTokenTTL will be used as fallback
* @param {Boolean} [options.useCredentials] refreshToken stored in cookie instead of store
* @param {Object} [options.refreshTokenParameters] Parameters that should be send in refreshToken call
* @param {Boolean} [options.oauth2RequestFormat] use oauth2 request format
* @returns {Object} JWT Token handler instance
*/
const jwtTokenHandlerFactory = function jwtTokenHandlerFactory({
Expand All @@ -45,7 +46,8 @@ const jwtTokenHandlerFactory = function jwtTokenHandlerFactory({
accessTokenTTL,
usePerTokenTTL = false,
refreshTokenParameters,
useCredentials = false
useCredentials = false,
oauth2RequestFormat = false
} = {}) {
const tokenStorage = jwtTokenStoreFactory({
namespace: serviceName,
Expand All @@ -65,12 +67,12 @@ const jwtTokenHandlerFactory = function jwtTokenHandlerFactory({
* @returns {Promise<String>} Promise of new token
*/
const unQueuedRefreshToken = () => {
let body;
let parameters;
let credentials;
let flow;

if (refreshTokenParameters) {
body = Object.assign({}, refreshTokenParameters);
parameters = Object.assign({}, refreshTokenParameters);
}

if (useCredentials) {
Expand All @@ -81,21 +83,34 @@ const jwtTokenHandlerFactory = function jwtTokenHandlerFactory({
if (!refreshToken) {
throw new Error('Refresh token is not available');
}
body = Object.assign({}, body, { refreshToken });
if (oauth2RequestFormat) {
parameters = Object.assign({}, parameters, { refresh_token: refreshToken });
} else {
parameters = Object.assign({}, parameters, { refreshToken });
}
});
}

return flow
.then(() => {
if (body) {
body = JSON.stringify(body);
const headers = {};
let body;
if (oauth2RequestFormat) {
body = new FormData();
Object.keys(parameters).forEach(key => {
body.append(key, parameters[key]);
});
} else {
if (parameters) {
body = JSON.stringify(parameters);
}

headers['Content-Type'] = 'application/json';
}
return fetch(refreshTokenUrl, {
method: 'POST',
credentials,
headers: {
'Content-Type': 'application/json'
},
headers,
body
});
})
Expand All @@ -112,7 +127,28 @@ const jwtTokenHandlerFactory = function jwtTokenHandlerFactory({
error.response = response;
return Promise.reject(error);
})
.then(({ accessToken }) => tokenStorage.setAccessToken(accessToken).then(() => accessToken));
.then(response => {
let accessToken, refreshToken, expiresIn;

if (oauth2RequestFormat) {
accessToken = response.access_token;
refreshToken = response.refresh_token;
expiresIn = response.expires_in;
} else {
accessToken = response.accessToken;
refreshToken = response.refreshToken;
}

if (expiresIn) {
tokenStorage.setAccessTokenTTL(expiresIn * 1000);
}

if (accessToken && refreshToken) {
return tokenStorage.setTokens(accessToken, refreshToken).then(() => accessToken);
}

return tokenStorage.setAccessToken(accessToken).then(() => accessToken);
});
};

return {
Expand Down
6 changes: 6 additions & 0 deletions test/core/jwt/jwtTokenHandler/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
},
setAccessTokenTTL(newAccessTokenTTL) {
accessTokenTTL = newAccessTokenTTL;
},
setTokens(newAccessToken, newRefreshToken) {
accessToken = newAccessToken;
refreshToken = newRefreshToken;
accessTokenStoredAt = Date.now();
return Promise.resolve(true);
}
};
});
Expand Down
81 changes: 81 additions & 0 deletions test/core/jwt/jwtTokenHandler/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,4 +532,85 @@ define(['jquery', 'core/jwt/jwtTokenHandler', 'fetch-mock', 'core/error/TokenErr
}
);
});

QUnit.module('OAuth2', {
beforeEach: function () {
this.handler = jwtTokenHandlerFactory({
refreshTokenUrl: '/refreshUrl',
oauth2RequestFormat: true,
refreshTokenParameters: {
grant_type: 'refresh_token',
client_id: 'client_1'
}
});
},
afterEach: function (assert) {
const done = assert.async();
fetchMock.restore();
this.handler.clearStore().then(done);
}
});

QUnit.test('refresh token', function (assert) {
assert.expect(10);

const done = assert.async();

const accessToken = 'some access token';
const refreshToken = 'some refresh token';
const updatedRefreshToken = 'some updated refresh token';
const updatedAccessToken = 'some updated access token';

const setupSecondRequest = () => {
fetchMock.restore();
fetchMock.mock('/refreshUrl', function (url, opts) {
const data = {};
for (let key of opts.body.keys()) {
data[key] = opts.body.get(key);
}
assert.equal(data.grant_type, 'refresh_token', 'grant type is sent to the api');
assert.equal(data.client_id, 'client_1', 'client id is sent to the api');
assert.equal(data.refresh_token, updatedRefreshToken, 'new refresh token is sent to the api');
return JSON.stringify({
access_token: updatedAccessToken,
refresh_token: updatedRefreshToken,
expires_in: 1
});
});
};

fetchMock.mock('/refreshUrl', function (url, opts) {
const data = {};
for (let key of opts.body.keys()) {
data[key] = opts.body.get(key);
}
assert.equal(data.grant_type, 'refresh_token', 'grant type is sent to the api');
assert.equal(data.client_id, 'client_1', 'client id is sent to the api');
assert.equal(data.refresh_token, refreshToken, 'refresh token is sent to the api');
setupSecondRequest();
return JSON.stringify({
access_token: accessToken,
refresh_token: updatedRefreshToken,
expires_in: 1
});
});

this.handler.storeRefreshToken(refreshToken).then(setTokenResult => {
assert.equal(setTokenResult, true, 'refresh token is set');
this.handler.getToken().then(refreshedAccessToken => {
assert.equal(refreshedAccessToken, accessToken, 'get refreshed access token');

this.handler.getToken().then(storedAccessToken => {
assert.equal(storedAccessToken, accessToken, 'get access token from store without refresh');
}).then(() => new Promise(resolve => {
setTimeout(resolve, 1000);
})).then(() => {
this.handler.getToken().then(storedAccessToken => {
assert.equal(storedAccessToken, updatedAccessToken, 'get access token again, because it was expired');
done();
});
});
});
});
});
});

0 comments on commit a731b07

Please sign in to comment.