dmytroshved's avatar

dmytroshved liked a comment+100 XP

3mos ago

@dmytro_shved Furthermore with Sanctum you don't have to store the token, it's done automatically via Laravel internal mechanisms.

dmytroshved's avatar

dmytroshved liked a comment+100 XP

4mos ago

Yeah, I have also struggled with this while learning. So, I remembered a little bit. I'am happy that it helps you.

As for now I have shifted towards the inertia so I just forgotten some amazing tips which I had learnt.

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

4mos ago

Here is the summary of changes after all refactors and researches

Appreciate for help: @shivamyadav, @shahriar_shaon and StackOverflow


Key points to pay attention to

  • there's no reason to keep setUser and getCurrentUser separate from the store, a store is not just a global state but can contain related business logic.

  • there's supposed to be a global auth guard instead of per route beforeEnter, this is where logic takes place:

router.beforeEach(async (to, from) => {
  if (from === START_LOCATION) {
    const userStore = useUserStore();
    await userStore.getUser();
  }
})
  • any initialization logic can be run like that. It's convenient to declaratively mark routes that need auth with meta: { auth: true } with this guard and run auth logic only if to.meta.auth === true.

  • it needs to be taken into account that initial navigation starts before an application is mounted. In order to avoid possible race conditions, it can be:

await router.isReady()
app.mount('#app')

Code

main.js

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';

import './style.css';

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(router)

await router.isReady()
app.mount('#app')

router/index.js

store/user.js

Usage

For example here is how my LoginView.vue script looks like

LoginView.vue

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

4mos ago

Appreciate your help :)

dmytroshved's avatar

dmytroshved liked a comment+100 XP

4mos ago

The issue happens because the router is creating a new Pinia store instance when you call useUserStore() inside the router guard. This latest instance does not contain the authenticated user, so isAuthorized always shows false.

router/index.js

import { useUserStore } from '@/store/user'
import pinia from '@/store'

router.beforeEach((to, from, next) => {
  const userStore = useUserStore(pinia)

  if ((to.name === 'login' || to.name === 'register') && userStore.isAuthorized) {
    return next('/')
  }

  next()
})
dmytroshved's avatar

dmytroshved liked a comment+100 XP

4mos ago

Try this you are mounting the router earlier.

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import setUser from '@/plugins/set-user.js'

async function bootstrap() {
  const app = createApp(App)
  const pinia = createPinia()

  app.use(pinia)

  //  Wait until user is loaded BEFORE router runs guards
  await setUser(pinia)

  app.use(router)
  app.mount('#app')
}
dmytroshved's avatar

dmytroshved wrote a reply+100 XP

4mos ago

It works only if I have authenticated user, if his session burns out I see only blank page and message that GET /user returns 401 Atuh error from backend, which means setUser failed

I added try..catch so application can mount even if user didn't found

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
import './style.css';
import setUser from '@/plugins/set-user.js'

async function bootstrap() {
  const app = createApp(App)
  const pinia = createPinia()

  app.use(pinia)

  try{
    //  Wait until user is loaded BEFORE router runs guards
    await setUser(pinia)
  } catch (error){
    console.log('Unauthorized')
  }

  app.use(router)
  app.mount('#app')
}

bootstrap()

What you think?

dmytroshved's avatar

dmytroshved started a new conversation+100 XP

4mos ago

Hi

I need to restrict access for authenticated users to the /login and /register routes

My Pinia Storage user.js contains a computed property isAuthorized. However when I try to use this variable in my router/index.js I see it always has a false instead of true.

Also F12 -> Vue -> Pinia shows isAuthorized = true, but in code it shows as false

I also have a plugin set-user that takes the current authenticated user from backend and saves him to the Pinia Store user.js

store/user.js

import { computed, ref } from 'vue'
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', () => {
  const user = ref(null)

  const isAuthorized = computed(() => !!user.value)

  function updateUser(userData) {
    userData ? user.value = userData : user.value = null
  }

  return {
    user,
    isAuthorized,
    updateUser
  }
})

router/index.js

plugins/set-user.js

import { getCurrentUser } from '@/api/user.js'
import { useUserStore } from '@/store/user.js'

export default async function setUser(pinia) {
  const { updateUser } = useUserStore(pinia)

  const userData = await getCurrentUser()

  userData ? updateUser(userData) : updateUser(null)
}

main.js

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
import './style.css';
import setUser from '@/plugins/set-user.js'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(router)

setUser(pinia)

app.mount('#app')

Would be grateful for your help

Best regards

dmytroshved's avatar

dmytroshved liked a comment+100 XP

4mos ago

