How to created a Refresh token

Am trying to have token rotation system where users can use a refresh token so they can request for a new access token…

How can I create a refresh token in Strapi v4?

2 Likes

I found only this repo https://github.com/olyphotographer/strapi-refresh-tokens
But 0 stars is adjusted…

I created a refresh token use the under code. and the resource: strapi-study-cases/strapi-server.js at main · GavinXue/strapi-study-cases · GitHub

// ref doc: https://docs.strapi.io/developer-docs/latest/development/plugins-extension.html#extending-a-plugin-s-interface
module.exports = (plugin) => {
	plugin.controllers.auth.refreshToken = async (ctx) => {
		// refresh userself token
		const newJwt = strapi.plugins['users-permissions'].services.jwt.issue({
			id: ctx.state.user.id
		})
		return { jwt: newJwt }

		// comment out next lines, and refresh the request body's token like {token: 'xxx'}
		// const { token } = ctx.request.body
		// const payload = strapi.plugins['users-permissions'].services.jwt.verify(token)
		// const newJwt = strapi.plugins['users-permissions'].services.jwt.issue({
		// 	id: payload.id
		// })
		// return {jwt: newJwt}
	}

	plugin.routes['content-api'].routes.push({
		method: 'POST',
		path: '/auth/refreshToken',
		handler: 'auth.refreshToken',
		config: {
			prefix: ''
		}
	});

	return plugin
}
2 Likes

@GavinXue Thank you! I tried implementing your code above but I keep getting a Forbidden error. Any thoughts on why that could be?

maybe you did not allow the request auth in api management. you can read the docs: Configuring end-user roles | Strapi Documentation ; you will find a there is a new api.

if you still have problem, you can watch a old video of strapi v3, maybe it can help:

1 Like

@kaarbez Forbidden is the auth problem, It is nothing to do with the code I think. hope the last reply can help. and also if you need graphql refreshToken API, you can read here: GitHub - GavinXue/strapi-study-cases: strapi use cases when study, maybe it can help someone else.

1 Like

Amazing! Thank you, got it working!

@GavinXue assume you would be calling this API just before it expires? Or would you have this with public access and just refresh it once you get a forbidden error from an API?

@kaarbez The logics of when refresh the token has implemented in frontend。I will refresh code when token near expires time. I think refreshing token can not solve the forbidden problem, because the new token may be forbidden too.
note: the posted code is just a case when I study to use strapi (im a novice), we can extend this code format to build any customize api you want.

@GavinXue Thanks for the clarification.

For now, I actually incorporated verifying the token, and then automatically refreshing the token if it is expired. Here is what I have.

plugin.controllers.auth.refreshToken = async (ctx) => {
		const payload = await strapi.plugins['users-permissions'].services.jwt.verify(ctx.request.body.token)
		.catch(error => { 
			console.log(error.message)
			return {jwt: strapi.plugins['users-permissions'].services.jwt.issue({
				id: ctx.request.body.id
			})}
		});

		console.log(payload)
		return {jwt: payload.jwt}
	}

I want to update it in the future so that my front end is verifying the expiry time and only calling when close to expiry. I also found this awesome project that incorporates Apollo client : React-GraphQL-JWT-Authentication-Example

@kaarbez Thanks for your recommended repo(it’s useful for me to study). My frontend will not refresh token when expired(it will redirect to login). due to spa I will just refresh token when first request of a day(and token should be not expired.)
Hope you solve problem.

1 Like

I’m a little confused with this JWT auth system. I’ve tried the code above, and it’s working. That is, I’m getting a new jwt after reaching BASE_URL/auth/refreshToken with a header set to { Authorzation: Bearer myOldToken }. However, if just one one of those myOldToken falls into the wrong hands, then he would get indefinite access by accessing the refresh endpoint. How do I prevent this indefinite access?

1 Like

Hi @Teriz I’m going exactly through the same issue

you need to revoke the old token. There is no native solution for revoking tokens in strapi. See Is there away to revoke user's jwt token?

plugin.controllers.auth['refreshToken'] = async (ctx) => {
    try {
        const { token } = ctx.request.body
        const payload = await strapi.plugins['users-permissions'].services.jwt.verify(token) 
        const refrechToken = await strapi.plugins['users-permissions'].services.jwt.issue({
            id: payload.id
        })
        return refrechToken
    } catch (error) {
        return ctx.badRequest(error.toString());
    }
}

plugin.routes['content-api'].routes.push({
    method: 'POST',
    path: '/refrechToken',
    handler: 'auth.refreshToken',
    config: {
        prefix: ''
    }
});

return plugin;

So this isn’t really what I’m doing, but your commented out JWT bit was exactly what I needed! Thank you for posting my friend :slight_smile: