153 lines
5.0 KiB
JavaScript
153 lines
5.0 KiB
JavaScript
|
|
import AuthClient, { __RewireAPI__ as rewire } from '.'; // eslint-disable-line
|
||
|
|
import { __RewireAPI__ as storageRewire } from './storage'; // eslint-disable-line
|
||
|
|
|
||
|
|
describe('Auth module', () => {
|
||
|
|
const STORAGE = {
|
||
|
|
ACCESS: storageRewire.__get__('STORAGE_ACCESS'),
|
||
|
|
ID: storageRewire.__get__('STORAGE_ID'),
|
||
|
|
EXPIRES: storageRewire.__get__('STORAGE_EXPIRES'),
|
||
|
|
USER: storageRewire.__get__('STORAGE_USER'),
|
||
|
|
STATE: storageRewire.__get__('STORAGE_STATE'),
|
||
|
|
NONCE: storageRewire.__get__('STORAGE_NONCE'),
|
||
|
|
};
|
||
|
|
let authZero;
|
||
|
|
let TEST_DATE;
|
||
|
|
let webAuth;
|
||
|
|
// populates the storage with some mock data to mimic a login
|
||
|
|
const populateStorage = () => {
|
||
|
|
localStorage.setItem(STORAGE.ACCESS, 'foo');
|
||
|
|
localStorage.setItem(STORAGE.ID, 'foo');
|
||
|
|
localStorage.setItem(STORAGE.EXPIRES, 'foo');
|
||
|
|
localStorage.setItem(STORAGE.USER, '{"foo": "bar"}');
|
||
|
|
localStorage.setItem(STORAGE.STATE, 'foo');
|
||
|
|
localStorage.setItem(STORAGE.NONCE, 'foo');
|
||
|
|
};
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
// freeze time for this test suite - we're going back to the 90s!
|
||
|
|
TEST_DATE = new Date('1999');
|
||
|
|
global.Date = jest.fn(() => TEST_DATE);
|
||
|
|
// mop up current localStorage before each run - it will not clean itself
|
||
|
|
localStorage.clear();
|
||
|
|
authZero = {
|
||
|
|
authorize: jest.fn(),
|
||
|
|
parseHash: jest.fn(),
|
||
|
|
client: {
|
||
|
|
buildAuthorizeUrl: jest.fn(() => 'https://example.com'),
|
||
|
|
userInfo: jest.fn(),
|
||
|
|
},
|
||
|
|
};
|
||
|
|
rewire.__set__('auth0', { WebAuth: () => authZero });
|
||
|
|
webAuth = new AuthClient();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('stores user info on successful login', (done) => {
|
||
|
|
const state = { returnUrl: '/foo' };
|
||
|
|
const authResult = {
|
||
|
|
accessToken: 'foo',
|
||
|
|
idToken: 'bar',
|
||
|
|
expiresIn: 86400,
|
||
|
|
state: JSON.stringify(state),
|
||
|
|
};
|
||
|
|
const userInfo = { foo: 'bar' };
|
||
|
|
|
||
|
|
authZero.parseHash = jest.fn((options, cb) => {
|
||
|
|
cb(null, authResult);
|
||
|
|
});
|
||
|
|
authZero.client.userInfo = jest.fn((token, cb) => {
|
||
|
|
cb(null, userInfo);
|
||
|
|
});
|
||
|
|
|
||
|
|
return webAuth.handleAuthentication()
|
||
|
|
.then((result) => {
|
||
|
|
const expiresAt = JSON.stringify(authResult.expiresIn * 1000 + TEST_DATE.getTime());
|
||
|
|
|
||
|
|
expect(authZero.parseHash).toBeCalled();
|
||
|
|
expect(localStorage.getItem(STORAGE.ACCESS)).toEqual(authResult.accessToken);
|
||
|
|
expect(localStorage.getItem(STORAGE.ID)).toEqual(authResult.idToken);
|
||
|
|
expect(localStorage.getItem(STORAGE.EXPIRES)).toEqual(expiresAt);
|
||
|
|
expect(localStorage.getItem(STORAGE.USER)).toEqual(JSON.stringify(userInfo));
|
||
|
|
// verify that the state we sent in is what we get back
|
||
|
|
expect(result).toEqual(state);
|
||
|
|
done();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clears state and nonce from storage on normal login attempt', () => {
|
||
|
|
populateStorage();
|
||
|
|
webAuth.triggerLogin({ returnUrl: '/' });
|
||
|
|
expect(localStorage.getItem(STORAGE.NONCE)).toBeFalsy();
|
||
|
|
expect(localStorage.getItem(STORAGE.STATE)).toBeFalsy();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sets correct localstorage content on silent login attempt', () => {
|
||
|
|
const state = { returnUrl: '/some-path/', foo: 'bar', ham: 34 };
|
||
|
|
const serializedState = JSON.stringify(state);
|
||
|
|
|
||
|
|
webAuth.triggerSilentLogin(state);
|
||
|
|
expect(localStorage.getItem(STORAGE.NONCE)).toEqual(TEST_DATE.getTime().toString());
|
||
|
|
expect(localStorage.getItem(STORAGE.STATE)).toEqual(serializedState);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('rejects failed logins', (done) => {
|
||
|
|
const authResult = {
|
||
|
|
error: 'failed to authenticate',
|
||
|
|
};
|
||
|
|
|
||
|
|
authZero.parseHash = jest.fn((options, cb) => {
|
||
|
|
cb(null, authResult);
|
||
|
|
});
|
||
|
|
|
||
|
|
return webAuth.handleAuthentication()
|
||
|
|
.catch(() => {
|
||
|
|
expect(authZero.parseHash).toBeCalled();
|
||
|
|
expect(localStorage.length).toBe(0);
|
||
|
|
done();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('rejects logins followed by failed user fetches', (done) => {
|
||
|
|
const authResult = {
|
||
|
|
accessToken: 'foo',
|
||
|
|
idToken: 'bar',
|
||
|
|
expiresIn: 86400,
|
||
|
|
};
|
||
|
|
|
||
|
|
authZero.parseHash = jest.fn((options, cb) => {
|
||
|
|
cb(null, authResult);
|
||
|
|
});
|
||
|
|
authZero.client.userInfo = jest.fn((token, cb) => {
|
||
|
|
cb('Credentials invalid');
|
||
|
|
});
|
||
|
|
|
||
|
|
return webAuth.handleAuthentication()
|
||
|
|
.catch(() => {
|
||
|
|
expect(authZero.parseHash).toBeCalled();
|
||
|
|
expect(authZero.client.userInfo).toBeCalled();
|
||
|
|
expect(localStorage.length).toBe(0);
|
||
|
|
done();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clears session on logout', () => {
|
||
|
|
populateStorage();
|
||
|
|
webAuth.logout();
|
||
|
|
expect(localStorage.length).toBe(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('indicates authenticated and expired users based on expiry time', () => {
|
||
|
|
populateStorage();
|
||
|
|
localStorage.setItem(STORAGE.EXPIRES, global.Date().getTime() - 1000);
|
||
|
|
expect(webAuth.isAuthenticated()).toBe(true);
|
||
|
|
expect(webAuth.isExpired()).toBe(true);
|
||
|
|
|
||
|
|
localStorage.setItem(STORAGE.EXPIRES, global.Date().getTime());
|
||
|
|
expect(webAuth.isAuthenticated()).toBe(true);
|
||
|
|
expect(webAuth.isExpired()).toBe(false);
|
||
|
|
|
||
|
|
localStorage.setItem(STORAGE.EXPIRES, global.Date().getTime() + 1000);
|
||
|
|
expect(webAuth.isAuthenticated()).toBe(true);
|
||
|
|
expect(webAuth.isExpired()).toBe(false);
|
||
|
|
});
|
||
|
|
});
|