Laravel 11.x Sanctum SPA authentication with Postman!

Laravel 11.x Sanctum SPA authentication with Postman!

For those who are unfamiliar with Laravel, it is a very popular monolithic PHP web framework similar to others like Ruby on Rails. It is known for its ease of use, rapid development and making PHP development far more enjoyable haha!

Sanctum is an official Laravel package that is designed to provides a featherweight authentication system for SPAs and simple APIs. Sanctum is by far the easiest way to add authentication to a Laravel application.

Sanctum offers an API token approach designed for authenticating APIs and mobile applications, which is fairly easy to setup. On the other hand the cookie bases SPA authentication method can be quite confusing to configure. Which is unfortunate as this is the method most people will be using.

So here I am going to show you how to configure the Sanctum SPA Authentication in Laravel 11.x and test it with Postman. I will also include an Axios configuration to easily authenticate from your SPA also!

NOTE: The SPA authentication method only works if the request is coming from the same domain, but can come from different subdomains. For example website.com can authenticate to api.website.com.

Follow along with the Sanctum documentation here.

Installation & Configuration of Sanctum

By default Laravel does not include authentication, but provides artisan commands to install and scaffold Sanctum. It will generate a few files you will need, like a database migration and a config file specifically for Sanctum.

php artisan install:api

Configuring Your First-Party Domains

In your .env file you will want to add the domain which you will be accepting requests from. This will be used to verify the Referer header, and if not found the Origin header.

SANCTUM_STATEFUL_DOMAINS=website.com
– or –
SANCTUM_STATEFUL_DOMAINS=spa.website.com

Sanctum Middleware

Inside bootstrap/app.php you want to add the stateful API middleware to the entire application, this can be done with the following. Without this middleware any route protected by the auth:sanctum middleware will fail.

->withMiddleware(function (Middleware $middleware) {
//
$middleware->statefulApi();
})

CORS and Cookies

For almost any application you will want CORS enabled, Sanctum requires it to function properly. You can easily scaffold its configuration with the following:

php artisan config:publish cors

This will generate the config/cors.php file. In this file you will simply need to set the supports_credentials to true. This will prevent the cookies from being blocked by CORS.

Lastly for this section you will to edit the SESSION_DOMAIN in your .env file. You will want to change it to the domain of your SPA or you can prefix it with a . to make it accept all subdomains.

For example .website.com will allow any subdomain.

Logging In

So now we have everything in place to verify out tokens, but we need to create the login route which will verify our email and password and associate that with our session.

You can easily just add the following to your routes/web.php

use IlluminateSupportFacadesAuth;

Route::post(‘/login’, function () {
$credentials = $request->validate([
’email’ => [‘required’, ’email’],
‘password’ => [‘required’],
]);

if (Auth::attempt($credentials)) {
$request->session()->regenerate();

return Response([
‘message’ => ‘Successful login!’
], 200);
}

return Response([
‘message’ => ‘Mismatch email and password!’
], 401);
});

You can also follow the example provided by Laravel however it does not return JSON like above, but a redirect response.

Configure Postman Collection

Before we configure Postman I want to briefly discuss the operations required for logging in.

First Sanctum needs us to hit the /sanctum/csrf-cookie endpoint with a GET request. This will return a 204 request meaning it was successful but has no content, it only contains our session cookies.

Then we can make a POST request to our newly created /login route with an an email and password in the body to authenticate and associate the authenticated user with the session matching the issued token in our previous step.

Now we are fully authenticated and can use any sanctum protected route by passing the cookie along with the header X-XSRF-TOKEN containing the parsed value of the cookie in the request. This can be tested by making a request to the /api/user route that is included by default.

Don’t worry Postman and Axios can easily manage the cookies and headers for us!

The postman collection

You can download this Laravel 11.x Sanctum SPA Collection to follow along.

The key to the postman collection lies in our collection Pre-request script:

const jar = pm.cookies.jar();

jar.get(http://localhost:5174, XSRF-TOKEN, (err, cookie) => {

pm.request.addHeader({
key: X-XSRF-TOKEN,
value: cookie
});

pm.request.addHeader({
key: Origin,
value: http://localhost:5174
});

pm.request.addHeader({
key: Referer,
value: http://localhost:5174
});

});

This script will run before every request, parsing the cookies found for the given origin and adding them to the X-XSRF-TOKEN header. It also sets both the Referer and Origin header which sanctum requires.

You may notice that I have set the Referer and Origin header to localhost:5174 this is simply because that is a common port for SPA applications built with Vite!

NOTE: If this fails at any point it is probably because Postman requires you to give access to the cookies that belong to the origin. You can do it with the following process:

Axios configuration

Axios is a promise based HTTP client for JavaScript giving you a really easy way to work with HTTP requests. In our case it offers configuration points that make working with Sanctum extremely easy.

import axios from axios;

let axiosInstance = axios.create({
baseURL: http://localhost,
timeout: 1000,
headers: {
Accept: application/json
},
withCredentials: true,
withXSRFToken: true,
xsrfCookieName: XSRF-TOKEN,
xsrfHeaderName: X-XSRF-TOKEN,
});

export default axiosInstance;

By examining the above configuration, if you are familiar with Axios, you will see that its a pretty simple Axios configuration except for 4 configurations:

withCredentials
withXSRFToken
xsrfCookieName
xsrfHeaderName

Lets first discuss the withCredentials. This option tells Axios to attach cookies found in the browser batching the origin to the request.

Next is withXSRFToken. This option tells Axios to set the XSRF header only for requests of the same origin.

Finally xsrfCookieName and xsrfHeaderName tell Axios which cookie to parse for the header, and the name of the header to attach. Both options default to the values given in the above configuration which Sanctum expects.

Now any requests made with this Axios instance will be compatible with Laravel Sanctum SPA authentication!