VOOZH about

URL: https://strapi.io/blog/strapi-authentication-in-nuxt-js

⇱ Strapi Authentication with Nuxt.js


Higher Quality, Stronger Performance, Increased Stability, Better Developer Experience, discover everything we've shipped recently!

  • Last updated: December 8, 2022 (Strapi v4 era)
  • 14 min read

Strapi Authentication in Nuxt.js

May 4, 2022

πŸ‘ tweet selection

Authentication is the process through which a website or app verifies the identity of its users. As the gatekeeper to an app, authentication needs to be secure and reliable. After all, it deals with user information, potentially the most critical data in an app.

Implementing a secure authentication mechanism from scratch could be difficult and can quickly become cumbersome. Where do you save the user data? Should you roll out a database and model the user content type? What about registration, login, and password reset? It doesn't end there. How do you deal with passwords securely?

That's a lot to think about when you just want to dive into the core functionality of the app you're developing. You could build your own authentication mechanism, but do you really need or want to? It may be better to rely on something that's already been built and thoroughly tested.

An Introduction to Strapi

Strapi, the leading open-source Headless CMS, speeds up the process and gives you the freedom to use your favorite frameworks. Strapi is the leading open-source headless CMS made by developers for deverlopers.. Strapi provides authentication right out of the box; it comes with built-in role-based access control and customizable REST API to perform the main authentication operations.

Goals

This is a step-by-step guide on how to implement Strapi-based authentication in a Nuxt.js app. On the frontend, we'll be using Nuxt.js and relying on Nuxt's Auth Module, which is the official zero-boilerplate authentication support for Nuxt.js.

In this article, we'll build two projects:

  • A Strapi application to store and manage users, and
  • A Nuxt application that will use Strapi's API for authentication purposes.

Here's a preview of what we want to achieve:

Prerequisites

To follow this tutorial, make sure you have:

  • Node.js, we recommend you have the v14 version installed.
  • Yarn, a modern package manager.
  • A text editor, we recommend VS Code with the Vetur extension, a Vue tooling for VS Code, powered by vls. It comes with multiple features like syntax highlighting, formatting, IntelliSense, debugging, and more.
  • A terminal, we recommend using VS Code's integrated terminal.

Let's get started!

Step 1: Set up Strapi

Begin by creating a Strapi project. Copy and paste the following command line into your terminal to create your first Strapi project.

 yarn create strapi-app backend --quickstart

Using the --quickstart flag at the end of the command to directly create the project in quickstart mode, which uses the default database (SQLite).

Once the installation is complete, your browser automatically opens a new tab.

Complete the form to create your new administrator account.

Now that you've created your Strapi application, you are ready to start a new Nuxt.js project.

Step 2: Set up Nuxt.js

In this step, we will use create-nuxt-app to create a new Nuxt project.

Open a terminal or, from Visual Studio Code, open an integrated terminal and use the following command to create a new starter project:

 yarn create nuxt-app frontend

After running the command above, you’ll have to answer some questions. Once all questions are answered, it will install all the dependencies.

 ? Project name: frontend
 ? Programming language: JavaScript
 ? Package manager: Yarn
 ? UI framework: Windi CSS
 ? Nuxt.js modules: None
 ? Linting tools: ESLint, Prettier
 ? Testing framework: None
 ? Rendering mode: Universal (SSR / SSG)
 ? Deployment target: Server (Node.js hosting)
 ? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
 ? Continuous integration: None
 ? Version control system: Git

Once the project is created, follow the instructions to install dependencies and start the dev server:

 cd frontend
 yarn
 yarn dev

Now that the dev server is running, open http://localhost:3000/ in your browser.

Good job, you successfully set up both Nuxt and Strapi projects! πŸŽ‰

Step 3: Set up Auth Module

**nuxt auth** authenticates users using a configurable authentication scheme or by using one of the directly supported providers. It provides an API for triggering authentication and accessing the resulting user information.

Let's install the packages we need. Open a new terminal:

 # Ctrl + C to close process js
 cd frontend
 yarn add --exact @nuxtjs/auth-next
 yarn add @nuxtjs/axios

