export const isTokenExpired = (token: string): boolean => {
const decoded = jwtDecode<DecodedToken>(token)
return decoded.exp * 1000 < Date.now()
}
export function getTokenExpirationTime(token: string): number {
const payload = JSON.parse(atob(token.split('.')[1]))
return payload.exp * 1000
}
export const validateAccessToken = async () => {
const session = (await getSession()) as CustomSession | null
if (!session) return
const accessToken = session.accessToken
const timeLeft = accessToken ? getTokenExpirationTime(accessToken) - Date.now() : 0
const refreshTimeout = setTimeout(async () => {
try {
await getValidAccessToken(session)
} catch (error) {
console.error(error)
}
}, Math.max(timeLeft - 5 * 60 * 1000, 0))
return () => clearTimeout(refreshTimeout)
}
async jwt({ token, profile, user }) {
const userWithTokens = user as CustomUser
if (user) {
token.accessToken = userWithTokens.accessToken
token.refreshToken = userWithTokens.refreshToken
token.accessTokenExpires = userWithTokens.accessTokenExpires;
}
if (profile) {
token.sub = profile.sub ?? ''
token.name = profile['cognito:username'] as string
}
if (Date.now() < (token.accessTokenExpires as number)) {
return token
}
const refreshedToken = await refreshAccessToken(
token?.refreshToken as string,
token?.name as string
)
if (refreshedToken) {
return {
...token,
accessToken: refreshedToken.accessToken,
accessTokenExpires: refreshedToken.accessTokenExpires,
}
}
return {
...token,
error: 'RefreshAccessTokenError',
}
},
export const refreshAccessToken = async (refreshToken: string, username: string) => {
const secretHash = await getSecretHash(username)
try {
const command = new InitiateAuthCommand({
AuthFlow: 'REFRESH_TOKEN_AUTH',
ClientId: clientId,
AuthParameters: {
REFRESH_TOKEN: refreshToken,
SECRET_HASH: secretHash,
},
})
const response = await cognitoClient.send(command)
const newAccessToken = response.AuthenticationResult?.AccessToken
const expiresIn = response.AuthenticationResult?.ExpiresIn || 3600
return {
accessToken: newAccessToken,
accessTokenExpires: Date.now() + expiresIn * 1000,
}
} catch (error) {
console.error('Error refreshing access token:', error)
return null
}
}