Without polling from user side is it possible to Refresh the Access Token with refresh token

Hi,
In my code, has refresh access token functionality but it requires regular interval of polling to trigger the refresh mechanism
here is the code

import NextAuth, { NextAuthOptions } from “next-auth”;
import KeycloakProvider from “next-auth/providers/keycloak”;
import jwt_decode from ‘jwt-decode’;
export const authOptions: NextAuthOptions = {
providers: [
KeycloakProvider({
clientId: process.env.KEYCLOAK_ID || ‘’,
clientSecret: process.env.KEYCLOAK_SECRET || ‘’,
issuer: process.env.KEYCLOAK_ISSUER || ‘’,
profile(profile) {
return {
id: profile.sub,
name: profile.name ?? profile.preferred_username,
email: profile.email,
image: profile.picture,
acr: profile.acr,
familyName: profile.family_name,
givenName: profile.given_name,
preferredUsername: profile.preferred_username
}
}
})
],
pages: {
signIn: ‘/signin’,
signOut: ‘/?logout=true’
},
callbacks: {
async jwt({ token, account }: any) {
if (account) {
return {
…token,
accessToken: account.access_token,
accessTokenExpires: Date.now() + account.expires_at * 1000,
id_token_hint: account.id_token,
refreshToken: account.refresh_token,
}
}
//current time calculation
const currentTimestamp = Math.floor(Date.now() / 1000);
const tokens = token.accessToken;
const decoded: any = jwt_decode(tokens);
const threshold = Number(process.env.REFRESH_TOKEN_THRESHOLD) || 120;
// trigger refreshtoken function based on threshold value
if (currentTimestamp > (decoded.exp - threshold)) {
try {
// if access token is invalid fetch new token
const refreshedToken = await refreshAccessToken(token);
console.log(“refresh access token success”)
if (refreshedToken.accessToken) {
return {
accessToken: refreshedToken.accessToken,
accessTokenExpires: refreshedToken.accessTokenExpires,
refreshToken: refreshedToken.refreshToken ?? token.refreshToken,
}
}
} catch (error) {
// Handle failure (e.g., redirect to login, notify the user, etc.)
return {
…token,
error: “Failed to refresh token”,
};
};
} else {
// else return original valid token
return token;
}
},
async session({ session, token }: any) {
// Send properties to the client, like an access_token from a provider.
session.accessToken = token.accessToken;
session.refreshToken = token.refreshToken
session.id_token = token.id_token_hint
return session;
}
}
};
// fetching new accesstoken using refresh token, ticket no E20-1015
async function refreshAccessToken(token: any) {
try {
const url = ${process.env.KEYCLOAK_ISSUER}/protocol/openid-connect/token;
const response = await fetch(url, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/x-www-form-urlencoded’,
},
body: new URLSearchParams({
client_id: process.env.KEYCLOAK_ID || ‘’,
client_secret: process.env.KEYCLOAK_SECRET || ‘’,
grant_type: ‘refresh_token’,
refresh_token: token.refreshToken,
}),
});
const refreshedTokens = await response.json();
if (!response.ok) {
throw refreshedTokens;
}
// return refreshed token
return {
accessToken: refreshedTokens.access_token,
accessTokenExpires: Date.now() / 1000 + (refreshedTokens.expires_in),
refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, // Fall back to old refresh token
};
} catch (error) {
console.error(‘RefreshAccessTokenError’, error);
// return error if failed to fetch access token
return {
…token,
error: ‘RefreshAccessTokenError’,
};
}
}
export default NextAuth(authOptions);

here the problem is without that polling the current timestamp value is not getting changed as live value
is there any fix for this?
Securing applications authentication client-configuration oidc Tips and tricks.