Then, add the following to the modules section of nuxt.config.js:

 // frontend/nuxt.config.js
 export default {
 // Modules: https://go.nuxtjs.dev/config-modules
 modules: [
 '@nuxtjs/axios',
 '@nuxtjs/auth-next'
 ],
 }

The auth-module relies on Vuex, a state management pattern + library for Vue.js applications. You can activate the store by creating a new ./store/index.js file

 // frontend/store/index.js
 export const getters = {
 isAuthenticated(state) {
 return state.auth.loggedIn
 },
 loggedInUser(state) {
 return state.auth.user
 },
 }

You can now start configuring your local scheme.

Step 4: Set up Local Scheme

Schemes define authentication logic, see IANA list of authentication schemes. local is the default credentials based scheme for flows like JWT (JSON Web Token), which is the authentication process provided by Strapi roles & permissions plugin.

In this guide we will see how to validate a JWT with Strapi. Let’s map the Strapi authentication endpoints to the local strategy. Add a new axios and auth sections to your nuxt.config.js:

 // frontend/nuxt.config.js
 export default {
 axios: {
 baseURL: process.env.STRAPI_URL || 'http://localhost:1337/api'
 },

 auth: {
 // Options
 strategies: {
 local: {
 token: {
 property: 'jwt',
 },
 user: {
 property: false,
 },
 endpoints: {
 login: {
 url: 'auth/local',
 method: 'post',
 },
 user: {
 url: 'users/me',
 method: 'get',
 },
 logout: false,
 },
 },
 },
 }
 }

Here, you set the base URL that axios will use when making requests. In our case, we are referencing the Strapi API endpoint we set up earlier.

Then, you define the authentication endpoints for the local strategy corresponding to those on your API:

  • login: authenticates the user. On successful authentication, the JWT token will be available in the jwt property of the response object.
  • user: retrieves the authenticated user's info. If the user is authenticated, the JWT token will be added to the request, allowing Strapi to identify the user.
  • We've also disabled the logout endpoint, since logging out a user is only done locally and doesn't require any request to Strapi's API. The token is simply removed from the local storage when the user logs out.

Step 5: Create a Navbar component

Create a new ./components/Navbar.vue file, and copy/paste the following code in it:

 // frontend/components/Navbar.vue
 <template>
 <div class="bg-gray-800 py-4 px-4">
 <NuxtLink class="text-white p-2 hover:bg-gray-700" to="/">Home</NuxtLink>
 <NuxtLink
 v-if="!isAuthenticated"
 class="text-white p-2 hover:bg-gray-700"
 to="/user/login"
 >Sign In</NuxtLink
 >
 <NuxtLink
 v-if="!isAuthenticated"
 class="text-white p-2 hover:bg-gray-700"
 to="/user/register"
 >Sign Up</NuxtLink
 >
 <NuxtLink
 v-if="isAuthenticated"
 class="text-white p-2 hover:bg-gray-700"
 to="/user/me"
 >Your profile</NuxtLink
 >
 <a
 v-if="isAuthenticated"
 class="text-white p-2 hover:bg-gray-700"
 href="/logout"
 @click.prevent="userLogout"
 >Logout</a
 >
 </div>
 </template>
 <script>
 import { mapGetters } from 'vuex'
 export default {
 computed: {
 ...mapGetters(['isAuthenticated']),
 },
 methods: {
 async userLogout() {
 await this.$auth.logout()
 },
 },
 }
 </script>

In the code above, we have created a navbar component using Tailwind CSS. Apart from that, we've defined the computed property isAuthenticated and userLogout method used in the component's template.

Add your navbar component to all your pages by extending the main layout. Add a new layouts/default.vue file, and copy/paste the following code in it:

 // frontend/layouts/default.vue
 <template>
 <div>
 <Navbar />
 <nuxt />
 </div>
 </template>

Great! After completing the navbar:

  • Run yarn dev to start the development server.
  • Visit http://localhost:3000 to view your application.

Step 6: Create a Login Page

