UNPKG

neo4j-client-sso

Version:

Single sign-on client (frontend) library for Neo4j products

183 lines (182 loc) 8.01 kB
import sinon from 'sinon'; import { handleRefreshingToken, handleAuthFromRedirect } from './main'; import * as common from './common'; import * as helpers from './helpers'; import { exampleSSOProvider, exampleSSOProviderTwo } from './__mocks__'; import { Response } from 'whatwg-fetch'; import { AUTH_STORAGE_CODE_VERIFIER, AUTH_STORAGE_STATE } from './constants'; global.Response = Response; const _mockResponse = (body = {}) => { return new Response(JSON.stringify(body), { status: 200, headers: { 'Content-type': 'application/json' } }); }; describe('handleRefreshingToken', () => { let fetchStub = null; let handleRefreshingTokenStub = null; beforeAll(() => { handleRefreshingTokenStub = sinon .stub(common, 'retrieveRefreshTokenData') .returns({}); sinon.stub(common, 'storeRefreshTokenData'); sinon .stub(common, 'getCredentialsFromAuthResult') .returns({ username: 'testusername', password: 'wooord' }); fetchStub = sinon.stub(); global.fetch = fetchStub.returns(Promise.resolve(_mockResponse())); }); afterAll(() => { sinon.restore(); }); it('handles error when retrieving refresh token', done => { handleRefreshingToken([exampleSSOProviderTwo]).catch(err => { expect(err).toBeTruthy(); expect(err.toString()).toContain('Could not retrieve a valid refresh token, aborting.'); done(); }); }); it('handles no matching SSO provider in args', done => { handleRefreshingTokenStub.returns({ refreshToken: 'tokentoken', selectedSSOProviderId: 'okta-oidc' }); handleRefreshingToken([exampleSSOProviderTwo]).catch(err => { expect(err).toBeTruthy(); expect(err.toString()).toContain('Could not find SSO provider data for refreshing token, aborting'); done(); }); }); it('gets executed correctly', done => { handleRefreshingTokenStub.returns({ refreshToken: 'tokencontent', selectedSSOProviderId: 'okta-oidc' }); handleRefreshingToken([exampleSSOProvider]).then(response => { sinon.assert.calledOnce(fetchStub); const content = { method: 'post', headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'grant_type=refresh_token&refresh_token=tokencontent&client_id=cxkvjcvkxlcjbvl&scope=openid%20profile%20email%20groups' }; sinon.assert.calledWithExactly(fetchStub, undefined, content); expect(response.username).toEqual('testusername'); expect(response.password).toEqual('wooord'); done(); }); }); }); describe('handleAuthFromRedirect', () => { const FAKE_STATE_VALUE = 'state-value'; const FAKE_CODE_VERIFIER = 'RT33'; const FAKE_CODE = 'mycode'; let fetchStub = null; let getInitParamsStub = null; beforeAll(() => { getInitParamsStub = sinon.stub(common, 'getInitialisationParameters'); sinon.stub(helpers, 'removeSearchParamsInBrowserHistory'); sinon.stub(common, 'storeRefreshTokenData'); sinon .stub(common, 'getCredentialsFromAuthResult') .returns({ username: 'otherusername', password: 'swoooth' }); fetchStub = sinon.stub(); global.fetch = fetchStub.returns(Promise.resolve(_mockResponse())); }); afterEach(() => { fetchStub.resetHistory(); }); afterAll(() => { sinon.restore(); window.sessionStorage.clear(); }); it('handles error in init parameters', done => { getInitParamsStub.returns({ error: 'My Error', error_description: 'The error desc' }); handleAuthFromRedirect([exampleSSOProviderTwo]).catch(err => { expect(err).toBeTruthy(); expect(err.toString()).toContain('Error detected after auth redirect, aborting. Error: My Error, Error description: The error desc'); done(); }); }); it('handles no idp_id in init parameters', done => { getInitParamsStub.returns({ useless_param: 'useless' }); handleAuthFromRedirect([exampleSSOProviderTwo]).catch(err => { expect(err).toBeTruthy(); expect(err.toString()).toContain('Invalid idp_id parameter, aborting'); done(); }); }); it('handles non-existing url parameter state', done => { getInitParamsStub.returns({ idp_id: 'keycloak-oidc' }); handleAuthFromRedirect([exampleSSOProviderTwo]).catch(err => { expect(err).toBeTruthy(); expect(err.toString()).toContain('Invalid state parameter, aborting'); done(); }); }); it('handles missing state value in web browser session storage', done => { getInitParamsStub.returns({ idp_id: 'keycloak-oidc', state: 'my-state-val' }); handleAuthFromRedirect([exampleSSOProviderTwo]).catch(err => { expect(err).toBeTruthy(); expect(err.toString()).toContain('Invalid state parameter, aborting'); done(); }); }); it('gets executed correctly for PKCE auth flow', done => { window.sessionStorage.setItem(AUTH_STORAGE_STATE, FAKE_STATE_VALUE); window.sessionStorage.setItem(AUTH_STORAGE_CODE_VERIFIER, FAKE_CODE_VERIFIER); expect(window.sessionStorage.getItem(AUTH_STORAGE_STATE)).toEqual(FAKE_STATE_VALUE); expect(window.sessionStorage.getItem(AUTH_STORAGE_CODE_VERIFIER)).toEqual(FAKE_CODE_VERIFIER); getInitParamsStub.returns({ idp_id: 'okta-oidc', state: FAKE_STATE_VALUE, code: FAKE_CODE }); handleAuthFromRedirect([exampleSSOProvider]).then(response => { // INFO: the session storage entry for the "state" and "code_verifier" gets cleared // when it's retrieved. expect(window.sessionStorage.getItem(AUTH_STORAGE_STATE)).toEqual(null); expect(window.sessionStorage.getItem(AUTH_STORAGE_CODE_VERIFIER)).toEqual(null); sinon.assert.calledOnce(fetchStub); const content = { method: 'post', headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }, body: `grant_type=authorization_code&client_id=cxkvjcvkxlcjbvl&redirect_uri=http%3A%2F%2Flocalhost%3Fidp_id%3Dokta-oidc%26auth_flow_step%3Dredirect_uri&code_verifier=${FAKE_CODE_VERIFIER}&code=${FAKE_CODE}` }; sinon.assert.calledWithExactly(fetchStub, undefined, content); expect(response.username).toEqual('otherusername'); expect(response.password).toEqual('swoooth'); done(); }); }); it('gets executed correctly for implicit auth flow', done => { window.sessionStorage.setItem(AUTH_STORAGE_STATE, FAKE_STATE_VALUE); expect(window.sessionStorage.getItem(AUTH_STORAGE_STATE)).toEqual(FAKE_STATE_VALUE); getInitParamsStub.returns({ idp_id: 'okta-oidc', state: FAKE_STATE_VALUE, code: 'mycode', access_token: 'accesstokencontent', token_type: 'bearer' }); handleAuthFromRedirect([exampleSSOProvider]).then(response => { // INFO: the session storage entry for the "state" gets cleared when it's retrieved. expect(window.sessionStorage.getItem(AUTH_STORAGE_STATE)).toEqual(null); sinon.assert.notCalled(fetchStub); expect(response.username).toEqual('otherusername'); expect(response.password).toEqual('swoooth'); done(); }); }); });