Files
.github
api-server
common
public
server
boot
boot_tests
manifests
middlewares
models
rss
utils
__mocks__
about.js
auth.js
bad-id-map.js
cast-to-observable.js
certTypes.json
constantStrings.json
constants.js
cookieConfig.js
create-handled-error.js
date-utils.js
date-utils.test.js
donation.js
donation.test.js
get-curriculum.js
getDynamicPropsForUser.js
getSetAccessToken.js
getSetAccessToken.test.js
in-memory-cache.js
in-memory-cache.test.js
index.js
lang-passthrough-urls.js
middleware.js
publicUserProps.js
react.js
redirection.js
redirection.test.js
rx.js
superBlockCertTypeMap.js
url-utils.js
user-stats.js
user-stats.test.js
validators.js
views
README.md
component-passport.js
config.development.js
config.json
config.local.js
config.production.js
datasources.development.js
datasources.json
datasources.production.js
index.js
middleware.json
model-config.json
passport-providers.js
.babelrc.js
.gitignore
development-start.js
jest.config.js
package-lock.json
package.json
production-start.js
client
config
curriculum
cypress
docs
tools
utils
.editorconfig
.eslintignore
.eslintrc-base.json
.eslintrc.json
.gitattributes
.gitignore
.gitpod.yml
.node-inspectorrc
.npmrc
.prettierignore
.prettierrc
.snyk
.vcmrc
CODE_OF_CONDUCT.md
CONTRIBUTING.md
HoF.md
LICENSE.md
README.md
SECURITY.md
change_volumes_owner.sh
cypress-install.js
cypress.json
jest.config.js
lerna.json
lighthouserc.js
package-lock.json
package.json
sample.env
freeCodeCamp/api-server/server/utils/redirection.js

88 lines
3.0 KiB
JavaScript
Raw Normal View History

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);
}
// TODO: tests!
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}`;
}
// TODO: this might be cleaner if we just use a URL for returnTo (call it
// returnURL for clarity) rather than pulling out origin and returning it
// separately
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);
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;