Create a new ./pages/user/Login.vue file, and copy/paste the following code in it:

 // frontend/pages/user/Login.vue
 <template>
 <div class="max-w-md w-full mx-auto mt-8">
 <h1 class="text-3xl font-extrabold mb-4">Sign in</h1>
 <form @submit.prevent="userLogin">
 <div
 v-if="err"
 class="
 p-4
 mb-4
 text-sm text-red-700
 bg-red-100
 rounded-lg
 dark:bg-red-200 dark:text-red-800
 "
 role="alert"
 >
 {{ err }}
 </div>
 <div class="mb-6">
 <label
 for="email"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your email</label
 >
 <input
 v-model="email"
 type="email"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 placeholder="name@strapi.io"
 required
 />
 </div>
 <div class="mb-6">
 <label
 for="password"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your password</label
 >
 <input
 v-model="password"
 type="password"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 required
 />
 <p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
 <NuxtLink
 class="font-medium text-blue-600 hover:underline dark:text-blue-500"
 to="/user/forgot"
 >Reset password</NuxtLink
 >?
 </p>
 </div>
 <button
 type="submit"
 class="
 text-white
 bg-blue-700
 hover:bg-blue-800
 focus:ring-4 focus:outline-none focus:ring-blue-300
 font-medium
 rounded-lg
 text-sm
 px-5
 py-2.5
 text-center
 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800
 "
 >
 Sign in
 </button>
 </form>
 </div>
 </template>
 <script>
 export default {
 auth: 'guest',
 data() {
 return {
 err: null,
 email: '',
 password: '',
 }
 },
 methods: {
 async userLogin() {
 try {
 await this.$auth.loginWith('local', {
 data: { identifier: this.email, password: this.password },
 })
 } catch (e) {
 if (e.response) this.err = e.response.data.error.message
 }
 },
 },
 }
 </script>

In the code above, we've defined three properties err, email and password used in the component's template and userLogin method which log in the user after sending the data to the Strapi application. An error notification will be displayed if login attempt is not successful, If not the user will be redirected to the homepage.

The auth: 'guest``' middleware help redirected the user to the homepage, if already logged in.

Step 7: Create a Registration Page

Create a new ./pages/user/Register.vue file, and copy/paste the following code in it:

 // frontend/pages/user/Register.vue
 <template>
 <div class="max-w-md w-full mx-auto mt-8">
 <h1 class="text-3xl font-extrabold mb-4">Sign up</h1>
 <form @submit.prevent="userRegister">
 <div
 v-if="err"
 class="
 p-4
 mb-4
 text-sm text-red-700
 bg-red-100
 rounded-lg
 dark:bg-red-200 dark:text-red-800
 "
 role="alert"
 >
 {{ err }}
 </div>
 <div
 v-if="success"
 class="
 p-4
 mb-4
 text-sm text-green-700
 bg-green-100
 rounded-lg
 dark:bg-green-200 dark:text-green-800
 "
 role="alert"
 >
 Your account has been created successfully you can now
 <NuxtLink class="font-medium" to="/user/login">Login</NuxtLink>
 </div>
 <div class="mb-6">
 <label
 for="username"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your username</label
 >
 <input
 v-model="username"
 type="text"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 placeholder="name"
 required
 />
 </div>
 <div class="mb-6">
 <label
 for="email"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your email</label
 >
 <input
 v-model="email"
 type="email"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 placeholder="name@strapi.io"
 required
 />
 </div>
 <div class="mb-6">
 <label
 for="password"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your password</label
 >
 <input
 v-model="password"
 type="password"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 required
 />
 </div>
 <button
 type="submit"
 class="
 text-white
 bg-blue-700
 hover:bg-blue-800
 focus:ring-4 focus:outline-none focus:ring-blue-300
 font-medium
 rounded-lg
 text-sm
 px-5
 py-2.5
 text-center
 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800
 "
 >
 Sign up
 </button>
 </form>
 </div>
 </template>
 <script>
 export default {
 auth: 'guest',
 data() {
 return {
 success: false,
 err: null,
 username: '',
 email: '',
 password: '',
 }
 },
 methods: {
 async userRegister() {
 try {
 this.$axios.setToken(false)
 await this.$axios.post('auth/local/register', {
 username: this.username,
 email: this.email,
 password: this.password,
 })
 this.success = true
 } catch (e) {
 if (e.response) this.err = e.response.data.error.message
 }
 },
 },
 }
 </script>

