neo4j-client-sso
Version:
Single sign-on client (frontend) library for Neo4j products
181 lines (180 loc) • 9.47 kB
JavaScript
;
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.restoreSearchAndHashParams = exports.wasRedirectedBackFromSSOServer = exports.getSSOServerIdIfShouldRedirect = exports.clearRefreshTokenData = exports.retrieveRefreshTokenData = exports.storeRefreshTokenData = exports.temporarilyStoreUrlSearchParams = exports.getCredentialsFromAuthResult = exports.getValidSSOProviders = exports.getInitialisationParameters = void 0;
const jwt_decode_1 = __importDefault(require("jwt-decode"));
const lodash_pick_1 = __importDefault(require("lodash.pick"));
const utils_1 = require("./utils");
const constants_1 = require("./constants");
const helpers_1 = require("./helpers");
const settings_1 = require("./settings");
const getInitialisationParameters = () => {
const urlSearchParams = window.location.search;
const urlHashParamsAsSearchParams = '?' + window.location.hash.substring(1);
const initParams = {};
new URLSearchParams(urlSearchParams).forEach((value, key) => {
initParams[key] = value;
});
new URLSearchParams(urlHashParamsAsSearchParams).forEach((value, key) => {
initParams[key] = value;
});
return initParams;
};
exports.getInitialisationParameters = getInitialisationParameters;
const getValidSSOProviders = (discoveredSSOProviders) => {
if (!discoveredSSOProviders) {
return [];
}
if (!Array.isArray(discoveredSSOProviders)) {
(0, helpers_1.authLog)(`Discovered SSO providers should be a list, got ${discoveredSSOProviders}`, 'warn');
}
if (discoveredSSOProviders.length === 0) {
(0, helpers_1.authLog)('List of discovered SSO providers was empty');
return [];
}
const validSSOProviders = discoveredSSOProviders.filter(provider => {
const missingKeys = settings_1.mandatoryKeysForSSOProviders.filter(key => !provider.hasOwnProperty(key));
if (missingKeys.length !== 0) {
(0, helpers_1.authLog)(`Dropping invalid discovered sso provider with id: "${provider.id}", missing key(s) ${missingKeys.join(', ')} `);
return false;
}
const missingParamKeys = settings_1.mandatoryKeysForSSOProviderParams.filter(key => !provider.params.hasOwnProperty(key));
if (missingParamKeys.length !== 0) {
(0, helpers_1.authLog)(`Dropping invalid discovered SSO provider with id: "${provider.id}", missing params key(s) ${missingParamKeys.join(', ')}`);
return false;
}
return true;
});
(0, helpers_1.authLog)('Checked SSO providers');
return validSSOProviders.map(ssoProvider => (Object.assign({
// visibility was introduced in 5.14.0 and defaults to true
visible: true }, ssoProvider)));
};
exports.getValidSSOProviders = getValidSSOProviders;
const getCredentialsFromAuthResult = (result, selectedSSOProvider) => {
var _a, _b, _c;
(0, helpers_1.authLog)(`Attempting to assemble credentials for idp_id: ${selectedSSOProvider.id}`);
if (!selectedSSOProvider) {
throw new Error('No SSO provider passed');
}
if (!result) {
throw new Error('Missing result in auth result handler');
}
const tokenTypePrincipal = ((_a = selectedSSOProvider.config) === null || _a === void 0 ? void 0 : _a['token_type_principal']) ||
settings_1.defaultTokenTypePrincipal;
(0, helpers_1.authLog)(`Credentials, using token type "${tokenTypePrincipal}" to retrieve principal`);
let parsedJWT;
try {
parsedJWT = (0, jwt_decode_1.default)(result[tokenTypePrincipal]);
}
catch (err) { }
if (!parsedJWT) {
throw new Error(`Could not parse JWT of type "${tokenTypePrincipal}" for idp_id "${selectedSSOProvider.id}", aborting`);
}
(0, helpers_1.authDebug)('Credentials, parsed JWT', parsedJWT);
const principal = (_b = selectedSSOProvider.config) === null || _b === void 0 ? void 0 : _b.principal;
if (principal) {
(0, helpers_1.authLog)(`Credentials, provided principal in config: ${principal}`);
}
else {
(0, helpers_1.authLog)(`Credentials, no principal provided in config, falling back to 'email' then 'sub'`);
}
const credsPrincipal = parsedJWT[principal] || parsedJWT.email || parsedJWT.sub;
(0, helpers_1.authLog)(`Credentials assembly with username: ${credsPrincipal}`);
const configuredTokenType = (_c = selectedSSOProvider.config) === null || _c === void 0 ? void 0 : _c['token_type_authentication'];
const tokenTypeAuthentication = configuredTokenType || settings_1.defaultTokenTypeAuthentication;
if (!configuredTokenType) {
(0, helpers_1.authLog)(`token_type_authentication not configured, using default token type "${settings_1.defaultTokenTypeAuthentication}".`);
}
(0, helpers_1.authLog)(`Credentials assembled with token type "${tokenTypeAuthentication}" as password. If connection still does not succeed, make sure 'neo4j.conf' is set up correctly`);
return {
username: credsPrincipal,
password: result[tokenTypeAuthentication]
};
};
exports.getCredentialsFromAuthResult = getCredentialsFromAuthResult;
const temporarilyStoreUrlSearchParams = () => {
const currentBrowserURLParams = (0, exports.getInitialisationParameters)();
(0, helpers_1.authLog)(`Temporarily storing the url search params. data: "${JSON.stringify(currentBrowserURLParams)}"`);
window.sessionStorage.setItem(constants_1.AUTH_STORAGE_URL_SEARCH_PARAMS, JSON.stringify(currentBrowserURLParams));
};
exports.temporarilyStoreUrlSearchParams = temporarilyStoreUrlSearchParams;
const storeRefreshTokenData = (refreshToken, selectedSSOProviderId) => {
(0, helpers_1.authLog)('Storing refresh data');
window.sessionStorage.setItem(constants_1.AUTH_STORAGE_REFRESH_DATA, JSON.stringify({ refreshToken, selectedSSOProviderId }));
};
exports.storeRefreshTokenData = storeRefreshTokenData;
const retrieveRefreshTokenData = () => {
const emptyResponse = { refreshToken: null, selectedSSOProviderId: null };
try {
const data = window.sessionStorage.getItem(constants_1.AUTH_STORAGE_REFRESH_DATA);
if (!data)
return emptyResponse;
return JSON.parse(data);
}
catch (err) {
(0, helpers_1.authLog)(`Parsing of refresh token data failed, err: ${err}`);
return emptyResponse;
}
};
exports.retrieveRefreshTokenData = retrieveRefreshTokenData;
const clearRefreshTokenData = () => window.sessionStorage.removeItem(constants_1.AUTH_STORAGE_REFRESH_DATA);
exports.clearRefreshTokenData = clearRefreshTokenData;
const getSSOServerIdIfShouldRedirect = () => {
const { searchParams } = new URL(window.location.href);
return searchParams.get(constants_1.SSO_REDIRECT);
};
exports.getSSOServerIdIfShouldRedirect = getSSOServerIdIfShouldRedirect;
const wasRedirectedBackFromSSOServer = () => {
const { auth_flow_step: authFlowStep } = (0, exports.getInitialisationParameters)();
return (authFlowStep || '').toLowerCase() === constants_1.REDIRECT_URI;
};
exports.wasRedirectedBackFromSSOServer = wasRedirectedBackFromSSOServer;
const restoreSearchAndHashParams = (toRetrieveParams = [], isClearStore = true) => {
(0, helpers_1.authLog)(`Retrieving temporarily stored url search params, params to retrieve: "${toRetrieveParams}"`);
try {
const storedParams = JSON.parse(window.sessionStorage.getItem(constants_1.AUTH_STORAGE_URL_SEARCH_PARAMS));
if (isClearStore) {
(0, helpers_1.authLog)('Clearing temporarily stored url search params.');
window.sessionStorage.removeItem(constants_1.AUTH_STORAGE_URL_SEARCH_PARAMS);
}
if (!(0, utils_1.isObject)(storedParams)) {
throw new Error(`Stored search params were ${storedParams}, expected an object.`);
}
let parameters = storedParams;
if (toRetrieveParams === null || toRetrieveParams === void 0 ? void 0 : toRetrieveParams.length) {
parameters = (0, lodash_pick_1.default)(storedParams, toRetrieveParams);
}
const crntHashParams = window.location.hash || undefined;
(0, helpers_1.addSearchParamsInBrowserHistory)(parameters);
const newUrl = `${window.location.href}${crntHashParams || ''}`;
window.history.replaceState({}, '', newUrl);
return parameters;
}
catch (err) {
(0, helpers_1.authLog)(`Error when parsing temporarily stored url search params, err: ${err}. Clearing.`);
window.sessionStorage.removeItem(constants_1.AUTH_STORAGE_URL_SEARCH_PARAMS);
return null;
}
};
exports.restoreSearchAndHashParams = restoreSearchAndHashParams;