Skip to content
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

How to use Refresh Token #480

Closed
Tracked by #634
Fenish opened this issue Jul 12, 2023 · 14 comments · Fixed by #641
Closed
Tracked by #634

How to use Refresh Token #480

Fenish opened this issue Jul 12, 2023 · 14 comments · Fixed by #641
Labels
documentation A change to the documentation p4 Important Issue provider-refresh An issue with the refresh provider

Comments

@Fenish
Copy link

Fenish commented Jul 12, 2023

Describe the feature

At the example code you provided refresh token but you didn't provide how to use it

following line: https://github.com/sidebase/nuxt-auth/blob/45d7e349ee0bb8791afdba69c7c35f39c9fe5a75/playground-local/server/api/auth/login.post.ts#L29C1-L29C1

is there any usage at wiki / docs about how to use refresh tokens

Additional information

Package.json

  "devDependencies": {
    "@nuxt/devtools": "latest",
    "@pinia-plugin-persistedstate/nuxt": "^1.1.1",
    "@sidebase/nuxt-auth": "^0.6.0-beta.3",
    "@types/node": "^18.16.19",
    "nuxt": "^3.6.2"
  }
@bekee
Copy link

bekee commented Jul 16, 2023

You can follow this doc https://sidebase.io/nuxt-auth/v0.6/recipes/directus

@luisfrocha
Copy link

How can that be converted to configuring in the nuxt.config.js file? I see that that example uses the CredentialsProvider, but I'm using a custom login page with the corresponding endpoint under /server/api/auth/login.post.ts. Does that mean I need to add a /server/api/auth/jwt.post.ts with some of that code to accomplish the renewal?

@cyanerd
Copy link

cyanerd commented Dec 7, 2023