@dmytro_shved Doing authorisation checks on the client is never secure. This is the entire reason Sanctum and its cookie-based authentication was created.

dmytroshved's avatar

dmytroshved started a new conversation+100 XP

4mos ago

Hey everyone

I am analyzing the code of RealWorld Example (Vue 3 + Pinia) and I'm trying to understand the author's logic for storing the user and token.

Below is a summary of what I observed.

1. User storage in localStorage

The app uses a custom Storage class to store the user object (from what I understood including the token) in localStorage:

// src/utils/storage.ts

export const userStorage = new Storage<User>('user')

Source code of userStorage

2. Global access via Pinia

The user is exposed through a Pinia store:

// src/store/user.ts

const user = ref(userStorage.get())
const isAuthorized = computed(() => !!user.value)

function updateUser(userData?: User | null) {
  if (userData) {
    userStorage.set(userData)
    api.setSecurityData(userData.token)
    user.value = userData
  } else {
    userStorage.remove()
    api.setSecurityData(null)
    user.value = null
  }
}

Notes:

  • user.value provides reactive access to the user data.

  • isAuthorized is a computed property based on whether a user exists (boolean true/false).

  • updateUser updates both Pinia and localStorage with edited user data.

Source code of Pinia storage

3. Token storage in JavaScript memory

The HttpClient class, used for API requests, has a private securedData property that holds the token.

// src/services/api.ts

export class HttpClient<SecurityDataType = unknown> {
  public baseUrl: string = "https://api.realworld.show/api";
  private securityData: SecurityDataType | null = null; // this line 
  private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
  private abortControllers = new Map<CancelToken, AbortController>();
  private customFetch = (...fetchParams: Parameters<typeof fetch>) =>
    fetch(...fetchParams);

  //...

  public setSecurityData = (data: SecurityDataType | null) => {
    this.securityData = data;
  };

Source code of api.ts (the file is pretty big (800+ lines of code), so you can find it by: Ctrl + F and typing HttpClient.)

During login, the token is stored both in localStorage (via userStorage) and in JavaScript memory (securityData):

// src/store/user.ts 

updateUser(result.data.user) // sets token in both places

4. Token recovery after reload

On application start, a plugin (set-authorization-token.ts) reads the token from localStorage and writes it to HttpClient.securityData

// src/plugins/set-authorization-token.ts

import { api } from 'src/services'
import { userStorage } from 'src/store/user'

export default function setAuthorizationToken(): void {
  const token = userStorage.get()?.token
  if (token !== undefined)
    api.setSecurityData(token)
}
// src/main.ts

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import registerGlobalComponents from './plugins/global-components'
import setAuthorizationToken from './plugins/set-authorization-token'
import { router } from './router'

const app = createApp(App)

app.use(createPinia())
app.use(router)

setAuthorizationToken()
registerGlobalComponents(app)

app.mount('#app')

Authentication flow:

  • The user visits Login.vue and logs in via api.users.login, which returns a user object (with token?).

  • updateUser(user) saves user in user.ts and userStorage, and copies token into HttpClient.securityData.

  • On page reload, setAuthorizationToken() reads the token from userStorage and restores it to HttpClient.securityData.

  • API requests use HttpClient.securityData in the Authorization header:

// src/services/index.ts

import { CONFIG } from 'src/config'
import type { GenericErrorModel, HttpResponse } from 'src/services/api'
import { Api, ContentType } from 'src/services/api'

export const limit = 10

export const api = new Api({
  baseUrl: `${CONFIG.API_HOST}/api`,
  securityWorker: token => token ? { headers: { Authorization: `Token ${String(token)}` } } : {},
  baseApiParams: {
    headers: {
      'content-type': ContentType.Json,
    },
    format: 'json',
  },
})

// ...

Source code of index.ts

My questions

