I have a Laravel powered api locally hosted at http://tenant.api.hydrogen.local and an Angular 9.2 SPA which is being served on http://localhost:8100. I recently installed Laravel Sanctum for authentication and followed instructions for SPA's listed in the docs but the CSRF token is not attached to requests from the SPA and I therefore receive a CSRF token mismatch error.
As instructed I make an initial call to //abc.api.hydrogen.local/sanctum/csrf
before subsequently attempting to login in:
this.http.get('sanctum/csrf-cookie')
.pipe(
switchMap(result => this.http.post('auth/login', {'email': email, 'password': password}))
);
Note: I have an interceptor that prepends the request url with the api url '//abc.api.hydrogen.local/' e.g. 'sanctum/csrf-cookie' will become '//abc.api.hydrogen.local/sanctum/csrf-cookie'
The response from sanctum/csrf-cookie is returned with the expected headers:
Access-Control-Allow-Credentials: true
Set-Cookie: XSRF-TOKEN=eyJpdiI6Ilc3UkRLR1BSZ29TWVh3ZWZEQ3Y4aGc9PSIsInZhbHVlIjoiRUZBZXNFWTlZbWo5QWhIeWsrRmpjNUZVWkExSGtaT1hzUTVnSXpoaGQ4c3dFc2VLNjZsUHlUVWFmbG1uVVdKZSIsIm1hYyI6ImU1ZTAxNGFmMjAwNWRiMDhiODFjMGZhYTljYmU1NmRjYTUzYTNmNDJjNWM3YmQyM2FkY2I2OGYwNjYzNGU2MjkifQ%3D%3D; expires=Thu, 30-Apr-2020 13:35:06 GMT; Max-Age=7200; path=/; domain=localhost
Access-Control-Allow-Origin: http://localhost:8100
However, when I look at browser console I do not see anything set in storage > cookies. Furthermore there are no cookies attached to the subsequent call to `login/' and I receive a CSRF token mismatch error.
I have read through numerous posts detailing similar problems and implemented their recommendations and configurations including the following:
This problem occurred because the browser/angular will only attach cookies to requests that have the same domain as where the request is coming from.
To fix this in the dev environment where the angular app is being served on localhost and the Laravel app is on a domain like abc.api.hydrogen.local I proxied requests from the angular app:
First ensure your requests are relative routes, for example I changed my calls to /api/sanctum/crsf which then gets proxied to http://abc.api.hydrogen.local/sanctum/crsf
Then create a proxy configuration proxy.conf.json
in the root of the project:
{
"/api/*": {
"target": "http://abc.api.hydrogen.local",
"secure": false,
"changeOrigin": true,
"logLevel": "debug",
"pathRewrite": {
"^/api": ""
}
}
}
Then edit angular.json
to use the proxy when it is serving:
"architect": {
...
"serve": {
...
"options": {
....
"proxyConfig": "proxy.conf.json"
}
}
}
Finally in your .env
file add the following to ensure that sanctum identifies requests as being from first party SPA's and the browser is able to read and attach cookies to the request.
SANCTUM_STATEFUL_DOMAINS=localhost,.hydrogen.local
SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
Now everything should work.