Is combining Nuxt 3 with WP REST API, Pinia, and local storage an effective approach for user authentication?

My current project involves utilizing NUXT 3 for the frontend and integrating Wordpress as the backend. The data is transmitted from the backend to the frontend through the REST API. The application functions as a content management system (CMS), with all routes protected by a middleware that verifies the user's login status. This middleware checks for the existence of local storage, created upon successful user login.

The process works as follows:

  1. For every route, the middleware validates the presence of local storage userAuthentication. If it's missing, the user is redirected to the /login page. This middleware operates globally but only on the client side.

  2. Upon attempting to access the application, a POST request is sent to the Wordpress backend with the user's provided credentials. If the endpoint responds with CODE 200, the data is saved in the PINIA store, and a local storage is generated containing the response data (including the token). Subsequently, the user gains access to protected routes.

  3. When the user logs out, the local storage is deleted, and they are redirected to the /login page.

Here are some queries I have:

  1. Is this approach secure?
  2. Is the server adequately secured by Wordpress, or should I implement server middleware?
  3. Could an unauthorized individual gain access to my app by creating local storage with the same name?

I welcome any insights or suggestions.

middleware/auth.global.ts

export default defineNuxtRouteMiddleware((to, from) => {
    // isAuthenticated() serves as an example validation method for user authentication
    if (typeof window !== 'undefined') {

        const useStateLocalStorage = JSON.parse(localStorage.getItem('userAuthentication'));

        if (!useStateLocalStorage) {
            if (from.path === '/login') {
                return abortNavigation()
            }

            if (to.path !== '/login') {
                return navigateTo('/login')
            }
        }

        if (useStateLocalStorage) {
            if (to.path === '/login') {
                return abortNavigation()
            }
        }

    }
})

/login.vue

import { useUserStore } from "~/store/userAuth";

const config = useRuntimeConfig();
const signinForm = ref({ username: "", password: "" });
const userStore = useUserStore();

const signIn = async () => {

  const response = await $fetch(config.public.apiBaseUrl + '/wp-json/jwt-auth/v1/token',
      {
        method: "post",
        body: {
          'username': signinForm.value.username,
          'password': signinForm.value.password
        }
      })
      .then((response) => {

        //SUCCESS
        //console.log('LOGIN SUCCESS', response);

        //SAVE USER DATA IN PINIA STORE
        userStore.IsAuth = true;
        userStore.token = response['data']['token'];
        userStore.username = response['data']['displayName'];
        userStore.email = response['data']['email'];
        userStore.firstName = response['data']['firstName'];
        userStore.lastName = response['data']['lastName'];

        //DEBUG

        console.log(userStore.IsAuth)
        console.log(userStore.token)
        console.log(userStore.username)
        console.log(userStore.email)
        console.log(userStore.firstName)
        console.log(userStore.lastName)

        //NAVIGATE TO HOME
        navigateTo('/')

      })
      .catch((error) => {
        console.log('LOGIN ERROR', error)
      });

  //console.log(response)
  signinForm.value = {username: "", password: ""};

}

userStore.$subscribe((mutation, state) => {
  localStorage.setItem('userAuthentication', JSON.stringify(state))
})

store/userAuth.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
    state: () => {
        return {
            token: null,
            username: null,
            email: null,
            firstName: null,
            lastName: null,
            IsAuth: false
        }
    },
    persist: true,
    actions: {
        userUpdate(payload) {
            //localStorage.setItem('user-auth', payload)
            this.user = payload;
            this.IsAuth = payload;
        },
        tokenUpdate(payload) {
            //localStorage.setItem('user-auth', payload)
            this.token = payload;
        },
    }
})

Answer №1

Although I am not well-versed in the wordpress backend, my recommendation would be to refrain from storing sensitive user information in localstorage due to its vulnerability to third-party scripts.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Accessing the page directly in a Nuxt SPA is not permitted

I'm currently working with Nuxt version 2.3.4. In my project, I am utilizing vue-apollo to fetch data for a file named pages/_.vue, which dynamically manages content. As indicated on this documentation page, this is the recommended approach for handli ...

A child component in Vue.js unexpectedly starts updating when the parent component renders and uses object literals as props

I'm currently facing an issue with my Vue components where object literals are passed as props like: <child :prop1="{ foo: 'bar' }"></child> After rerendering the parent component, the prop prop1 changes and triggers an update ...

Executing a callback function when a window confirmation is triggered during the onbeforeunload event