@luisfrocha hello! have you find the solution for this? i have the same issue :(

@zoey-kaiser
Copy link
Member

Hi @cyanerd,

The refresh provider is currently in alpha. I am actually writing the docs today and will then officially release the new provider! I already released an alpha version of it last week, so the author could begin using and testing it, and I could create a new app to properly test it.

I can ping you here once I have finished up 🥳

@zoey-kaiser
Copy link
Member

You can already find a basic outline here:

https://sidebase.io/nuxt-auth/getting-started/quick-start#provider-refresh

@zoey-kaiser
Copy link
Member

See more information on how to use the refresh provider here: https://sidebase.io/nuxt-auth/getting-started/quick-start#provider-refresh

@Jumail
Copy link

Jumail commented Dec 11, 2023

You can already find a basic outline here:

https://sidebase.io/nuxt-auth/getting-started/quick-start#provider-refresh

This does not explain tokens are refreshed. I receive both refresh token and access token to my application but when the access token expires, It automatically get's deleted on my application without being refreshed. Am I missing something here?

@azuryel
Copy link

azuryel commented Dec 28, 2023

I'm not sure why this has been marked as closed, same thing on my application, as soon as my token expire i just got unlogged and there is no call to my refresh token route

(using custom node api with refreshToken route, and refresh provider)

@Fenish
Copy link
Author

Fenish commented Dec 29, 2023

I'm not sure why this has been marked as closed, same thing on my application, as soon as my token expire i just got unlogged and there is no call to my refresh token route

(using custom node api with refreshToken route, and refresh provider)

even documents says refresh token logic is exists but you cannot use it

@azuryel
Copy link

azuryel commented Dec 29, 2023

I'm not sure why this has been marked as closed, same thing on my application, as soon as my token expire i just got unlogged and there is no call to my refresh token route
(using custom node api with refreshToken route, and refresh provider)

even documents says refresh token logic is exists but you cannot use it

well in the end i have been able to make it work. i had to change the default token route to /accessToken instead of the /token and actually write "lax" ( or "strict")

without these 2 things the token wasn't actually stored in cookie. but with it both refresh and auth token are actually stored in cookie and refreshed. It now work as intended i guess ?

my nuxt.config.ts

auth: {
    baseURL: process.env.API_BASE_URL,
    provider: {
      type: "refresh",
      endpoints: {
        signIn: { path: "/user/login", method: "post" },
        signOut: false,
        signUp: { path: "/user/register", method: "post" },
        getSession: { path: "/user/me", method: "get" },
        refresh: { path: "/user/refreshToken", method: "post" },
      },
      token: {
        signInResponseTokenPointer: "/accessToken",
        maxAgeInSeconds: 300000,
        sameSiteAttribute: "lax",
      },
    },

@Fenish
Copy link
Author

Fenish commented Dec 29, 2023

I'm not sure why this has been marked as closed, same thing on my application, as soon as my token expire i just got unlogged and there is no call to my refresh token route
(using custom node api with refreshToken route, and refresh provider)

even documents says refresh token logic is exists but you cannot use it

well in the end i have been able to make it work. i had to change the default token route to /accessToken instead of the /token and actually write "lax" ( or "strict")

without these 2 things the token wasn't actually stored in cookie. but with it both refresh and auth token are actually stored in cookie and refreshed. It now work as intended i guess ?

my nuxt.config.ts

auth: {
    baseURL: process.env.API_BASE_URL,
    provider: {
      type: "refresh",
      endpoints: {
        signIn: { path: "/user/login", method: "post" },
        signOut: false,
        signUp: { path: "/user/register", method: "post" },
        getSession: { path: "/user/me", method: "get" },
        refresh: { path: "/user/refreshToken", method: "post" },
      },
      token: {
        signInResponseTokenPointer: "/accessToken",
        maxAgeInSeconds: 300000,
        sameSiteAttribute: "lax",
      },
    },

I stopped using nuxt auth after i open this issue. From then this is my auth logic

import { useTokenStore } from '~/store/tokenStore'
import { useUserStore } from '~/store/userStore'

export const useAuth = () => {
	const config = useRuntimeConfig().public
	const authStatus = useState<SessionStatus>('auth:status', () => 'loading')

	const status = computed({
		get() {
			return authStatus.value
		},
		set(val) {
			authStatus.value = val
		},
	})

	const accessToken = computed(() => {
		const store = useTokenStore()
		const token = store.getAccessToken()

		return token
	})

	const getSession = async () => {
		try {
			const response: any = await $fetch(
				config.API_URL + '/auth/session',
				{
					headers: {
						Authorization: 'Bearer ' + accessToken.value,
					},
					method: 'GET',
				},
			)

			status.value = 'authenticated'

			const user = await useCustomFetch('/user/' + response.data.id)
			const store = useUserStore()
			store.setUser(user)
			return user
		} catch (err: any) {
			status.value = 'unauthenticated'
			const code = err.response.status
			if (code === 401) {
				return refresh()
			}
			throw new Error(err.response._data.message)
		}
	}



	async function signIn(identifier: string, password: string) {
		try {
			const response: any = await $fetch(config.API_URL + '/auth/login', {
				body: {
					identifier,
					password,
				},
				method: 'POST',
				credentials: 'include',
			})
			status.value = 'authenticated'
			const store = useTokenStore()
			store.setAccessToken(response.data)
		} catch (err: any) {
			status.value = 'unauthenticated'
			throw new Error(err.response._data.message)
		}
	}

	async function refresh() {
		try {
			const response: any = await $fetch(
				config.API_URL + '/auth/refresh',
				{
					headers: {
						Authorization: 'Bearer ' + accessToken.value,
					},
					credentials: 'include',
					method: 'POST',
				},
			)
			status.value = 'authenticated'
			const store = useTokenStore()
			store.setAccessToken(response.data)
		} catch (err: any) {
			throw new Error(err.response._data.message)
		}
	}

	return {
		accessToken,
		getSession,
		signIn,
		refresh,
		status,
	}
}

@azuryel
Copy link

azuryel commented Dec 29, 2023

I'm not sure why this has been marked as closed, same thing on my application, as soon as my token expire i just got unlogged and there is no call to my refresh token route
(using custom node api with refreshToken route, and refresh provider)

even documents says refresh token logic is exists but you cannot use it

well in the end i have been able to make it work. i had to change the default token route to /accessToken instead of the /token and actually write "lax" ( or "strict")
without these 2 things the token wasn't actually stored in cookie. but with it both refresh and auth token are actually stored in cookie and refreshed. It now work as intended i guess ?
my nuxt.config.ts

auth: {
    baseURL: process.env.API_BASE_URL,
    provider: {
      type: "refresh",
      endpoints: {
        signIn: { path: "/user/login", method: "post" },
        signOut: false,
        signUp: { path: "/user/register", method: "post" },
        getSession: { path: "/user/me", method: "get" },
        refresh: { path: "/user/refreshToken", method: "post" },
      },
      token: {
        signInResponseTokenPointer: "/accessToken",
        maxAgeInSeconds: 300000,
        sameSiteAttribute: "lax",
      },
    },

I stopped using nuxt auth after i open this issue. From then this is my auth logic

import { useTokenStore } from '~/store/tokenStore'
import { useUserStore } from '~/store/userStore'

export const useAuth = () => {
	const config = useRuntimeConfig().public
	const authStatus = useState<SessionStatus>('auth:status', () => 'loading')

	const status = computed({
		get() {
			return authStatus.value
		},
		set(val) {
			authStatus.value = val
		},
	})

	const accessToken = computed(() => {
		const store = useTokenStore()
		const token = store.getAccessToken()

		return token
	})

	const getSession = async () => {
		try {
			const response: any = await $fetch(
				config.API_URL + '/auth/session',
				{
					headers: {
						Authorization: 'Bearer ' + accessToken.value,
					},
					method: 'GET',
				},
			)

			status.value = 'authenticated'

			const user = await useCustomFetch('/user/' + response.data.id)
			const store = useUserStore()
			store.setUser(user)
			return user
		} catch (err: any) {
			status.value = 'unauthenticated'
			const code = err.response.status
			if (code === 401) {
				return refresh()
			}
			throw new Error(err.response._data.message)
		}
	}



	async function signIn(identifier: string, password: string) {
		try {
			const response: any = await $fetch(config.API_URL + '/auth/login', {
				body: {
					identifier,
					password,
				},
				method: 'POST',
				credentials: 'include',
			})
			status.value = 'authenticated'
			const store = useTokenStore()
			store.setAccessToken(response.data)
		} catch (err: any) {
			status.value = 'unauthenticated'
			throw new Error(err.response._data.message)
		}
	}

	async function refresh() {
		try {
			const response: any = await $fetch(
				config.API_URL + '/auth/refresh',
				{
					headers: {
						Authorization: 'Bearer ' + accessToken.value,
					},
					credentials: 'include',
					method: 'POST',
				},
			)
			status.value = 'authenticated'
			const store = useTokenStore()
			store.setAccessToken(response.data)
		} catch (err: any) {
			throw new Error(err.response._data.message)
		}
	}

	return {
		accessToken,
		getSession,
		signIn,
		refresh,
		status,
	}
}

im curious to know how you plan to handle the 401 unauthorized? will you call your refresh function at every API call that return 401 ? that sound like a lot of repetitive code.
And before turning to nuxt-auth i had a fully working handmade auth store also but i couldnt make the refresh token system to have it automatically refresh on 401

@Fenish
Copy link
Author

Fenish commented Dec 29, 2023

I'm not sure why this has been marked as closed, same thing on my application, as soon as my token expire i just got unlogged and there is no call to my refresh token route
(using custom node api with refreshToken route, and refresh provider)

even documents says refresh token logic is exists but you cannot use it

well in the end i have been able to make it work. i had to change the default token route to /accessToken instead of the /token and actually write "lax" ( or "strict")
without these 2 things the token wasn't actually stored in cookie. but with it both refresh and auth token are actually stored in cookie and refreshed. It now work as intended i guess ?
my nuxt.config.ts

auth: {
    baseURL: process.env.API_BASE_URL,
    provider: {
      type: "refresh",
      endpoints: {
        signIn: { path: "/user/login", method: "post" },
        signOut: false,
        signUp: { path: "/user/register", method: "post" },
        getSession: { path: "/user/me", method: "get" },
        refresh: { path: "/user/refreshToken", method: "post" },
      },
      token: {
        signInResponseTokenPointer: "/accessToken",
        maxAgeInSeconds: 300000,
        sameSiteAttribute: "lax",
      },
    },

I stopped using nuxt auth after i open this issue. From then this is my auth logic

import { useTokenStore } from '~/store/tokenStore'
import { useUserStore } from '~/store/userStore'

export const useAuth = () => {
	const config = useRuntimeConfig().public
	const authStatus = useState<SessionStatus>('auth:status', () => 'loading')

	const status = computed({
		get() {
			return authStatus.value
		},
		set(val) {
			authStatus.value = val
		},
	})

	const accessToken = computed(() => {
		const store = useTokenStore()
		const token = store.getAccessToken()

		return token
	})

	const getSession = async () => {
		try {
			const response: any = await $fetch(
				config.API_URL + '/auth/session',
				{
					headers: {
						Authorization: 'Bearer ' + accessToken.value,
					},
					method: 'GET',
				},
			)

			status.value = 'authenticated'

			const user = await useCustomFetch('/user/' + response.data.id)
			const store = useUserStore()
			store.setUser(user)
			return user
		} catch (err: any) {
			status.value = 'unauthenticated'
			const code = err.response.status
			if (code === 401) {
				return refresh()
			}
			throw new Error(err.response._data.message)
		}
	}



	async function signIn(identifier: string, password: string) {
		try {
			const response: any = await $fetch(config.API_URL + '/auth/login', {
				body: {
					identifier,
					password,
				},
				method: 'POST',
				credentials: 'include',
			})
			status.value = 'authenticated'
			const store = useTokenStore()
			store.setAccessToken(response.data)
		} catch (err: any) {
			status.value = 'unauthenticated'
			throw new Error(err.response._data.message)
		}
	}

	async function refresh() {
		try {
			const response: any = await $fetch(
				config.API_URL + '/auth/refresh',
				{
					headers: {
						Authorization: 'Bearer ' + accessToken.value,
					},
					credentials: 'include',
					method: 'POST',
				},
			)
			status.value = 'authenticated'
			const store = useTokenStore()
			store.setAccessToken(response.data)
		} catch (err: any) {
			throw new Error(err.response._data.message)
		}
	}

	return {
		accessToken,
		getSession,
		signIn,
		refresh,
		status,
	}
}

im curious to know how you plan to handle the 401 unauthorized? will you call your refresh function at every API call that return 401 ? that sound like a lot of repetitive code. And before turning to nuxt-auth i had a fully working handmade auth store also but i couldnt make the refresh token system to have it automatically refresh on 401

Yes i designed my backend for this composable. I have authorization check middleware. Everytime that i get data from protected route, if it returns 401 im refreshing token. If its not protected route, i don't have to refresh my token because it is unnecessary. After refresh if its still wrong token, im basically make user logout. I didn't tried to make this snippet perfect but this version works very well

@mwc2016
Copy link

mwc2016 commented Jan 9, 2024

I am using github oauth to login and storing custom token generated by my own server. Might I know that the refresh provider will work during $fetch calling API?

@zoey-kaiser zoey-kaiser added p4 Important Issue documentation A change to the documentation provider-refresh An issue with the refresh provider and removed enhancement labels Feb 23, 2024
@zoey-kaiser zoey-kaiser linked a pull request Feb 24, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation A change to the documentation p4 Important Issue provider-refresh An issue with the refresh provider
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants