N
Nuxt3w ago
marvin

Nuxt Auth

Hi, I am currently struggling with implementing OAuth2 for my application. I have added @sidebase/nuxt-auth with a NuxtAuthHandler with Authentik as following:
export default NuxtAuthHandler({
secret: useRuntimeConfig().auth.secret,
providers: [
AuthentikProvider.default({
clientId: useRuntimeConfig().auth.clientId,
clientSecret: useRuntimeConfig().auth.clientSecret,
issuer: useRuntimeConfig().auth.issuer
})
],
callbacks: {
jwt (data) {
const { token, account } = data
if (account) {
token.accessToken = account.access_token
}
return token
},
session ({ session, token }) {
session.accessToken = token.accessToken
return session
}
}
})
export default NuxtAuthHandler({
secret: useRuntimeConfig().auth.secret,
providers: [
AuthentikProvider.default({
clientId: useRuntimeConfig().auth.clientId,
clientSecret: useRuntimeConfig().auth.clientSecret,
issuer: useRuntimeConfig().auth.issuer
})
],
callbacks: {
jwt (data) {
const { token, account } = data
if (account) {
token.accessToken = account.access_token
}
return token
},
session ({ session, token }) {
session.accessToken = token.accessToken
return session
}
}
})
The defined callbacks functions allow me to use the accessToken from Authentik in the frontend and therefore as a header in useFetch to my external (Spring Boot) API. The problem I have is the accessToken being valid for only 5 minutes by default. However @sidebase/nuxt-auth doesn't recognise this. The state keeps staying on "authenticated", and the accessToken doesn't get refreshed in any way. The user has to sign out completely and then sign in again to get a new accessToken for the next 5 minutes. Of course I could increase the accessToken lifetime, but that wouldn't fix the bad user experience. How can I fix this problem, or what am I doing wrong here?
2 Replies
kapa.ai
kapa.ai3w ago
Hi @marvin. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the information provided in the knowledge sources, I can offer some insights and suggestions regarding your Nuxt Auth implementation with OAuth2 and token refreshing. However, it's important to note that the specific details about @sidebase/nuxt-auth and Authentik provider are not directly covered in the provided knowledge sources. The issue you're experiencing with the access token expiring after 5 minutes and not being automatically refreshed is a common challenge in OAuth2 implementations. Here are some suggestions to address this: 1. Implement token refreshing: The key to solving this issue is to implement a token refresh mechanism. While the exact implementation for @sidebase/nuxt-auth is not provided in the knowledge sources, we can draw inspiration from similar implementations in Nuxt. 2. Use a custom fetch composable: You can create a custom fetch composable that handles token refreshing. This approach is mentioned in the Nuxt documentation on custom useFetch composables (https://nuxt.com/docs/examples/advanced/use-custom-fetch-composable). Here's an example of how you might structure this:
export function useCustomFetch<T>(url: string, options: UseFetchOptions<T> = {}) {
const config = useRuntimeConfig()
const { getToken, refreshToken } = useAuthStore() // You'll need to implement this

const defaults: UseFetchOptions<T> = {
baseURL: config.public.apiBaseUrl,
key: url,

onRequest({ options }) {
options.headers = { Authorization: `Bearer ${getToken()}` }
},

async onResponseError({ response }) {
if (response.status === 401) {
await refreshToken() // Implement this method to refresh the token
// Retry the original request
}
}
}
const params = defu(options, defaults)
return useFetch(url, params)
}

export function useCustomFetch<T>(url: string, options: UseFetchOptions<T> = {}) {
const config = useRuntimeConfig()
const { getToken, refreshToken } = useAuthStore() // You'll need to implement this

const defaults: UseFetchOptions<T> = {
baseURL: config.public.apiBaseUrl,
key: url,

onRequest({ options }) {
options.headers = { Authorization: `Bearer ${getToken()}` }
},

async onResponseError({ response }) {
if (response.status === 401) {
await refreshToken() // Implement this method to refresh the token
// Retry the original request
}
}
}
const params = defu(options, defaults)
return useFetch(url, params)
}

3. Implement token refreshing logic: You'll need to implement the logic to refresh the token. This typically involves making a request to your authentication server (Authentik in your case) with the refresh token to obtain a new access token. 4. Update the session and JWT callbacks: Modify your jwt and session callbacks to handle the refreshed token:
callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token
token.refreshToken = account.refresh_token
token.expiresAt = account.expires_at * 1000
}

if (Date.now() < token.expiresAt) {
return token
}

// Token has expired, try to refresh it
return await refreshAccessToken(token)
},
session({ session, token }) {
session.accessToken = token.accessToken
return session
}
}

callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token
token.refreshToken = account.refresh_token
token.expiresAt = account.expires_at * 1000
}

if (Date.now() < token.expiresAt) {
return token
}

// Token has expired, try to refresh it
return await refreshAccessToken(token)
},
session({ session, token }) {
session.accessToken = token.accessToken
return session
}
}

You'll need to implement the refreshAccessToken function to handle the token refresh process. 5. Consider using useCookie: For better server-side and client-side consistency, consider using useCookie to store tokens instead of localStorage. This is mentioned in a Stack Overflow answer (https://stackoverflow.com/questions/78634376) about accessing tokens on the server-side:
const accessToken = useCookie("accessToken");
accessToken.value = "your_new_token";

const accessToken = useCookie("accessToken");
accessToken.value = "your_new_token";

6. Handle token refreshing errors: Make sure to handle cases where token refreshing fails, possibly logging the user out if the refresh token is invalid or expired. Remember that implementing secure authentication and token management can be complex. Always ensure you're following best practices for security, especially when handling sensitive tokens. Given that the specific details about @sidebase/nuxt-auth and Authentik are not covered in the provided knowledge sources, you might need to consult their respective documentation for more precise implementation details. The suggestions provided here are based on general OAuth2 and Nuxt authentication practices. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@318106208995377152> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Want results from more Discord servers?
Add your server