Maybe I'm late, but I west a lot of time to find the solution for this issue and I want to share you the final solution that was correct for me.
My setup: Angular 15 - Laravel 10 with sanctum.
Laravel configuration:
.env file: add lines
SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
sanctum.php file add stateful localhost:4200 (for angular ng serve)
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,localhost:4200',
Sanctum::currentApplicationUrlWithPort()
))),
cors.php set true for credentials:
'supports_credentials' => true,
RESTART THE SERVER LARAVEL FOR APPLY CHANGES.
Then, in Angular app:
Define interceptor like:
export class HttpXsrfInterceptor implements HttpInterceptor {
headerName = 'X-XSRF-TOKEN';
constructor(private tokenService: HttpXsrfTokenExtractor) {}
intercept(
req: HttpRequest,
next: HttpHandler
): Observable<HttpEvent> {
req = req.clone({
withCredentials: true,
});
req.headers.set('withCredentials', 'true');
if (req.method === 'GET' || req.method === 'HEAD') {
return next.handle(req);
}
const token = this.tokenService.getToken();
// Be careful not to overwrite an existing header of the same name.
if (token !== null && !req.headers.has(this.headerName)) {
req = req.clone({ headers: req.headers.set(this.headerName, token) });
}
return next.handle(req);
}
}
In AuthService, put the login method like:
login(loginForm: LoginForm): Observable {
return this.http.get('http://localhost/sanctum/csrf-cookie').pipe(
switchMap(() => {
return this.http
.post<LoginResponse>(base_url + 'access/login', loginForm)
.pipe(
tap((data) => {
const user = new User(
data.user.id,
data.user.firstname,
data.user.lastname,
data.user.username,
data.user.email,
data.user.created_at
);
this.user.next(user);
})
)
}),
catchError(error => {
console.error(error);
return throwError(error);
})
);
};
I hope this help someone.