Reader Stacks

Setting and Getting Cookies in Angular and Laravel

Angular needs a small service (or a package) to touch document.cookie safely, while Laravel wraps cookies in its own facade with automatic encryption baked in.

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.