Currently, I need to implement a feature where a confirmation window pops up when the user tries to close the page. The code snippet for this functionality is included below: window.onbeforeunload=function(){ if(...) { return "Are you sure you want to ...

Storing formatted user input in an array with VueJS: A step-by-step guide

Looking for assistance that relates to the following question Vue.js: Input formatting using computed property is not applying when typing quick I am facing a challenge in extracting formatted values from text inputs and storing them in an array. I intend ...

The IMDB API is throwing a GraphQL error that says, "ClientError: Unable to retrieve information on the field 'Image' for the type 'MainSearchEntity'."

Seeking suggestions for the top 10 movies related to 'Africa' using the IMDB API demo available here. In my query, I am looking for movie id, title, poster image, and filming location. However, I encounter an error message 'ClientError: Ca ...

Sending an Ajax POST request from a Node.js server

I am running a Node.js server with Socket.IO that communicates with a Python server using Django. I am looking to make a POST request from the Node.js server to the Django server on a specific method without utilizing any jQuery functions due to their depe ...

Does Vuex dispatch from within a component include a particular type of behavior known as a "promise"?

Currently, I am diving into vuex and facing an issue. During the created() lifecycle hook, my goal is to fetch data from an API. Once this action is complete, I need to call a getter from the component and assign the retrieved cards to the component's ...

Combine an unlimited number of arrays in Node, arranging the items in the result array in an alternating pattern

How can I efficiently merge multiple arrays of different lengths containing objects of the same types into one final array while ensuring that the items alternate in the result? For example, if one array only has one value, the merging should continue alt ...

Welcome Message using Discord.js V13

As a newcomer to bot creation, I am facing an issue with my welcome message in discord.js v13. Previously working in v12, I am now encountering difficulties sending a message to a specific channel when a user joins the server. After some investigation, I r ...

Guide on incorporating a texture file (.mtl) onto a model (.obj) with three.js

I've managed to successfully display a .obj file using three.js by adapting code I found online for my project. However, I'm now facing challenges when trying to incorporate the .mtl material file. Despite attempting various solutions, nothing s ...

Is it possible to execute JavaScript code (using Node.js) through AppleScript on MAC OS?

After downloading Node.js for MAC OS from this link: http://nodejs.org/download/ (http://nodejs.org/dist/v0.10.29/node-v0.10.29.pkg), I needed to execute a JavaScript on Google Chrome. To do this, I utilized the following AppleScript code: do shell script ...

The module named "jquery" has not been loaded in this context: _. Please use require() to load it

As I work on migrating my Javascript files to Typescript, I encountered an issue when trying to use the transpiled javascript file in an HTML page. The error message I received is as follows: https://requirejs.org/docs/errors.html#notloaded at makeError (r ...

Session is required for req.flash() function in node.js to work properly

I recently started working with Node.js and I'm encountering an issue with sessions. I developed a simple application and tried to run it locally, but ran into some errors. Below are the details of my code along with the error messages: BAPS.js (app. ...

"Encountering an undefined error when making an AngularJS $http post request and receiving a

I am working on retrieving a specific value from the server side by passing a variable from the front-end (AngularJS javascript) to the backend (PHP) using $http. Once the server side (PHP) receives the value from the front-end, it executes an SQL query to ...

Learn how to retrieve the value on keyup in Laravel 5 when using Vue.js for editing purposes

Within our application, we have incorporated validation into the code. When working on the Edit section, how can I verify if a particular code already exists? The following snippet demonstrates my attempt: Edit Vue <label>Code</label> <inp ...

What is the best way to develop a widget that loads asynchronously by implementing AJAX, JavaScript, and PHP?

Currently, this widget is in need of items that are sourced from a php file. For instance, the javascript function should generate a table within this div element. <div id="widget"></> The aim is to dynamically update the content with the ht ...

Outputting HTML using JavaScript following an AJAX request

Let's consider a scenario where I have 3 PHP pages: Page1 is the main page that the user is currently viewing. Page2 is embedded within Page1. It contains a list of items with a delete button next to each item. Page3 is a parsing file where I send i ...

Retrieve child and descendant nodes with Fancytree JQuery

I'm currently utilizing Fancytree and have created the following tree structure: root |_ child1 |_ subchild1 |_ subchild2 |_ subchild3 |_ subchild4 When the selected node is child1, I am able to retrieve the fir ...

Modifying webpage design using JavaScript for styling

Is there a way to change the css style(defined in the page source) dynamically with Java? I know it is possible to do it with JavaScript. If there isn't, are there other situations where JavaScript is the only choice developing a web app? ...

Customize Nuxt default document using a custom app.html file

According to the guidelines provided by Nuxt documentation, you have the ability to customize the default document by... placing an app.html file in the source directory of your project, which is typically the root directory. I followed these instructio ...