* fix: redirect correctly in development * fix: prevent // appearing in path * refactor: remove old comments * fix: remove trailing slash for redirection
		
			
				
	
	
		
			84 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
const jwt = require('jsonwebtoken');
 | 
						|
const { availableLangs } = require('../../../client/i18n/allLangs');
 | 
						|
const { allowedOrigins } = require('../../../config/cors-settings');
 | 
						|
// homeLocation is being used as a fallback here. If the one provided by the
 | 
						|
// client is invalid we default to this.
 | 
						|
const { homeLocation } = require('../../../config/env.json');
 | 
						|
 | 
						|
function getReturnTo(encryptedParams, secret, _homeLocation = homeLocation) {
 | 
						|
  let params;
 | 
						|
  try {
 | 
						|
    params = jwt.verify(encryptedParams, secret);
 | 
						|
  } catch (e) {
 | 
						|
    // TODO: report to Sentry? Probably not. Remove entirely?
 | 
						|
    console.log(e);
 | 
						|
    // something went wrong, use default params
 | 
						|
    params = {
 | 
						|
      returnTo: `${_homeLocation}/learn`,
 | 
						|
      origin: _homeLocation,
 | 
						|
      pathPrefix: ''
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  return normalizeParams(params, _homeLocation);
 | 
						|
}
 | 
						|
 | 
						|
function normalizeParams(
 | 
						|
  { returnTo, origin, pathPrefix },
 | 
						|
  _homeLocation = homeLocation
 | 
						|
) {
 | 
						|
  // coerce to strings, just in case something weird and nefarious is happening
 | 
						|
  returnTo = '' + returnTo;
 | 
						|
  origin = '' + origin;
 | 
						|
  pathPrefix = '' + pathPrefix;
 | 
						|
  // we add the '/' to prevent returns to
 | 
						|
  // www.freecodecamp.org.somewhere.else.com
 | 
						|
  if (
 | 
						|
    !returnTo ||
 | 
						|
    !allowedOrigins.some(allowed => returnTo.startsWith(allowed + '/'))
 | 
						|
  ) {
 | 
						|
    returnTo = `${_homeLocation}/learn`;
 | 
						|
    origin = _homeLocation;
 | 
						|
    pathPrefix = '';
 | 
						|
  }
 | 
						|
  if (!origin || !allowedOrigins.includes(origin)) {
 | 
						|
    returnTo = `${_homeLocation}/learn`;
 | 
						|
    origin = _homeLocation;
 | 
						|
    pathPrefix = '';
 | 
						|
  }
 | 
						|
  pathPrefix = availableLangs.client.includes(pathPrefix) ? pathPrefix : '';
 | 
						|
  return { returnTo, origin, pathPrefix };
 | 
						|
}
 | 
						|
 | 
						|
// TODO: tests!
 | 
						|
// TODO: ensure origin and pathPrefix validation happens first
 | 
						|
// (it needs a dedicated function that can be called from here and getReturnTo)
 | 
						|
function getRedirectBase(origin, pathPrefix) {
 | 
						|
  const redirectPathSegment = pathPrefix ? `/${pathPrefix}` : '';
 | 
						|
  return `${origin}${redirectPathSegment}`;
 | 
						|
}
 | 
						|
 | 
						|
function getRedirectParams(req, _normalizeParams = normalizeParams) {
 | 
						|
  const url = req.header('Referer');
 | 
						|
  // since we do not always redirect the user back to the page they were on
 | 
						|
  // we need client locale and origin to construct the redirect url.
 | 
						|
  const returnUrl = new URL(url ? url : homeLocation);
 | 
						|
  const origin = returnUrl.origin;
 | 
						|
  // if this is not one of the client languages, validation will convert
 | 
						|
  // this to '' before it is used.
 | 
						|
  const pathPrefix = returnUrl.pathname.split('/')[0];
 | 
						|
  return _normalizeParams({ returnTo: returnUrl.href, origin, pathPrefix });
 | 
						|
}
 | 
						|
 | 
						|
function isRootPath(redirectBase, returnUrl) {
 | 
						|
  const base = new URL(redirectBase);
 | 
						|
  const url = new URL(returnUrl);
 | 
						|
  return base.pathname === url.pathname;
 | 
						|
}
 | 
						|
 | 
						|
module.exports.getReturnTo = getReturnTo;
 | 
						|
module.exports.getRedirectBase = getRedirectBase;
 | 
						|
module.exports.normalizeParams = normalizeParams;
 | 
						|
module.exports.getRedirectParams = getRedirectParams;
 | 
						|
module.exports.isRootPath = isRootPath;
 |