/**
* All functions in this module are action creators and the return value should be passed to the
* redux store dispatch() function.
*
* IMPORTANT: This file contains imports that should only be bundled when doing a 'node' build.
* This action file should never be imported in the web bundle
* @module
*/
import debugLib from 'debug';
import createAction from 'redux-actions/lib/createAction';
import getMasterKeyById from '../util/getMasterKeyById';
import unprotectAspNetData from '../util/unprotectAspNetData';
import RedirectError from '../../app/util/RedirectError';
import ContainerName from '../../app/data/enum/ContainerName';
import msUrlTokenDecode from '../util/msUrlTokenDecode';
import { cleanUserIdentity } from '../../app/actions/resources/accountActions';
import isLocalOrDevelopment from './../util/isLocalOrDevelopment';
import {
ASPNET_IDENTITY_APP_COOKIE,
ASPNET_MIGRATION_APP_COOKIE,
IDSRV_SESSION_COOKIE,
ASPNET_DOCS_COOKIE,
} from '../util/AuthenticationHelper/constants';
const debug = debugLib('SlimmingWorld:logoutResponseActions');
const SET_LOGOUT_RESPONSE = 'logoutResponseActions/SET_LOGOUT_RESPONSE';
/**
* Sets the logout response as decoded from the query string
* @function setLogoutResponse
* @param query The parsed query string. This will be decoded into an object
*/
export const setLogoutResponse = createAction(SET_LOGOUT_RESPONSE);
/**
* Validate if decoded contains Data.ClientId if it's missing it should
* redirects to logout confirmation.
* if Data.Client exist it should clean redux state identity, cookies from the browser
* and redirect to postLogoutRedirectUri
*/
const redirectLogoutValidation = (decoded, res, environmentConfig) => dispatch => {
// if Data.ClientId exist redirects to post logout redirect uri
if (decoded.Data.ClientId) {
// clean user identity in redux state
dispatch(cleanUserIdentity());
// clean the cookies in the browser
res.clearCookie(ASPNET_IDENTITY_APP_COOKIE, {});
res.clearCookie(ASPNET_MIGRATION_APP_COOKIE, {});
res.clearCookie(IDSRV_SESSION_COOKIE, {});
res.clearCookie(ASPNET_DOCS_COOKIE, {});
// redirect to postLogoutRedirectUri;
// if it's local should prepend account host otherwise just redirect to postLogoutRedirectUri
throw new RedirectError(
isLocalOrDevelopment()
? `${environmentConfig.web.account.host}${decoded.Data.PostLogoutRedirectUri}`
: decoded.Data.PostLogoutRedirectUri,
);
}
};
/**
* We need to clear the migration cookie nd redirect to the public site
*
* @param res
* @returns {Function}
*/
export const redirectMigrationLogout = (res, environmentConfig) => dispatch => {
// clean user identity in redux state
dispatch(cleanUserIdentity());
// clean the cookies in the browser
res.clearCookie(ASPNET_MIGRATION_APP_COOKIE, {});
// throw new RedirectError(`${config.web.public.host}`);
res.redirect(environmentConfig.web.public.host);
};
/**
* Parse the logout response on the query parameters, if it is present.
* If the logout response is found, it will be decoded and validated using
* the signature in the query string. If a valid response is present, it will
* dispatch the setLogoutResponse action to pass the response to the redux
* state. This will be read from routeRequirements on the logout callback route.
* @param query The query object as parsed by react-router
* @param res
* @param azureBlobConnectionString
*/
export const parseLogoutResponseQuery = (
query,
res,
{ azureBlobConnectionString, azureBlobContainerPrefix, ...environmentConfig },
) => async dispatch => {
if (query.logoutId) {
const PURPOSES = [
'SlimmingWorld.Platform.Account.Web',
'IdentityServer4.Stores.ProtectedDataMessageStore',
];
let data;
try {
data = msUrlTokenDecode(query.logoutId);
} catch (e) {
debug('Could not parse logoutId response query as base64. Ignoring query.');
return;
}
let decrypted;
try {
decrypted = await unprotectAspNetData(
data,
PURPOSES,
getMasterKeyById,
azureBlobConnectionString,
`${azureBlobContainerPrefix}${ContainerName.ACCOUNT}`,
);
} catch (e) {
debug(`Error during unprotectAspNetData in logoutResponseActions:\n${e.message || e}`);
return;
}
const decoded = JSON.parse(decrypted.toString());
dispatch(setLogoutResponse(decoded));
dispatch(redirectLogoutValidation(decoded, res, environmentConfig));
}
};