in src/app/api/utils/auth.tsx [245:298]
async session({ session, token }) {
if (token.fxa) {
session.user.fxa = {
locale: token.fxa.locale,
twoFactorAuthentication: token.fxa.twoFactorAuthentication,
metricsEnabled: token.fxa.metricsEnabled,
avatar: token.fxa.avatar,
avatarDefault: token.fxa.avatarDefault,
subscriptions: token.fxa.subscriptions,
};
}
if (token.subscriber) {
session.user.subscriber = token.subscriber;
// refresh token
const dbFxATokens = await getFxATokens(token.subscriber.id);
if (
!dbFxATokens?.fxa_session_expiry ||
dbFxATokens.fxa_session_expiry.getTime() < Date.now()
) {
// If the access token has expired, try to refresh it
if (!dbFxATokens?.fxa_refresh_token) {
logger.error("no_fxa_refresh_token", { dbFxATokens });
session.error = "RefreshAccessTokenError";
return session;
}
try {
const responseTokens = await refreshOAuthTokens(
dbFxATokens.fxa_refresh_token,
);
const updatedUser = await updateFxATokens(
token.subscriber,
responseTokens.access_token,
responseTokens.refresh_token,
Date.now() + responseTokens.expires_in * 1000,
);
if (updatedUser) {
const sanitizedUpdatedUser = sanitizeSubscriberRow(updatedUser);
// Next-Auth implicitly converts `updatedUser` to a SerializedSubscriber,
// hence the type assertion:
token.subscriber =
sanitizedUpdatedUser as unknown as SerializedSubscriber;
}
} catch (error) {
logger.error("refresh_access_token", error);
// The error property can be used client-side to handle the refresh token error
session.error = "RefreshAccessTokenError";
}
}
}
return session;
},