-
Notifications
You must be signed in to change notification settings - Fork 118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setUserSession does not update session immediately after login in 'fetch' hook #357
Comments
I'm facing the same issue. In my case I'm using the import type { H3Event } from 'h3'
import { jwtDecode } from 'jwt-decode'
import type { UserSession } from '#auth-utils'
function shouldRefreshToken(accessToken: string): boolean {
const decodedToken = jwtDecode(accessToken)
return decodedToken.iat + 10000 < Date.now() // for debugging purpose
// const ONE_HOUR = 60 * 60 * 1000
// return Date.now() + ONE_HOUR >= decodedToken.exp * 1000
}
async function refreshTokens(refreshToken: string) {
const config = useRuntimeConfig()
return $fetch(`https://${config.oauth.auth0.domain}/oauth/token`, {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: config.oauth.auth0.clientId,
client_secret: config.oauth.auth0.clientSecret,
refresh_token: refreshToken,
}).toString(),
})
}
export default defineNitroPlugin(() => {
sessionHooks.hook('fetch', async (session: UserSession, event: H3Event) => {
if (!session?.tokens) {
return
}
const { tokens } = session
if (shouldRefreshToken(tokens.access_token)) {
try {
console.log('old refresh token', tokens.refresh_token) // Correctly prints the old refresh token the first time this hook is called, but stays the same after that
const newTokens = await refreshTokens(tokens.refresh_token)
await setUserSession(event, {
tokens: newTokens,
})
console.log('new refresh token', newTokens.refresh_token) // Correctly prints the new refresh token
session.tokens = newTokens
} catch (error) {
console.error('Failed to refresh tokens:', error)
await clearUserSession(event)
}
}
})
}) Console output:
|
Thanks @Crease29, your code gave me an idea to try and I found a 'solution' that worked for my case. instead of await setUserSession(event, {
user: { name: 'test' },
}) I use session.user = { name: 'test' } Still think its a bug tho that setUserSession is not working anymore. Edit: @atinux, if I'm mistaken in thinking that I should use setUserSession in the fetch hook and should instead set data directly on the session variable, feel free to close this ticket. |
Found this #314 (comment), which might be helpful. Edit: I've implemented it as a custom refresh endpoint and it seems to work fine :)
import { UserSession } from '#auth-utils'
import { jwtDecode } from 'jwt-decode'
function isTokenExpired(token: string): boolean {
const decoded = jwtDecode(token)
const ONE_HOUR = 60 * 60 * 1000
const expiresAt = (decoded?.exp ?? 0) * 1000
return Date.now() + ONE_HOUR >= expiresAt
}
async function refreshTokens(refreshToken: string) {
const config = useRuntimeConfig()
return $fetch(`https://${config.oauth.auth0.domain}/oauth/token`, {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: config.oauth.auth0.clientId,
client_secret: config.oauth.auth0.clientSecret,
refresh_token: refreshToken,
}).toString(),
})
}
export default defineEventHandler(async (event) => {
const session: UserSession = await getUserSession(event)
if (!session?.tokens) {
return
}
const { tokens } = session
const isAccessTokenExpired = isTokenExpired(tokens.access_token)
if (!isAccessTokenExpired) {
// If the access token is still valid, we don't need to refresh it
return
}
try {
const newTokens = await refreshTokens(tokens.refresh_token)
session.tokens = newTokens
await setUserSession(event, {
tokens: {
access_token: newTokens.access_token,
refresh_token: newTokens.refresh_token,
},
})
} catch (error) {
console.error('Failed to refresh tokens:', error)
await clearUserSession(event)
}
})
onMounted(() => {
$fetch('/api/auth/refresh')
}) |
Last working version: v0.5.11
Issue description:
After updating past v0.5.11, setUserSession is no longer updating the session immediately after login when adding user data in the fetch hook. The session does update, but only after the fact and only visible after page reload.
Expected behavior:
as in v0.5.11 the session immediately reflected the updated user data after calling setUserSession in the hook.
Actual behavior:
After login, the session, in the frontend/app does not immediately contain the updated user data.
Reloading the page makes the session data appear.
Code:
refreshing on
http://localhost:3000/api/_auth/session
after shows user.name = 'test'.Another way to quickly test this:
Open
http://localhost:3000/api/_auth/session
usereplaceUserSession
orsetUserSession
in the hook, change some values in code and you than need to refresh 2 times to see the changes in sessionThe text was updated successfully, but these errors were encountered: