impersonation-banner
Version:
A banner that shows when a Keycloak impersonator is active
89 lines (73 loc) • 2.84 kB
JavaScript
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
})((function () { 'use strict';
(function (global) {
function parseJwt(token) {
try {
const payload = token.split('.')[1];
return JSON.parse(atob(payload));
} catch (e) {
console.error('[impersonation-banner] Invalid token:', e);
return null;
}
}
function checkImpersonation(token) {
const decoded = parseJwt(token);
const impersonator = decoded?.impersonator;
if (impersonator && Object.keys(impersonator).length > 0) {
return {
isImpersonating: true,
impersonator,
user: decoded?.preferred_username || decoded?.sub,
};
}
return { isImpersonating: false };
}
function showBanner({ isImpersonating, impersonator, user }) {
if (!isImpersonating) return;
if (document.getElementById('impersonation-banner')) return;
const banner = document.createElement('div');
banner.id = 'impersonation-banner';
banner.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
background: #f44336;
color: white;
padding: 15px 20px;
border-radius: 8px;
font-family: sans-serif;
font-size: 14px;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
`;
banner.innerHTML = `
🔒 You are impersonating <strong>User ${user}</strong><br/>
<small>As ${impersonator?.username || 'Unknown'}</small>
<button id="stop-impersonation" style="margin-top: 10px; background: white; color: #f44336; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer;">
Stop Impersonation
</button>
`;
document.body.appendChild(banner);
document.getElementById('stop-impersonation')?.addEventListener('click', () => {
global.keycloak?.logout?.() ?? location.reload();
});
}
function init() {
const keycloak = global.keycloak;
if (!keycloak || !keycloak.token) {
console.warn('[impersonation-banner] Keycloak instance or token not found');
return;
}
const result = checkImpersonation(keycloak.token);
showBanner(result);
}
// Export
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = { init };
} else {
global.ImpersonationBanner = { init };
}
})(typeof window !== 'undefined' ? window : globalThis);
}));