@luigi-project/plugin-auth-oauth2
Version:
OAuth2 implicit grant provider plugin for @luigi-project/core
127 lines (115 loc) • 4.55 kB
HTML
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript">
const tokenLifetimeDays = 7;
const getParameterByName = (name) => {
return new URLSearchParams(location.search).get(name);
};
const setAuthData = (data) => {
const storageType = getParameterByName('storageType') || 'localStorage';
switch (storageType) {
case 'localStorage':
case 'sessionStorage':
window[storageType].setItem('luigi.auth', JSON.stringify(data));
window[storageType].setItem('luigi.newlyAuthorized', true);
break;
default:
console.error(
'Configuration Error: Invalid auth.storage setting. Must be either localStorage or sessionStorage to be used with OAuth2 Provider.',
);
}
};
const getHashParams = () => {
let hash = encodeURIComponent(window.location.hash.substring(1));
return decodeURIComponent(hash)
.split('&')
.reduce(function (result, item) {
var parts = item.split('=');
result[parts[0]] = parts[1];
return result;
}, {});
};
const processExpDate = (expiresInString) => {
let expirationDate;
const expiresIn = Number(expiresInString);
if (!isNaN(expiresIn) && expiresIn > 0) {
const nsToMsMultiplier = 1000;
expirationDate =
Number(new Date()) + nsToMsMultiplier * (expiresIn - tokenLifetimeDays);
}
return expirationDate;
};
const parseJwt = (token) => {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
atob(base64)
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join(''),
);
return JSON.parse(jsonPayload);
};
</script>
</head>
<body>
<script type="text/javascript">
const uri = encodeURIComponent(window.location.href);
const hashParams = getHashParams(uri);
const token = hashParams['access_token'] || hashParams['id_token'];
if (hashParams && (token || hashParams['error'])) {
const error = hashParams['error'];
const { exp } = parseJwt(hashParams['id_token']);
const expires_in = hashParams['expires_in'] || exp;
if (!error) {
const data = {
accessToken: token,
accessTokenExpirationDate: processExpDate(expires_in),
scope: hashParams['scope'],
idToken: hashParams['id_token'],
};
setAuthData(data);
const decodedState = atob(decodeURIComponent(hashParams['state'])).split(
'_luigiNonce=',
);
const appState = decodeURI(decodedState[0] || '');
const nonce = decodedState[1];
if (nonce !== sessionStorage.getItem('luigi.nonceValue')) {
document.getElementsByTagName('body')[0].innerHTML =
'Something went wrong. Try to log in again.';
throw new Error(
'State parameter returned from the authorization endpoint does not match locally stored state. Aborting login process.',
);
}
const appStateUrl = new URL(appState);
if (appStateUrl.origin === window.location.origin) {
const newUrl = new URL(window.location.href);
newUrl.pathname = appStateUrl.pathname;
newUrl.search = appStateUrl.search;
newUrl.hash = appStateUrl.hash;
window.location.href = newUrl.href;
} else {
window.location.href = '/';
console.log(
`Preventing redirect to ${appState} as it does not match the current origin.`,
);
}
} else {
// else tree only applies to idtoken auths, I guess
const errorDescription = hashParams['error_description'];
console.error('error', errorDescription);
const params = new URLSearchParams();
params.set('error', error);
params.set('errorDescription', errorDescription);
const url = new URL('/', window.location.href);
url.search = params;
window.location.href = url.href;
}
}
</script>
</body>
</html>