  1. If the token is already in userStorage, why does the author also store it in JavaScript memory (securityData)?
  2. Is this approach secure? I understand that storing tokens in userStorage is vulnerable to XSS attacks, but since this repo has many stars I still don't understand the logic.
  3. How is the token actually protected here, given that it persists in userStorage and only copied into JavaScript memory on initialization?

I'm trying to understand the rationale and security implications of this design. Is this a common pattern? Are there better practices for SPA token management?

Would be grateful for your help

dmytroshved's avatar

dmytroshved was awarded Best Answer+1000 XP

5mos ago

I finally noticed where I had a mistake

My session table didn't have an user_id because I was using UUID for my users, and session table wasn't properly configured for such UUID

Fixed session migration (notice that session table included in the create_users_table migration in laravel 12)

Schema::create('sessions', function (Blueprint $table) {
    $table->string('id')->primary();
    $table->foreignUuid('user_id')->nullable()->index(); // fixed line to use UUID
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->longText('payload');
    $table->integer('last_activity')->index();
});

EDIT

I also wanna to leave the important configuration places you need to check if you're getting errors

Config settings to check:

backend

1. Check your SPA (e.g. VueJS app) and API (e.g. Laravel) are on the same top level domain

For example:

api - localhost:8000

spa - localhost:5173

(notice: localhost = 127.0.0.1:8000 is a top-level domain)

2. Ensure to properly configure .env

APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:5173
SANCTUM_STATEFUL_DOMAINS=localhost:5173
SESSION_DOMAIN=localhost

3. In your bootstrap/app.php in the withMiddleware

$middleware->statefulApi(); 

4. Ensure config/cors.php is properly configured

Notice: If you don't have this file run: php artisan config:publish cors

    'paths' => ['*'], // optionally config this line (see usual config below)

    'allowed_methods' => ['*'], // EXAMINE THIS LINE 

    'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], // v

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],
    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true, // AND EXAMINE THIS LINE (throws CORS error if false)

usually you can see this kind of config for paths in config/cors.php

'paths' => ['api/*', 'sanctum/csrf-cookie', '/login', '/logout'],

5. Session and SESSION_DRIVER

In your .env file check SESSION_DRIVER=database (it's a default value and you don't need to touch it)

Check user_id is set after registration/login in your sessions table

Reminder:

  • You don't need to call the /sanctum/csrf-cookie in logout, because after yout logged in or registered the frontend should already have the token

  • Authentication routes (login, register, logout) should be in routes/api.php not routes/web.php

frontend

1. Check your axiosClient (if you're using one, or chec your axios are using proper settings)

Example of my src/axios.js

import axios from 'axios'
import router from '@/router/index.js'

const axiosClient = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL, // check how to configure this line below
  withCredentials: true, // THIS LINE IS IMPORTANT
  withXSRFToken: true, // THIS LINE IS ALSO IMPORTANT
})

axiosClient.interceptors.response.use( (response) =>{
  return response;
}, error => {
  if (error.response && error.response.status === 401){
    router.push({name: 'Login'})
  }

  throw error;
})

export default axiosClient

in your .env (notice: its a SPA's .env file, not an API's) check you have your API base URL, for example

VITE_API_BASE_URL=http://localhost:8000

2. Check your routes are sending the GET /sanctum/csrf-cookie request before POST, PUT, PATCH, DELETE

example: login request

const form = reactive({
  email: '',
  password: '',
})

const errorMessage = ref('')

function submit() {
  // THIS LINE IS IMPORTANT
  axiosClient.get('/sanctum/csrf-cookie').then(response => {
    axiosClient.post('/login', form)
      .then(response => {
        router.push({name: 'Home'})
      })
      .catch(error => {
        errorMessage.value = error.response.data.message;
      })
  });
}

Reminder:

  • You shouldn't call GET /sanctum/csrf-cookie before EVERY POST, PUT, PATCH, DELETE requests

Remember this: You only need to call the endpoint once at the start of the session.

Hope it'll provide clear understanding where you can find your error

Really appreciate the support I got from:

@jussimannisto

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

5mos ago

I finally noticed where I had a mistake

My session table didn't have an user_id because I was using UUID for my users, and session table wasn't properly configured for such UUID

Fixed session migration (notice that session table included in the create_users_table migration in laravel 12)

Schema::create('sessions', function (Blueprint $table) {
    $table->string('id')->primary();
    $table->foreignUuid('user_id')->nullable()->index(); // fixed line to use UUID
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->longText('payload');
    $table->integer('last_activity')->index();
});

EDIT

I also wanna to leave the important configuration places you need to check if you're getting errors

Config settings to check:

backend

1. Check your SPA (e.g. VueJS app) and API (e.g. Laravel) are on the same top level domain

For example:

api - localhost:8000

spa - localhost:5173

(notice: localhost = 127.0.0.1:8000 is a top-level domain)

2. Ensure to properly configure .env

APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:5173
SANCTUM_STATEFUL_DOMAINS=localhost:5173
SESSION_DOMAIN=localhost

3. In your bootstrap/app.php in the withMiddleware

$middleware->statefulApi(); 

4. Ensure config/cors.php is properly configured

Notice: If you don't have this file run: php artisan config:publish cors

    'paths' => ['*'], // optionally config this line (see usual config below)

    'allowed_methods' => ['*'], // EXAMINE THIS LINE 

    'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], // v

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],
    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true, // AND EXAMINE THIS LINE (throws CORS error if false)

