Skip to content

Session Monitoring

For applications that need to react to session changes in real time, @authrim/web provides a small set of browser-side coordination helpers. They cover cross-tab synchronization, OIDC OP session checks, front-channel logout handling, and the lower-level check_session_iframe transport.

FeaturePurposeBrowser Support
Tab SyncCoordinate auth state and leader election across browser tabsModern browsers with BroadcastChannel
Session MonitorPoll the OP check_session_iframe for OIDC session changesLimited by iframe and third-party cookie behavior
Front-Channel LogoutValidate logout requests loaded by the OP in an iframeLimited by iframe and browser storage behavior
Check Session IframeLow-level postMessage wrapper around check_session_iframeLimited by iframe and third-party cookie behavior

TabSyncManager uses BroadcastChannel to notify other tabs about session changes and logout. It also elects one active leader tab, which is useful when only one tab should run periodic work.

import { TabSyncManager } from '@authrim/web';
const tabSync = new TabSyncManager({
channelName: 'authrim-session',
heartbeatIntervalMs: 5000,
leaderTimeoutMs: 15000,
});
tabSync.initialize();
const unsubscribeLeader = tabSync.onLeaderChange((isLeader) => {
if (isLeader) {
console.log('This tab is now responsible for background checks');
}
});
// Broadcast when this tab observes a new session state.
const sessionResponse = await auth.session.get();
tabSync.broadcastSessionChange(sessionResponse.data?.session ?? null);
// Broadcast logout after clearing local auth state.
tabSync.broadcastLogout();
window.addEventListener('beforeunload', () => {
unsubscribeLeader();
tabSync.destroy();
});

If you pass a compatible eventEmitter, the manager emits session:sync for cross-tab session changes, logout, and leader changes. Without an emitter, you can still use onLeaderChange() and manually call broadcastSessionChange() or broadcastLogout() from your auth flow.

ParameterTypeDefaultDescription
channelNamestring'authrim-session'BroadcastChannel name
heartbeatIntervalMsnumber5000Leader heartbeat interval
leaderTimeoutMsnumber15000Time before another tab can claim leadership
eventEmitterEventEmitter-Optional SDK event emitter for session:sync events

SessionMonitor implements the RP side of OIDC Session Management. It loads the OP’s check_session_iframe, polls it with the current session_state, and emits events when the OP reports that the session changed.

import { SessionMonitor } from '@authrim/web';
const monitor = new SessionMonitor({
checkSessionIframeUrl: discovery.check_session_iframe,
clientId: 'my-app',
opOrigin: 'https://auth.example.com',
pollInterval: 2000,
maxErrors: 3,
});
const unsubscribe = monitor.on(async (event) => {
if (event.type === 'session:changed') {
await auth.signOut({ logoutScope: 'local' });
window.location.href = '/login';
}
if (event.type === 'session:error') {
console.warn('OIDC session check failed:', event.error);
}
});
await monitor.start(initialSessionState);
// After a successful re-authentication, update the monitored session_state.
monitor.updateSessionState(newSessionState);
window.addEventListener('beforeunload', () => {
monitor.stop();
unsubscribe();
});
ParameterTypeDefaultDescription
checkSessionIframeUrlstring-OP check_session_iframe URL from discovery
clientIdstring-OAuth client ID
opOriginstring-Expected OP origin for postMessage validation
pollIntervalnumber2000Polling interval in milliseconds
maxErrorsnumber3Consecutive errors before the monitor stops
TypeMeaning
session:changedOP reports that the user session changed
session:unchangedOP reports that the monitored session_state is still current
session:errorThe iframe check failed or the OP returned error
session:stoppedMonitoring stopped manually or after too many errors

FrontChannelLogoutHandler validates OIDC front-channel logout requests delivered to your registered logout URI. The OP typically loads this URI in a hidden iframe with iss and optionally sid query parameters.

Register a front-channel logout URI in the Authrim Admin panel:

SettingValue
Front-Channel Logout URIhttps://myapp.com/logout/front-channel
Front-Channel Logout Session Requiredtrue when you can validate sid
import { FrontChannelLogoutHandler } from '@authrim/web';
const handler = new FrontChannelLogoutHandler({
issuer: 'https://auth.example.com',
sessionId: currentSessionId,
requireIss: true,
requireSid: true,
onLogout: async (params) => {
await auth.signOut({ logoutScope: 'local' });
console.log('Front-channel logout handled:', params.sid);
},
});
if (handler.isLogoutRequest()) {
const result = await handler.handleCurrentUrl();
if (!result.success) {
console.warn('Invalid front-channel logout request:', result.error);
}
}
ParameterTypeDefaultDescription
issuerstring-Expected OP issuer
sessionIdstring-Current session ID for sid validation
requireIssbooleanfalseRequire and validate the iss parameter
requireSidbooleanfalseRequire and validate the sid parameter
onLogout(params) => void | Promise<void>-Called after request validation succeeds

CheckSessionIframeManager is the lower-level wrapper used by SessionMonitor. Use it directly when you want to control polling yourself.

import { CheckSessionIframeManager } from '@authrim/web';
const manager = new CheckSessionIframeManager({
checkSessionIframeUrl: 'https://auth.example.com/check-session',
clientId: 'my-app',
opOrigin: 'https://auth.example.com',
timeout: 5000,
});
await manager.initialize();
const result = await manager.checkSession(currentSessionState);
if (result.response === 'changed') {
await auth.signOut({ logoutScope: 'local' });
window.location.href = '/login';
}
manager.destroy();
ParameterTypeDefaultDescription
checkSessionIframeUrlstring-OP check_session_iframe URL
clientIdstring-OAuth client ID
opOriginstring-Expected OP origin for message validation
timeoutnumber5000Iframe load and message response timeout

A practical browser setup usually combines Tab Sync with one explicit session check path:

import { TabSyncManager } from '@authrim/web';
const tabSync = new TabSyncManager();
tabSync.initialize();
const stopLeader = tabSync.onLeaderChange((isLeader) => {
if (!isLeader) return;
const timer = window.setInterval(async () => {
const isValid = await auth.session.validate();
if (!isValid) {
await auth.signOut({ logoutScope: 'local' });
tabSync.broadcastLogout();
window.location.href = '/login';
}
}, 60000);
window.addEventListener('beforeunload', () => window.clearInterval(timer), {
once: true,
});
});
window.addEventListener('beforeunload', () => {
stopLeader();
tabSync.destroy();
});

Add SessionMonitor when your deployment exposes OIDC check_session_iframe and you need OP-session change detection in addition to app-session validation.