Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vincent15000's avatar

Authentication with VueJS 3, axios and pinia

Hello,

I have an application (personal project) I had developed with VueJS2, axios and VueX. I now want to develop it with VueJS 3, axios and pinia. The back is with Laravel, I use Fortify for the authentication and the API endpoint are protected with Sanctum.

In the first application all works fine, but it was also my first VueJS front application so I had some bad code because it was my first steps into VueJS. But it does the job.

I have an API service (authApi) with 3 methods : login(user), logout() and getAuthenticated().

I have a Login component for the login view.

And the user can logout from the App.vue component where there is the main menu.

What I need is advice to organize all my authentication code.

According to me, pinia shouldn't have to login or logout a user, pinia should only have to store some data to be shared with the entire application (I say this because I have seen several example on the web with some business code for authentication inside a pinia store). But I'm perhaps wrong.

And I need to use pinia to persist the authentication even if a user refreshes manually the browser. For the moment I persisted the authentication with a property in the session storage. And if the user refreshed the browser manually, I read the session storage and if true I checked the authentication via a query to the backend. What can I do other and better ?

Can you advise me please how to organize the authentication code in the frontend ?

Thanks a lot.

V

0 likes
3 replies
ChrisSimons's avatar

Firstly, in terms of organising the logic, I would suggest separating the actual implementation logic for authenticating into another file and importing those into the Pinia store. The store would still have the getAuthenticated getter, and login/logout actions, but the action would defer to the implementation layer.

Secondly, I have had a similar experience implementing persistent storage in a pinia store, but in Nuxt3. I ended up using the useCookie function in the state, which let me define the state to reference a cookie. There maybe something similar for vanilla VueJS3. Not exactly a solution, but it may give you a steer on where/what to look for.

2 likes
vincent15000's avatar

@ChrisSimons So according to you it's not a problem to have the authentication logic inside the store ?

I'm really not used to handle stores ;).

ChrisSimons's avatar
Level 1

@vincent15000 Having the authentication logic in the store is not ideal, no. What I meant was to extract that logic (the implementation) into a separate unit. Your store would still be responsible for managing the state, but not implementing it. I've given an example below of the suggested segregation:

// ~/stores/auth:

import { loginImplmentation, logoutImplmentation } from '~/api/auth'
import { formatUser } from '~/utils/formatters'

export const useAuthStore = defineStore("auth", {
  state: () => ({
    user: null
  }),
  getters: {
    isAuthenticated: (state) => !!state?.user
  },
  actions: {
    async login (request) {
      await loginImplmentation(request) // defer the implmentation of login
        .then((response) => this.user = formatUser(response.data)) // update the store to reflect the state
        .then((user) => ...) // do whatever else you need
        .catch((e) => ...) // catch reject
    },
    async logout() {
      await logoutImplmentation() // defer the implmentation
      .then((response) => {  
        this.user = null
        return response
      }) // update the store to reflect the state
      .then((response) => ...) // do whatever else you need
      .catch((e) => ...) // catch reject
    }
  }
});
//~/api/auth.js

export const loginImplmentation = async ({ username, password }) => {
  return $fetch('/login', {
    method: "POST",
    body: { username, password }
  });
}

export const logoutImplmentation = async() => {
  // your logout implmentation
}
3 likes

Please or to participate in this conversation.