usually you can see this kind of config for paths in config/cors.php

'paths' => ['api/*', 'sanctum/csrf-cookie', '/login', '/logout'],

5. Session and SESSION_DRIVER

In your .env file check SESSION_DRIVER=database (it's a default value and you don't need to touch it)

Check user_id is set after registration/login in your sessions table

Reminder:

  • You don't need to call the /sanctum/csrf-cookie in logout, because after yout logged in or registered the frontend should already have the token

  • Authentication routes (login, register, logout) should be in routes/api.php not routes/web.php

frontend

1. Check your axiosClient (if you're using one, or chec your axios are using proper settings)

Example of my src/axios.js

import axios from 'axios'
import router from '@/router/index.js'

const axiosClient = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL, // check how to configure this line below
  withCredentials: true, // THIS LINE IS IMPORTANT
  withXSRFToken: true, // THIS LINE IS ALSO IMPORTANT
})

axiosClient.interceptors.response.use( (response) =>{
  return response;
}, error => {
  if (error.response && error.response.status === 401){
    router.push({name: 'Login'})
  }

  throw error;
})

export default axiosClient

in your .env (notice: its a SPA's .env file, not an API's) check you have your API base URL, for example

VITE_API_BASE_URL=http://localhost:8000

2. Check your routes are sending the GET /sanctum/csrf-cookie request before POST, PUT, PATCH, DELETE

example: login request

const form = reactive({
  email: '',
  password: '',
})

const errorMessage = ref('')

function submit() {
  // THIS LINE IS IMPORTANT
  axiosClient.get('/sanctum/csrf-cookie').then(response => {
    axiosClient.post('/login', form)
      .then(response => {
        router.push({name: 'Home'})
      })
      .catch(error => {
        errorMessage.value = error.response.data.message;
      })
  });
}

Reminder:

  • You shouldn't call GET /sanctum/csrf-cookie before EVERY POST, PUT, PATCH, DELETE requests

Remember this: You only need to call the endpoint once at the start of the session.

Hope it'll provide clear understanding where you can find your error

Really appreciate the support I got from:

@jussimannisto

dmytroshved's avatar

dmytroshved liked a comment+100 XP

5mos ago

I'm not sure I get it right, so should I remove /sanctum/csrf-token call in the logout?

Yes. It shouldn't be needed, because the front end should already have the token: you only need to call the endpoint once at the start of the session. If it doesn't work, something's wrong.

Am I making a mistake placing my auth routes in routes/web.php instead of routes/api.php?

Yes. When you're using Laravel as a stateful API, those routes should be under api.php. Also, make sure to apply the auth:sanctum middleware to protected routes, e.g. the logout route.

https://laravel.com/docs/12.x/sanctum#protecting-mobile-api-routes

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

5mos ago

Okay I have an interesting question

Should I configure my SESSION_DRIVER to cookie instead of default DATABASE?

Because when I changed this thing my spa is not throwing 419 and everything working well!

Example

+ SESSION_DRIVER=cookie
- SESSION_DRIVER=database

EDIT

I also got a new idea how to fix it while keeping my SESSION_DRIVER=database

