webadmin: remove the implicit flow

we now use pkce . main advantage is that we don't see the access token
in the url anymore.

in pkce, the auth code by itself is useless. need the verifier.

fixes #844
This commit is contained in:
Girish Ramakrishnan
2026-03-14 22:06:17 +05:30
parent dc1449c7b6
commit c15e342bb8
7 changed files with 101 additions and 28 deletions

View File

@@ -2,19 +2,59 @@
<script>
const tmp = window.location.hash.slice(1).split('&');
(async function () {
const params = new URLSearchParams(window.location.search);
const code = params.get('code');
// FIXME: implicit flow (response_type=code token) results in access_token query param. this is not secure
tmp.forEach(function (pair) {
if (pair.indexOf('access_token=') === 0) localStorage.token = pair.split('=')[1];
});
if (!code) {
console.error('No authorization code in callback URL');
window.location.replace('/');
return;
}
let redirectTo = '/';
if (localStorage.getItem('redirectToHash')) {
redirectTo += localStorage.getItem('redirectToHash');
localStorage.removeItem('redirectToHash');
}
const codeVerifier = sessionStorage.getItem('pkce_code_verifier');
const clientId = sessionStorage.getItem('pkce_client_id') || 'cid-webadmin';
const apiOrigin = sessionStorage.getItem('pkce_api_origin') || '';
window.location.replace(redirectTo); // this removes us from history
sessionStorage.removeItem('pkce_code_verifier');
sessionStorage.removeItem('pkce_client_id');
sessionStorage.removeItem('pkce_api_origin');
try {
const response = await fetch(apiOrigin + '/openid/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: clientId,
redirect_uri: window.location.origin + '/authcallback.html',
code_verifier: codeVerifier
})
});
const data = await response.json();
if (!response.ok || !data.access_token) {
console.error('Token exchange failed', data);
window.location.replace('/');
return;
}
localStorage.token = data.access_token;
} catch (e) {
console.error('Token exchange error', e);
window.location.replace('/');
return;
}
let redirectTo = '/';
if (localStorage.getItem('redirectToHash')) {
redirectTo += localStorage.getItem('redirectToHash');
localStorage.removeItem('redirectToHash');
}
window.location.replace(redirectTo);
})();
</script>