@okta/okta-auth-js
Version:
The Okta Auth SDK
225 lines (221 loc) • 9.03 kB
JavaScript
/*!
* Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (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.
*/
import { __rest } from '../_virtual/_tslib.js';
import { warn } from '../util/console.js';
import { split2 } from '../util/misc.js';
import * as index from './remediators/index.js';
import { GenericRemediator } from './remediators/GenericRemediator/GenericRemediator.js';
import { IdxFeature } from './types/api.js';
function isTerminalResponse(idxResponse) {
const { neededToProceed, interactionCode } = idxResponse;
return !neededToProceed.length && !interactionCode;
}
function canSkipFn(idxResponse) {
return idxResponse.neededToProceed.some(({ name }) => name === 'skip');
}
function canResendFn(idxResponse) {
return Object.keys(idxResponse.actions).some(actionName => actionName.includes('resend'));
}
function getMessagesFromIdxRemediationValue(value) {
if (!value || !Array.isArray(value)) {
return;
}
return value.reduce((messages, value) => {
if (value.messages) {
messages = [...messages, ...value.messages.value];
}
if (value.form) {
const messagesFromForm = getMessagesFromIdxRemediationValue(value.form.value) || [];
messages = [...messages, ...messagesFromForm];
}
if (value.options) {
let optionValues = [];
value.options.forEach(option => {
if (!option.value || typeof option.value === 'string') {
return;
}
optionValues = [...optionValues, option.value];
});
const messagesFromOptions = getMessagesFromIdxRemediationValue(optionValues) || [];
messages = [...messages, ...messagesFromOptions];
}
return messages;
}, []);
}
function getMessagesFromResponse(idxResponse, options) {
var _a;
let messages = [];
const { rawIdxState, neededToProceed } = idxResponse;
const globalMessages = (_a = rawIdxState.messages) === null || _a === void 0 ? void 0 : _a.value.map(message => message);
if (globalMessages) {
messages = [...messages, ...globalMessages];
}
if (!options.useGenericRemediator) {
for (let remediation of neededToProceed) {
const fieldMessages = getMessagesFromIdxRemediationValue(remediation.value);
if (fieldMessages) {
messages = [...messages, ...fieldMessages];
}
}
}
const seen = {};
messages = messages.reduce((filtered, message) => {
var _a;
const key = (_a = message.i18n) === null || _a === void 0 ? void 0 : _a.key;
if (key && seen[key]) {
return filtered;
}
seen[key] = message;
filtered = [...filtered, message];
return filtered;
}, []);
return messages;
}
function getEnabledFeatures(idxResponse) {
const res = [];
const { actions, neededToProceed } = idxResponse;
if (actions['currentAuthenticator-recover']) {
res.push(IdxFeature.PASSWORD_RECOVERY);
}
if (neededToProceed.some(({ name }) => name === 'select-enroll-profile')) {
res.push(IdxFeature.REGISTRATION);
}
if (neededToProceed.some(({ name }) => name === 'redirect-idp')) {
res.push(IdxFeature.SOCIAL_IDP);
}
if (neededToProceed.some(({ name }) => name === 'unlock-account')) {
res.push(IdxFeature.ACCOUNT_UNLOCK);
}
return res;
}
function getAvailableSteps(authClient, idxResponse, useGenericRemediator) {
var _a;
const res = [];
const remediatorMap = Object.values(index)
.reduce((map, remediatorClass) => {
if (remediatorClass.remediationName) {
map[remediatorClass.remediationName] = remediatorClass;
}
return map;
}, {});
for (let remediation of idxResponse.neededToProceed) {
const T = getRemediatorClass(remediation, { useGenericRemediator, remediators: remediatorMap });
if (T) {
const remediator = new T(remediation);
res.push(remediator.getNextStep(authClient, idxResponse.context));
}
}
for (const [name] of Object.entries((idxResponse.actions || {}))) {
let stepObj = {
name,
action: async (params) => {
return authClient.idx.proceed({
actions: [{ name, params }]
});
}
};
if (name.startsWith('currentAuthenticator')) {
const [part1, part2] = split2(name, '-');
const actionObj = idxResponse.rawIdxState[part1].value[part2];
const rest = __rest(actionObj, ["href", "method", "rel", "accepts", "produces"]);
const value = (_a = actionObj.value) === null || _a === void 0 ? void 0 : _a.filter(item => item.name !== 'stateHandle');
stepObj = Object.assign(Object.assign(Object.assign({}, rest), (value && { value })), stepObj);
}
res.push(stepObj);
}
return res;
}
function filterValuesForRemediation(idxResponse, remediationName, values) {
const remediations = idxResponse.neededToProceed || [];
const remediation = remediations.find(r => r.name === remediationName);
if (!remediation) {
warn(`filterValuesForRemediation: "${remediationName}" did not match any remediations`);
return values;
}
const valuesForRemediation = remediation.value.reduce((res, entry) => {
const { name, value } = entry;
if (name === 'stateHandle') {
res[name] = value;
}
else {
res[name] = values[name];
}
return res;
}, {});
return valuesForRemediation;
}
function getRemediatorClass(remediation, options) {
const { useGenericRemediator, remediators } = options;
if (!remediation) {
return undefined;
}
if (useGenericRemediator) {
return GenericRemediator;
}
return remediators[remediation.name];
}
function getRemediator(idxRemediations, values, options) {
const remediators = options.remediators;
const useGenericRemediator = options.useGenericRemediator;
let remediator;
if (options.step) {
const remediation = idxRemediations.find(({ name }) => name === options.step);
if (remediation) {
const T = getRemediatorClass(remediation, options);
return T ? new T(remediation, values, options) : undefined;
}
else {
warn(`step "${options.step}" did not match any remediations`);
return;
}
}
const remediatorCandidates = [];
if (useGenericRemediator) {
remediatorCandidates.push(new GenericRemediator(idxRemediations[0], values, options));
}
else {
for (let remediation of idxRemediations) {
const isRemeditionInFlow = Object.keys(remediators).includes(remediation.name);
if (!isRemeditionInFlow) {
continue;
}
const T = getRemediatorClass(remediation, options);
remediator = new T(remediation, values, options);
if (remediator.canRemediate()) {
return remediator;
}
remediatorCandidates.push(remediator);
}
}
return remediatorCandidates[0];
}
function getNextStep(authClient, remediator, idxResponse) {
const nextStep = remediator.getNextStep(authClient, idxResponse.context);
const canSkip = canSkipFn(idxResponse);
const canResend = canResendFn(idxResponse);
return Object.assign(Object.assign(Object.assign({}, nextStep), (canSkip && { canSkip })), (canResend && { canResend }));
}
function handleFailedResponse(authClient, idxResponse, options = {}) {
const terminal = isTerminalResponse(idxResponse);
const messages = getMessagesFromResponse(idxResponse, options);
if (terminal) {
return { idxResponse, terminal, messages };
}
else {
const remediator = getRemediator(idxResponse.neededToProceed, {}, options);
const nextStep = remediator && getNextStep(authClient, remediator, idxResponse);
return Object.assign({ idxResponse,
messages }, (nextStep && { nextStep }));
}
}
export { canResendFn, canSkipFn, filterValuesForRemediation, getAvailableSteps, getEnabledFeatures, getMessagesFromIdxRemediationValue, getMessagesFromResponse, getNextStep, getRemediator, handleFailedResponse, isTerminalResponse };
//# sourceMappingURL=util.js.map