/** * TOKEN REFRESHER * Logic: Silent background token rotation. * Role: Communicates with Keycloak to exchange a Refresh Token for a new Access Token. */ import { keycloakConfig } from './keycloak-config'; export const refreshAccessToken = async (token: any) => { try { const url = `${process.env.KEYCLOAK_ISSUER_URL}/realms/${process.env.KEYCLOAK_REALM}/protocol/openid-connect/token`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ client_id: keycloakConfig.clientId, client_secret: keycloakConfig.clientSecret, grant_type: 'refresh_token', refresh_token: token.refreshToken, }), }); const refreshedTokens = await response.json(); if (!response.ok) throw refreshedTokens; return { ...token, accessToken: refreshedTokens.access_token, accessTokenExpires: Date.now() + refreshedTokens.expires_in * 1000, refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, // Fallback to old refresh token }; } catch (error) { console.error('Error refreshing access token', error); return { ...token, error: 'RefreshAccessTokenError', }; } };