In the code above, we've defined two more properties success and username used to display a success message after a successful registration.

Time for the user profile page.

Step 9: Create a Profile Page

Create a new ./pages/user/Me.vue file, and copy/paste the following code in it:

 // frontend/pages/user/Me.vue
 <template>
 <div class="max-w-md w-full mx-auto mt-8">
 <h1 class="text-3xl font-extrabold mb-4">Your profile</h1>
 <form @submit.prevent="userLogin">
 <div class="mb-6">
 <label
 for="email"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your email</label
 >
 <input
 type="email"
 class="
 mb-6
 bg-gray-100
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 cursor-not-allowed
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-500
 dark:text-gray-500
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 "
 :value="loggedInUser.email"
 disabled
 />
 </div>
 <div class="mb-6">
 <label
 for="username"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your username</label
 >
 <input
 type="text"
 class="
 mb-6
 bg-gray-100
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 cursor-not-allowed
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-500
 dark:text-gray-500
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 "
 :value="loggedInUser.username"
 disabled
 />
 </div>
 </form>
 </div>
 </template>
 <script>
 import { mapGetters } from 'vuex'
 export default {
 middleware: 'auth',
 computed: {
 ...mapGetters(['loggedInUser']),
 },
 }
 </script>

The auth middleware guarantees that only logged in users can access this page.

Let's now implement a password reset mechanism.

Step 10: Set-up Password Reset

This will be achieved with the following workflow:

  1. In the forgot password page, a user submits an email.
  2. If the email is in Strapi's user database, it receives a unique reset password link.
  3. When the user click on the link, it open a reset password page.
  4. The new specified password is sent to Strapi, along with the reset code.
  5. The password is updated and the user can now use it to log in.

Before implementing the password reset feature. We need to enable the Public Role permissions for the auth/reset-password and auth/forgot-password endpoints.

To do so, open your Strapi application at http://localhost:1337/admin, from the left sidebar of the admin dashboard, click Settings, Roles, Edit Public, open Users-permissions, check both forgotPassword and resetPassword, then click Save.

Step 11: Create a New Password page

Create a new ./pages/user/Forgot.vue file, and copy/paste the following code in it:

 // frontend/pages/user/Forgot.vue
 <template>
 <div class="max-w-md w-full mx-auto mt-8">
 <h1 class="text-3xl font-extrabold mb-4">New password</h1>
 <form @submit.prevent="userPassword">
 <div
 v-if="err"
 class="
 p-4
 mb-4
 text-sm text-red-700
 bg-red-100
 rounded-lg
 dark:bg-red-200 dark:text-red-800
 "
 role="alert"
 >
 {{ err }}
 </div>
 <div class="mb-6">
 <label
 for="email"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Your email</label
 >
 <input
 v-model="email"
 type="email"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 placeholder="name@strapi.io"
 required
 />
 </div>
 <button
 type="submit"
 class="
 text-white
 bg-blue-700
 hover:bg-blue-800
 focus:ring-4 focus:outline-none focus:ring-blue-300
 font-medium
 rounded-lg
 text-sm
 px-5
 py-2.5
 text-center
 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800
 "
 >
 New password
 </button>
 </form>
 </div>
 </template>
 <script>
 export default {
 auth: 'guest',
 data() {
 return {
 err: null,
 email: '',
 }
 },
 methods: {
 async userPassword() {
 try {
 await this.$axios.post('auth/forgot-password', {
 email: this.email,
 })
 } catch (e) {
 if (e.response) this.err = e.response.data.error.message
 }
 },
 },
 }
 </script>

In the code above, we've defined a new userPassword method that sends a request to Strapi's auth/forgot-password endpoint. If the email address exists in Strapi's user database, an email is sent with a link to a reset password page in the frontend app.

This link contains an empty URL with code param which is required to reset user password. To specify a URL, there’s some simple configuration you need to do inside the admin panel. From the left sidebar of the admin dashboard, click Settings, Advanced settings, paste http://localhost:3000/user/reset in the β€œReset password page" field, then click Save.

Let's now create the reset page that will allow the user to define a new password.

Step 12: Complete the New Password page

