Laravel sanctum csrf cookie every request?
Asked Answered
B

4

13

I'm using Laravel sanctum (former Airlock) and have a question about it. I read in the docs:

To authenticate your SPA, your SPA's login page should first make a request to the /sanctum/csrf-cookie route to initialize CSRF protection for the application:

axios.get('/sanctum/csrf-cookie').then(response => {
// Login... }); 

Once CSRF protection has been initialized, you should make a POST request to the typical Laravel /login route. This /login route may be provided by the laravel/ui authentication scaffolding package.

Does this mean that for every request I make, I should first check if the cookie has already been set? Because let's say I have a user that registers. Before making the POST request to register a user I should first make a GET request to get the CSRF-Cookie from my backend and then make the POST request to register the user.

Now the user gets redirected to the login webpage and is asked to login. Does the frontend then first have to check if there's a CSRF-Cookie, and if there isn't should it first again make the GET request to get the cookie?

This last bit also confuses me, because when calling the register method a user doesn't actually get logged in so the user has to be redirect to the login page to log in with the credentials the user just filled in to register which for me seems like a bad user experience, right?

Balkh answered 21/3, 2020 at 11:26 Comment(0)
T
23

I know it's been a while since this question was asked but just for anyone searching out there, No. You don't have to call /sanctum/csrf-cookie with every request. Before you make a post | put | delete... request, you can check to see if the XSRF-TOKEN cookie is set. If it is not, make a call to the /sanctum/csrf-cookie route (or whatever you have configured it to be). After the request has completed, (the XSRF-TOKEN cookie would have been set by your browser automatically) you can now proceed with the initial request.

The best place to do this is in an interceptor (if your http library supports it). I'm going to assume you are using axios.

// Install with 'npm i js-cookie'. A library that helps you manage cookies 
// (or just build your own).
import Cookies from 'js-cookie';

// Create axios instance with base url and credentials support
export const axiosInstance = axios.create({
    baseURL: '/api',
    withCredentials: true,
});

// Request interceptor. Runs before your request reaches the server
const onRequest = (config) => {
    // If http method is `post | put | delete` and XSRF-TOKEN cookie is 
    // not present, call '/sanctum/csrf-cookie' to set CSRF token, then 
    // proceed with the initial response
    if ((
            config.method == 'post' || 
            config.method == 'put' || 
            config.method == 'delete',
            /* other methods you want to add here */
        ) &&
        !Cookies.get('XSRF-TOKEN')) {
        return setCSRFToken()
            .then(response => config);
    }
    return config;
}

// A function that calls '/api/csrf-cookie' to set the CSRF cookies. The 
// default is 'sanctum/csrf-cookie' but you can configure it to be anything.
const setCSRFToken = () => {
    return axiosInstance.get('/csrf-cookie'); // resolves to '/api/csrf-cookie'.
}

// attach your interceptor
axiosInstance.interceptors.request.use(onRequest, null);

export default axiosInstance;

The XSRF-TOKEN cookie comes with a time of expiry. After that time, the browser deletes it. So as long as you can find the cookie, it is safe to make a request without calling /sanctum/csrf-cookie or whatever you have configured it to be.

Trustee answered 4/12, 2021 at 21:15 Comment(2)
Any idea why I automatically get new cookies with each request to the API?Dandridge
That's because Laravel automatically responds with a Set-Cookie header. This header contains the cookie, the browser then picks the cookie and saves it.Trustee
L
4

Once you hit axios.get('/sanctum/csrf-cookie') API, after that you don't have to hit it again and again for every request, Because this/sanctum/csrf-cookie will save the XSRF token on browser and Axios will send it with the request.

You can learn about it in detail in this video: https://www.youtube.com/watch?v=8Uwn5M6WTe0

Lying answered 9/4, 2020 at 9:43 Comment(1)
I've been stuck on a CORS error with sanctum for 3 days, just stumbled upon your answer on this question that is not anywhere near related to my actual problem but it addresses 60% of the basics that I found lacking in official docs and were root cause for my problem. Kudos to you for sharing this YouTube tutorial.Timisoara
R
3

When you get the csrf token, in the following request, laravel will update the token automatic, so you dont need focus this after axios.get('/sanctum/csrf-cookie').

Replevin answered 21/3, 2020 at 13:12 Comment(2)
So basically I should just make the request one when registering and after that Laravel does the magic each request itself?Balkh
Check this, bilibili.com/video/av96088617. There is a sample in it.Replevin
A
-1

In Laravel 11 the XSRF-TOKEN cookie has the same expiration time than your session cookie. Notice that a session can be (and usually is) created no matter if you are logged in or not, so in theory you can request your XSRF-TOKEN cookie without the need of logging in. However, assuming all your writing endpoints (POST, PUT, DELETE) are for authenticated users only, it is just the most convenient thing to call /sanctum/csrf-cookie just before logging in. On top of that, when you log in, Laravel will regenerate the session, which means it will also regenerate the XSRF-TOKEN and refresh both cookies expiration dates.

Therefore, in my opinion, you don't even need to check if this cookie is there or not. At some point your session cookie will expire, and then all "private" endpoints will return a 401. If you are writing an SPA you might want to handle this "user is not authenticated anymore" situation. You could do long polling or set an axios interceptor (for the response status 401), and force reload or redirect to login page, depending on how your frontend routing works.

Aintab answered 10/6 at 21:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.