Setup Postman for Laravel Sanctum
Laravel Sanctum provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs. Because Sanctum uses cookie-based authentication and hits CSRF protected endpoints like /login and /logout, we need to make sure we're sending a CSRF token with Postman.
Create a Postman Collection
To make this as effortless as possible, I'd recommend creating a Postman collection so we can apply our pre-request script (in a moment) to all endpoints. (you could use our laravel-postman package aswell). This makes it easier to apply a pre-request script to all endpoints under that collection. It also helps keep everything nice and tidy.
Create an environment
We're going to be setting a CSRF token in our environment variables in Postman, so we need to create a Postman environment.
Click the cog/eye in the top right of Postman, click Add and give your environment a name. Click Add again and switch to your environment in the top right (see top right of screenshot). Add a few environmental variables that you may need, the ones we are dealing with are 'APP_URL' and 'XSRF_TOKEN'
Now create a new request to /login in Postman, save it to your collection and add in the form data (email and password). Add an Accept
header with application/json
too, so you get back JSON. No surprise here, we get back a CSRF token mismatch error when you submit it.
Add a pre-request script
Now let's add that pre-request script to grab the CSRF token using Sanctum, setting the value in our Postman environment variables.
Edit your collection and switch to the Pre-request Scripts tab, and add the following.
pm.sendRequest({
url: pm.environment.get('APP_URL') + 'sanctum/csrf-cookie',
method: 'GET'
}, function (error, response, { cookies }) {
if (!error) {
pm.environment.set('XSRF_TOKEN', cookies.get('XSRF-TOKEN'))
}
})
Save and close, then edit your login endpoint and in the headers section add a header with the key: "X-XSRF-TOKEN" and value "{{XSRF_TOKEN}}". Save and try login again. You should now be authenticated.
Make authenticated requests
So we've sorted CSRF, now we'll make a request to /api/user to verify we're actually authenticated. Create a request for this in Postman and add it to your collection. And of course, send that request.
Strange.... , it shows unauthenticated.
Now, this should actually work. Postman has stored the cookies we got back from making the earlier request to /login and will send them along with this request. You can verify this by clicking the cookies link to the top right of your request.
The reason this isn't working is that Sanctum is denying the authenticated request based on the referrer.
If you're interested in diving into some Sanctum code and figuring out why, open up the EnsureFrontendRequestsAreStateful middleware and check out the fromFrontend method that all requests are piped through.
public static function fromFrontend($request)
{
$referer = Str::replaceFirst('https://', '', $request->headers->get('referer'));
$referer = Str::replaceFirst('http://', '', $referer);
return Str::startsWith($referer, config('sanctum.stateful', [])) ||
Str::is(config('sanctum.stateful', []), $referer);
}
It's checking the referrer!
At the moment in Postman, this isn't set, so add it to your headers list and send the request again. And now it will work.