Create a new file ./pages/user/Reset.vue and paste the following code into it:

 // frontend/pages/user/Rest.vue
 <template>
 <div class="max-w-md w-full mx-auto mt-8">
 <h1 class="text-3xl font-extrabold mb-4">New password</h1>
 <form @submit.prevent="userPassword">
 <div
 v-if="err"
 class="
 p-4
 mb-4
 text-sm text-red-700
 bg-red-100
 rounded-lg
 dark:bg-red-200 dark:text-red-800
 "
 role="alert"
 >
 {{ err }}
 </div>
 <div
 v-if="success"
 class="
 p-4
 mb-4
 text-sm text-green-700
 bg-green-100
 rounded-lg
 dark:bg-green-200 dark:text-green-800
 "
 role="alert"
 >
 Your password has been updated successfully you can now
 <NuxtLink class="font-medium" to="/user/login">Login</NuxtLink>
 </div>
 <div class="mb-6">
 <label
 for="password"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >New password</label
 >
 <input
 v-model="password"
 type="password"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 required
 />
 </div>
 <div class="mb-6">
 <label
 for="password-confirmation"
 class="
 block
 mb-2
 text-sm
 font-medium
 text-gray-900
 dark:text-gray-300
 "
 >Confirm new password</label
 >
 <input
 v-model="passwordConfirmation"
 type="password"
 class="
 shadow-sm
 bg-gray-50
 border border-gray-300
 text-gray-900 text-sm
 rounded-lg
 focus:ring-blue-500 focus:border-blue-500
 block
 w-full
 p-2.5
 dark:bg-gray-700
 dark:border-gray-600
 dark:placeholder-gray-400
 dark:text-white
 dark:focus:ring-blue-500
 dark:focus:border-blue-500
 dark:shadow-sm-light
 "
 required
 />
 </div>
 <button
 type="submit"
 class="
 text-white
 bg-blue-700
 hover:bg-blue-800
 focus:ring-4 focus:outline-none focus:ring-blue-300
 font-medium
 rounded-lg
 text-sm
 px-5
 py-2.5
 text-center
 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800
 "
 >
 New password
 </button>
 </form>
 </div>
 </template>
 <script>
 export default {
 auth: 'guest',
 data() {
 return {
 success: false,
 err: null,
 password: '',
 passwordConfirmation: '',
 }
 },
 methods: {
 async userPassword() {
 try {
 await this.$axios.post('auth/reset-password', {
 code: this.$route.query.code,
 password: this.password,
 passwordConfirmation: this.passwordConfirmation,
 })
 this.success = true
 } catch (e) {
 if (e.response) this.err = e.response.data.error.message
 }
 },
 },
 }
 </script>

In the code above, we've defined three propreties.

  • password, which will be our new password
  • passwordConfirmation, to make sure that the user didn’t make any mistake
  • code, the code contained in the reset link sent to the user via email

To test the new functionality, run npm run dev to start the development server. Then, visit http://localhost:3000/forgot in your browser, go through the forgot password process and then try the reset, starting with the reset link sent to your email address.

Step 13: Token bonus

Awesome! We've done a lot, but there's still something missing before we wrap up.

If the JWT token expires, subsequent requests to Strapi will return a 401 Unauthorized error. To deal with this, we'll intercept error responses in axios and check if the status code is 401. If it is, we redirect the user to the login page.

Create a new ./plugins/axios.js file, and paste the following:

 export default function ({ $axios, redirect }) {
 $axios.onError((error) => {
 const code = parseInt(error.response && error.response.status)
 if (code === 401) redirect('/user/login')
 })
 }

Now, let’s import the new plugin in nuxt.config.js, add the following to your plugins section:

 plugins: ['~plugins/axios'],

Now, when the JWT expires the user will be gracefully redirected to the login page.

Conclusion

Hopefully, you've found this tutorial helpful for implementing Strapi authentication in your Nuxt app! You should now have a fully-built, ready to be deployed in production authentication flow, through which users can register, login, and reset their password.

Resources

The source code for both projects can be found on GitHub.

πŸ‘ tweet selection
Amine Boulaffas
Front-end develope

A Front-end developer, Acquia Certified and React.js expert.