diff --git a/doc/baseConfig.md b/doc/baseConfig.md index 30807dd..e307c2d 100644 --- a/doc/baseConfig.md +++ b/doc/baseConfig.md @@ -121,6 +121,15 @@ platform = 'browser'; storage = 'localStorage'; // The key used for storing the authentication response locally storageKey = 'aurelia_authentication'; +// optional function to extract the expiration date. takes the server responseas parameter +// eg (expires_in in sec): getExpirationDateFromResponse = serverResponse => new Date().getTime() + serverResponse.expires_in * 1000; +getExpirationDateFromResponse = null; +// optional function to extract the access token from the response. takes the server response as parameter +// eg: getAccessTokenFromResponse = serverResponse => serverResponse.data[0].access_token; +getAccessTokenFromResponse = null; +// optional function to extract the refresh token from the response. takes the server response as parameter +// eg: getRefreshTokenFromResponse = serverResponse => serverResponse.data[0].refresh_token; +getRefreshTokenFromResponse = null; // List of value-converters to make global globalValueConverters = ['authFilterValueConverter']; diff --git a/src/authentication.js b/src/authentication.js index cfd1fda..dcb9aff 100644 --- a/src/authentication.js +++ b/src/authentication.js @@ -145,14 +145,23 @@ export class Authentication { getDataFromResponse(response) { const config = this.config; - this.accessToken = this.getTokenFromResponse(response, config.accessTokenProp, config.accessTokenName, config.accessTokenRoot); + // get access token either with from supplied parameters or with supplied function + this.accessToken = typeof this.config.getAccessTokenFromResponse === 'function' + ? this.config.getAccessTokenFromResponse(response) + : this.getTokenFromResponse(response, config.accessTokenProp, config.accessTokenName, config.accessTokenRoot); + this.refreshToken = null; if (config.useRefreshToken) { try { - this.refreshToken = this.getTokenFromResponse(response, config.refreshTokenProp, config.refreshTokenName, config.refreshTokenRoot); + // get refresh token either with from supplied parameters or with supplied function + this.refreshToken = typeof this.config.getRefreshTokenFromResponse === 'function' + ? this.config.getRefreshTokenFromResponse(response) + : this.getTokenFromResponse(response, config.refreshTokenProp, config.refreshTokenName, config.refreshTokenRoot); } catch (e) { this.refreshToken = null; + + LogManager.getLogger('authentication').warn('useRefreshToken is set, but could not extract a refresh token'); } } @@ -168,7 +177,10 @@ export class Authentication { this.payload = this.accessToken ? jwtDecode(this.accessToken) : null; } catch (_) {_;} - this.exp = this.payload ? parseInt(this.payload.exp, 10) : NaN; + // get exp either with from jwt or with supplied function + this.exp = typeof this.config.getExpirationDateFromResponse === 'function' + ? this.config.getExpirationDateFromResponse(response) + : (this.payload && parseInt(this.payload.exp, 10)) || NaN; this.hasDataStored = true; diff --git a/src/baseConfig.js b/src/baseConfig.js index 40d034a..be7c858 100644 --- a/src/baseConfig.js +++ b/src/baseConfig.js @@ -149,6 +149,15 @@ export class BaseConfig { storage = 'localStorage'; // The key used for storing the authentication response locally storageKey = 'aurelia_authentication'; + // optional function to extract the expiration date. takes the server responseas parameter + // eg (expires_in in sec): getExpirationDateFromResponse = serverResponse => new Date().getTime() + serverResponse.expires_in * 1000; + getExpirationDateFromResponse = null; + // optional function to extract the access token from the response. takes the server response as parameter + // eg: getAccessTokenFromResponse = serverResponse => serverResponse.data[0].access_token; + getAccessTokenFromResponse = null; + // optional function to extract the refresh token from the response. takes the server response as parameter + // eg: getRefreshTokenFromResponse = serverResponse => serverResponse.data[0].refresh_token; + getRefreshTokenFromResponse = null; // List of value-converters to make global globalValueConverters = ['authFilterValueConverter']; diff --git a/test/authentication.spec.js b/test/authentication.spec.js index c391a7c..6b7c92b 100644 --- a/test/authentication.spec.js +++ b/test/authentication.spec.js @@ -82,6 +82,14 @@ describe('Authentication', () => { expect(authentication.getAccessToken()).toBe('some'); }); + + it('Should use custom function to analyze response first and return accessToken', () => { + authentication.config.getAccessTokenFromResponse = response => response.custom; + + authentication.setResponseObject({custom: 'custom'}); + + expect(authentication.getAccessToken()).toBe('custom'); + }); }); describe('.getRefreshToken()', () => { @@ -95,10 +103,20 @@ describe('Authentication', () => { it('Should analyze response first and return refreshToken', () => { authentication.config.useRefreshToken = true; + authentication.setResponseObject({token: 'some', refresh_token: 'another'}); expect(authentication.getRefreshToken()).toBe('another'); }); + + it('Should use custom function to analyze response first and return refreshToken', () => { + authentication.config.useRefreshToken = true; + authentication.config.getRefreshTokenFromResponse = response => response.custom; + + authentication.setResponseObject({token: 'some', custom: 'other custom'}); + + expect(authentication.getRefreshToken()).toBe('other custom'); + }); }); describe('.getIdToken()', () => { @@ -162,6 +180,16 @@ describe('Authentication', () => { expect(typeof exp === 'number').toBe(true); expect(exp).toBe(Number(tokenPast.payload.exp)); }); + + it('Should use custom function to analyze response first and return exp', () => { + authentication.config.getExpirationDateFromResponse = response => response.custom; + + authentication.setResponseObject({token: 'some', custom: 2460017154}); + + const exp = authentication.getExp(); + expect(typeof exp === 'number').toBe(true); + expect(exp).toBe(2460017154); + }); });