In my project it was necessary to use UUID for users (I know about their disadvantage, but it wasn't mine idea)

what if in my session table there was no user_id and thus I got an 419 because application didn't see users id in auth session?

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

5mos ago

There is no app.blade.php it is a Vue App

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

5mos ago

I'm not sure I get it right, so should I remove /sanctum/csrf-token call in the logout?

Are you doing anything unusual related to origins, like redirecting to a different subdomain or port after logging in, and then attempting to log out from there?

No, after login I am redirecting to the Home page, nothing fancy here

function submit() {
  axiosClient.get('/sanctum/csrf-cookie').then(response => {
    axiosClient.post('/login', data.value)
      .then(response => {
        router.push({name: 'Home'})
      })
      .catch(error => {
        console.log(error.response)
        errorMessage.value = error.response.data.message;
      })
  });
}

EDIT

Am I making a mistake placing my auth routes in routes/web.php instead of routes/api.php?

Route::post('login', LoginController::class);
Route::post('register', RegisterController::class);
Route::post('logout', LogoutController::class);
dmytroshved's avatar

dmytroshved liked a comment+100 XP

5mos ago

POST endpoints require a CSRF token, of course. The token is included in the XSRF-TOKEN cookie you receive in responses, and Axios automatically includes it as a request header.

The real question is why the token stops working after register or login. You shouldn't need to call the /sanctum/csrf-cookie endpoint before every POST request. Once should be enough. Even if the token was rotated during login (which it is not), the new token cookie would be included in the login response.

There must be something wrong with your setup.

Edit. Are you doing anything unusual related to origins, like redirecting to a different subdomain or port after logging in, and then attempting to log out from there?

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

5mos ago

Some good guy helped me with that, so I am leaving the answer here

You would still need to call the /sanctum/csrf-cookie as your /logout endpoint is a POST request.

All of laravel's POST,PUT, PATCH, DELETE requests require you to have the csrf cookie as mentioned here in the docs.


Fixed logout function

function logout() {
  axiosClient.get('/sanctum/csrf-cookie').then(response => {
    axiosClient.post('/logout')
  });
}
dmytroshved's avatar

dmytroshved wrote a reply+100 XP

5mos ago

The error happens in the request to /logout, I mean when I try to logout, I hit the button, it emits the logout function and then I see 419 in the browser, however preflight request was successfull

Are you regenerating the CSRF token at the end of a login / register, like you're doing in logout?

Im not sure, I am regenerating the session in the login, but at the register I don't

RegisterController

public function __invoke(RegisterRequest $request)
    {
        $user = User::create($request->validated());

        Auth::login($user);

        return (new UserResource($user));
    }

LoginController

public function __invoke(LoginRequest $request)
    {
        if (Auth::attempt($request->validated())){
            $request->session()->regenerate();

            return (new UserResource(Auth::user()));
        }else{
            return response()->json([
                'message' => 'The provided credentials are incorrect'
            ], 422);
        }
    }
dmytroshved's avatar

dmytroshved liked a comment+100 XP

5mos ago

When is the 419 thrown? Is it on the logout request itself, or some other action after that? Check the network tab in the browser's dev tools.

Are you regenerating the CSRF token at the end of a login / register, like you're doing in logout?

Regardless, Laravel should include a fresh XSRF-TOKEN cookie in the login or register response, and Axios should pick that up. If that's not working, further debugging is needed.

dmytroshved's avatar

dmytroshved started a new conversation+100 XP

5mos ago

Hey everyone

I am struggling with annoying 419 error trying to logout. The login and register are working fine. My api and spa are on the same top-level domain, but different ports

api - localhost:8000 spa (vue) - localhost:5173

After hours of debugging and changing the different settings I still get the 419

backend:

env

APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:5173
SANCTUM_STATEFUL_DOMAINS=localhost:5173
SESSION_DOMAIN=localhost

bootstrap/app.php

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        apiPrefix: 'api/v1',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->alias([
            'role' => RoleMiddleware::class,
        ]);

        $middleware->api(prepend: [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        ]);

        $middleware->statefulApi();
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();

cors

'paths' => ['*'],

    'allowed_methods' => ['*'],

    'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

sanctum

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,localhost:5173,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort(),
        // Sanctum::currentRequestHost(),
    ))),

authentication routes in routes/web.php

Route::post('login', LoginController::class);
Route::post('register', RegisterController::class);
Route::post('logout', LogoutController::class);

LogoutController.php

public function __invoke(Request $request)
    {
        Auth::logout();

        $request->session()->invalidate();

        $request->session()->regenerateToken();

        return response()->json([
           'message' => 'Logged out'
        ]);
    }

frontend:

axios.js

import axios from 'axios'
import router from '@/router/index.js'

const axiosClient = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  withCredentials: true,
  withXSRFToken: true,
})

axiosClient.interceptors.response.use( (response) =>{
  return response;
}, error => {
  if (error.response && error.response.status === 401){
    router.push({name: 'Login'})
  }

  throw error;
})

export default axiosClient

env

VITE_API_BASE_URL=http://localhost:8000

logout function

function logout() {
  axiosClient.post('/logout')
    .then((response) => {
      router.push({name: 'Login'})
    })
}

for reference

login function

const data = ref({
  email: '',
  password: '',
})

const errorMessage = ref('')

function submit() {
  axiosClient.get('/sanctum/csrf-cookie').then(response => {
    axiosClient.post('/login', data.value)
      .then(response => {
        router.push({name: 'Home'})
      })
      .catch(error => {
        console.log(error.response)
        errorMessage.value = error.response.data.message;
      })
  });
}

How I tried to debug logout

  • login
  • check cookies are set
  • use logout (error shows)

Would be grateful for your help

Best regards

dmytroshved's avatar

dmytroshved wrote a reply+100 XP

5mos ago

I have a question, what do you mean by

... blocks the address from being used to create any new ones

I mean how should I block that email? Should I create separate table for bounced_emails and then create vlidation rule that checks if email is in the black list? Or there is another way to block email?