@cimpress/simple-auth-wrapper
Advanced tools
Comparing version 6.5.0 to 6.6.0
# Changelog | ||
## 6.6.X (2020-05-14) | ||
Added a check to see if the user's token is expired when the browser tab gains focus. This is because the expiration timer is often times unreliable when the user's browser is asleep. A `checkExpirationOnFocus` option was added to the `centralizedAuth` options that | ||
allows this to be enabled/disabled. | ||
## 6.5.X (2020-04-14) | ||
@@ -4,0 +8,0 @@ Added `authorizeParams` option to `CentralizedAuth.login()`. The option is passed through to `auth0-js` and will eventually end up in the `/authorize` call sent to auth0. It can be helpful when [passing custom parameters](https://auth0.com/docs/connections/pass-parameters-to-idps) to an IDP. |
@@ -51,2 +51,5 @@ 'use strict'; | ||
// Check to see if the token is expired when the window comes into focus. This is because the expiration timer is sometimes unreliable. | ||
checkExpirationOnFocus: true, | ||
// number of seconds of clock skew to tolerate (see https://auth0.com/docs/libraries/lock/v10/customization#leeway-integer-) | ||
@@ -66,2 +69,3 @@ leeway: 30 | ||
// emitInitialAuthenticated (optional, see default above) | ||
// checkExpirationOnFocus (optional, see default above) | ||
// leeway (optional, see default above) | ||
@@ -91,2 +95,6 @@ // lockWidgetOptions (optional, see defaults in newLockWidget) | ||
window.addEventListener('storage', this.listenToStorage); | ||
// The tokenExpired event can be unreliable (for example when your computer goes to sleep) | ||
// So we are double checking that you are logged in when the browser tab gains focus. | ||
window.addEventListener('visibilitychange', this.handleFocusChange); | ||
} | ||
@@ -187,2 +195,11 @@ | ||
this.handleFocusChange = function () { | ||
if (document.visibilityState === 'visible' && _this.checkExpirationOnFocus) { | ||
var expiration = _this.getExpiration(); | ||
if (expiration && expiration - _this.expirationOffset * 1000 <= new Date().getTime()) { | ||
_this.events.emit('tokenExpired', expiration); | ||
} | ||
} | ||
}; | ||
this.setExpirationTimer = function () { | ||
@@ -189,0 +206,0 @@ // Get the time that the access token will expire at |
{ | ||
"name": "@cimpress/simple-auth-wrapper", | ||
"version": "6.5.0", | ||
"version": "6.6.0", | ||
"description": "A simple utility class to wrap basic Auth0 functionality", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -56,3 +56,3 @@ # MEX Simple Auth Wrapper v. 3.0 | ||
|----------------|---------------| | ||
| `tokenExpired` | This event is triggered when the user's token expires. If the user's token in localStorage is expired at the time this event is subscribed to (i.e. `auth.on('tokenExpired', ...)`) this event will immediately emit. You can turn this behavior off via the `emitInitialTokenExpired` constructor option. By default this event will emit 30 seconds before the actual expiry. You can change this offset value via the `expirationOffset` constructor option. | | ||
| `tokenExpired` | This event is triggered when the user's token expires. If the user's token in localStorage is expired at the time this event is subscribed to (i.e. `auth.on('tokenExpired', ...)`) this event will immediately emit. You can turn this behavior off via the `emitInitialTokenExpired` constructor option. By default this event will emit 30 seconds before the actual expiry. You can change this offset value via the `expirationOffset` constructor option. It is also possible for this to be fired on browser focus. This is controlled by the `checkExpirationOnFocus` constructor option and exists because the token expired timer can be unreliable when the user's computer is asleep.| | ||
@@ -59,0 +59,0 @@ ```javascript |
@@ -30,2 +30,5 @@ import Auth0 from 'auth0-js'; | ||
// Check to see if the token is expired when the window comes into focus. This is because the expiration timer is sometimes unreliable. | ||
checkExpirationOnFocus: true, | ||
// number of seconds of clock skew to tolerate (see https://auth0.com/docs/libraries/lock/v10/customization#leeway-integer-) | ||
@@ -45,2 +48,3 @@ leeway: 30 | ||
// emitInitialAuthenticated (optional, see default above) | ||
// checkExpirationOnFocus (optional, see default above) | ||
// leeway (optional, see default above) | ||
@@ -66,2 +70,7 @@ // lockWidgetOptions (optional, see defaults in newLockWidget) | ||
window.addEventListener('storage', this.listenToStorage); | ||
// The tokenExpired event can be unreliable (for example when your computer goes to sleep) | ||
// So we are double checking that you are logged in when the browser tab gains focus. | ||
window.addEventListener('visibilitychange', this.handleFocusChange); | ||
} | ||
@@ -110,2 +119,11 @@ | ||
handleFocusChange = () => { | ||
if (document.visibilityState === 'visible' && this.checkExpirationOnFocus) { | ||
const expiration = this.getExpiration(); | ||
if (expiration && expiration - (this.expirationOffset * 1000) <= new Date().getTime()) { | ||
this.events.emit('tokenExpired', expiration); | ||
} | ||
} | ||
} | ||
// Assumes the token details have already been stored to local storage. | ||
@@ -112,0 +130,0 @@ setExpirationTimer = () => { |
@@ -11,2 +11,7 @@ import clock from 'jest-plugin-clock'; | ||
const mockAddEvent = jest.fn(window.addEventListener) | ||
window.addEventListener = mockAddEvent | ||
beforeEach(() => { | ||
@@ -28,2 +33,8 @@ window.localStorage.clear(); | ||
}); | ||
test('should add both event listeners',() => { | ||
expect(mockAddEvent).toBeCalledTimes(2) | ||
expect(mockAddEvent).toHaveBeenNthCalledWith(1, 'storage', testModule.listenToStorage); | ||
expect(mockAddEvent).toHaveBeenNthCalledWith(2, 'visibilitychange',testModule.handleFocusChange); | ||
}) | ||
@@ -173,2 +184,14 @@ test('should return the token in localStorage', () => { | ||
test('"tokenExpired" event should fire even if logged in if we are within the expiration offset', () => { | ||
const tokenExpiredCallback = jest.fn(); | ||
testModule.on('tokenExpired', tokenExpiredCallback); | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(1); | ||
window.dispatchEvent(new Event('visibilitychange')) | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(2); | ||
}); | ||
test('isLoggedIn should return true', () => { | ||
@@ -179,2 +202,34 @@ expect(testModule.isLoggedIn()).toBe(true); | ||
describe('when the user has a token that expires outside of the expiration offset', () => { | ||
beforeEach(() => { | ||
// set expiration 60 seconds into future | ||
window.localStorage.setItem('expires_at', JSON.stringify(now.getTime() + 60 * 1000)); | ||
}); | ||
test('subscribing to "authenticated" should fire the event', () => { | ||
const authenticatedCallback = jest.fn(); | ||
testModule.on('authenticated', authenticatedCallback); | ||
expect(authenticatedCallback).toHaveBeenCalledTimes(1); | ||
expect(authenticatedCallback).toBeCalledWith('initial'); | ||
}); | ||
test('"tokenExpired" event should not fire even if logged in and outside the expiration offset', () => { | ||
const tokenExpiredCallback = jest.fn(); | ||
testModule.on('tokenExpired', tokenExpiredCallback); | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(0); | ||
window.dispatchEvent(new Event('visibilitychange')) | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(0); | ||
}); | ||
test('isLoggedIn should return true', () => { | ||
expect(testModule.isLoggedIn()).toBe(true); | ||
}); | ||
}); | ||
describe('when the token is considered expired according to the "expirationOffset"', () => { | ||
@@ -192,2 +247,14 @@ beforeEach(() => { | ||
}); | ||
test('subscribing to "tokenExpired" should fire the event when focus event happens', () => { | ||
const tokenExpiredCallback = jest.fn(); | ||
testModule.on('tokenExpired', tokenExpiredCallback); | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(1); | ||
window.dispatchEvent(new Event('visibilitychange')) | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(2); | ||
}); | ||
}); | ||
@@ -208,2 +275,13 @@ | ||
test('subscribing to "tokenExpired" should fire the event when focus event happens', () => { | ||
const tokenExpiredCallback = jest.fn(); | ||
testModule.on('tokenExpired', tokenExpiredCallback); | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(1); | ||
window.dispatchEvent(new Event('visibilitychange')) | ||
expect(tokenExpiredCallback).toHaveBeenCalledTimes(2); | ||
}); | ||
test('isLoggedIn should return false', () => { | ||
@@ -248,3 +326,3 @@ expect(testModule.isLoggedIn()).toBe(false); | ||
describe('Centralized Auth using emitInitialTokenExpired = false, and emitInitialAuthenticated = false', () => { | ||
describe('Centralized Auth using emitInitialTokenExpired = false, emitInitialAuthenticated = false, and checkExpirationOnFocus = false', () => { | ||
let testModule; | ||
@@ -255,3 +333,4 @@ beforeEach(() => { | ||
emitInitialTokenExpired: false, | ||
emitInitialAuthenticated: false | ||
emitInitialAuthenticated: false, | ||
checkExpirationOnFocus: false | ||
}); | ||
@@ -284,3 +363,13 @@ }); | ||
}); | ||
test('visibility change should not fire tokenExpired callback',() => { | ||
const tokenExpiredCallback = jest.fn(); | ||
testModule.on('tokenExpired', tokenExpiredCallback); | ||
window.dispatchEvent(new Event('visibilitychange')) | ||
expect(tokenExpiredCallback).not.toHaveBeenCalled(); | ||
}) | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
135888
1695