UNPKG

neo4j-client-sso

Version:

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

211 lines (210 loc) 9.72 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const sinon_1 = __importDefault(require("sinon")); const main_1 = require("./main"); const common = __importStar(require("./common")); const helpers = __importStar(require("./helpers")); const __mocks__1 = require("./__mocks__"); const whatwg_fetch_1 = require("whatwg-fetch"); const constants_1 = require("./constants"); global.Response = whatwg_fetch_1.Response; const _mockResponse = (body = {}) => { return new whatwg_fetch_1.Response(JSON.stringify(body), { status: 200, headers: { 'Content-type': 'application/json' } }); }; describe('handleRefreshingToken', () => { let fetchStub = null; let handleRefreshingTokenStub = null; beforeAll(() => { handleRefreshingTokenStub = sinon_1.default .stub(common, 'retrieveRefreshTokenData') .returns({}); sinon_1.default.stub(common, 'storeRefreshTokenData'); sinon_1.default .stub(common, 'getCredentialsFromAuthResult') .returns({ username: 'testusername', password: 'wooord' }); fetchStub = sinon_1.default.stub(); global.fetch = fetchStub.returns(Promise.resolve(_mockResponse())); }); afterAll(() => { sinon_1.default.restore(); }); it('handles error when retrieving refresh token', done => { (0, main_1.handleRefreshingToken)([__mocks__1.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' }); (0, main_1.handleRefreshingToken)([__mocks__1.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' }); (0, main_1.handleRefreshingToken)([__mocks__1.exampleSSOProvider]).then(response => { sinon_1.default.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_1.default.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_1.default.stub(common, 'getInitialisationParameters'); sinon_1.default.stub(helpers, 'removeSearchParamsInBrowserHistory'); sinon_1.default.stub(common, 'storeRefreshTokenData'); sinon_1.default .stub(common, 'getCredentialsFromAuthResult') .returns({ username: 'otherusername', password: 'swoooth' }); fetchStub = sinon_1.default.stub(); global.fetch = fetchStub.returns(Promise.resolve(_mockResponse())); }); afterEach(() => { fetchStub.resetHistory(); }); afterAll(() => { sinon_1.default.restore(); window.sessionStorage.clear(); }); it('handles error in init parameters', done => { getInitParamsStub.returns({ error: 'My Error', error_description: 'The error desc' }); (0, main_1.handleAuthFromRedirect)([__mocks__1.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' }); (0, main_1.handleAuthFromRedirect)([__mocks__1.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' }); (0, main_1.handleAuthFromRedirect)([__mocks__1.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' }); (0, main_1.handleAuthFromRedirect)([__mocks__1.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(constants_1.AUTH_STORAGE_STATE, FAKE_STATE_VALUE); window.sessionStorage.setItem(constants_1.AUTH_STORAGE_CODE_VERIFIER, FAKE_CODE_VERIFIER); expect(window.sessionStorage.getItem(constants_1.AUTH_STORAGE_STATE)).toEqual(FAKE_STATE_VALUE); expect(window.sessionStorage.getItem(constants_1.AUTH_STORAGE_CODE_VERIFIER)).toEqual(FAKE_CODE_VERIFIER); getInitParamsStub.returns({ idp_id: 'okta-oidc', state: FAKE_STATE_VALUE, code: FAKE_CODE }); (0, main_1.handleAuthFromRedirect)([__mocks__1.exampleSSOProvider]).then(response => { // INFO: the session storage entry for the "state" and "code_verifier" gets cleared // when it's retrieved. expect(window.sessionStorage.getItem(constants_1.AUTH_STORAGE_STATE)).toEqual(null); expect(window.sessionStorage.getItem(constants_1.AUTH_STORAGE_CODE_VERIFIER)).toEqual(null); sinon_1.default.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_1.default.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(constants_1.AUTH_STORAGE_STATE, FAKE_STATE_VALUE); expect(window.sessionStorage.getItem(constants_1.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' }); (0, main_1.handleAuthFromRedirect)([__mocks__1.exampleSSOProvider]).then(response => { // INFO: the session storage entry for the "state" gets cleared when it's retrieved. expect(window.sessionStorage.getItem(constants_1.AUTH_STORAGE_STATE)).toEqual(null); sinon_1.default.assert.notCalled(fetchStub); expect(response.username).toEqual('otherusername'); expect(response.password).toEqual('swoooth'); done(); }); }); });