Cookies work quite differently on the Angular front end versus the Laravel back end — Angular has no built-in cookie API and needs either a small service wrapping document.cookie or a dedicated package, while Laravel wraps cookies in its own facade with automatic encryption already applied.
Setting a cookie in Laravel
use Illuminate\Support\Facades\Cookie;
Cookie::queue('theme', 'dark', 60 * 24 * 30); // minutes: 30 days
// or attached directly to a response
return response('OK')->cookie('theme', 'dark', 60 * 24 * 30);
Cookie::queue() is the more common approach — it queues the cookie to be attached to the outgoing response automatically, without needing to manually chain ->cookie() onto whatever specific response object the current request happens to return.
Getting a cookie in Laravel
$theme = request()->cookie('theme');
// or, equivalently
$theme = Cookie::get('theme');
Laravel encrypts cookies by default
Every cookie set through Laravel is automatically encrypted and includes an authentication signature, verified by the EncryptCookies middleware on the way back in — this happens transparently, and is exactly why a cookie value can't simply be read or tampered with directly in browser dev tools without it being rejected as invalid on the next request.
Excluding a specific cookie from encryption
// bootstrap/app.php (Laravel 11+)
->withMiddleware(function (Middleware $middleware) {
$middleware->encryptCookies(except: ['analytics_id']);
})
A cookie that needs to be readable by client-side JavaScript, or by a third-party script, needs to be excluded from Laravel's automatic encryption — otherwise that external code would only ever see the encrypted, unreadable value.
Reading and writing a cookie in Angular with a small service
@Injectable({ providedIn: 'root' })
export class CookieService {
set(name: string, value: string, days: number = 30): void {
const expires = new Date();
expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;
}
get(name: string): string | null {
const match = document.cookie.match(new RegExp(`(^| )${name}=([^;]+)`));
return match ? match[2] : null;
}
delete(name: string): void {
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`;
}
}
Wrapping document.cookie's notoriously awkward string-based API in a small service keeps components from needing to know the low-level cookie string format directly, and makes cookie access mockable in component tests.
Using the ngx-cookie-service package as an alternative
npm install ngx-cookie-service
constructor(private cookieService: CookieService) {}
setTheme(theme: string) {
this.cookieService.set('theme', theme, 30);
}
getTheme(): string {
return this.cookieService.get('theme');
}
A dedicated package handles edge cases (path/domain scoping, SameSite attributes, proper encoding) more robustly than a quick hand-rolled service — worth the small dependency for an application relying on cookies more than incidentally.
Why a cookie set by Angular and one set by Laravel don't automatically share data
A cookie is scoped by domain, path, and other attributes independent of which side of the stack set it — an Angular app and a Laravel API on genuinely different origins need explicit CORS and cookie configuration (SameSite, credentials) for cookies to actually flow between them, following the CORS guidance covered elsewhere on this site.