Thursday, November 14, 2024

Laravel Security: Using Encrypted Cookies

Rutger Broerze
Laravel Security: Using Encrypted Cookies image

Web application security is a critical aspect of development, especially when it comes to protecting user data. Cookies play a vital role in web applications, helping with session management, user authentication, and storing preferences. Improperly handled cookies can expose sensitive data to attackers.

Laravel takes security seriously by automatically encrypting cookies. In this post, I will explain how Laravel handles cookie encryption, why it’s essential, and how you can ensure your application is leveraging it effectively.

Laravel simplifies cookie encryption with built-in mechanisms. By default, all cookies created by your application are encrypted before being sent to the user’s browser. This ensures that even if someone intercepts the cookie, its contents remain unreadable without the decryption key.

How It Works

  1. Encryption: When you create a cookie, Laravel uses the APP_KEY specified in your .env file to encrypt the data using AES-256-CBC.
  2. Decryption: When the user’s browser sends the cookie back, Laravel decrypts it automatically to make the data accessible to your application.
  3. Validation: Laravel also validates the integrity of cookies, ensuring that no tampering has occurred.

The entire process is handled by the EncryptCookies middleware, which is applied globally to your application and enabled by default.

Checking If Laravel Is Encrypting Your Cookies

To verify that your Laravel application is encrypting cookies correctly, follow these steps:

Inspect Cookies in the Browser

  • Open your browser’s developer tools (usually accessible via F12 or right-click > Inspect).
  • Navigate to the Application or Storage tab (the exact name depends on your browser).
  • Under the Cookies section, locate your application’s domain.
  • Check the cookie values.
  • Encrypted cookies will appear as long, seemingly random strings (e.g., eyJpdiI6IjhzQk...).
  • If the cookie contains readable values, encryption is not working as expected.

Automatic Check

I am currently developing a new feature for Sorane that will automatically do this check for you (among a lot of other checks), and notify you when your cookies are not encrypted. Consider using Sorane if you want this kind of information.

Laravel comes with cookie encryption enabled out of the box, but if you're seeing unencrypted cookie values, check these files to ensure everything is set up correctly:

Check the EncryptCookies Middleware

If you have a app/Http/Kernel.php file, which is common in older versions of Laravel, confirm that the EncryptCookies middleware is listed under the $middlewareGroups array. It should look like this:

protected $middlewareGroups = [
	'web' => [
		\App\Http\Middleware\EncryptCookies::class,
		...
	]
];

If you have a bootstrap/app.php file, more common in recent versions of Laravel, you should look at the withMiddleware function in that file.

Make sure you don't overwrite the whole web middleware group with your own set of middleware, without including the EncryptCookies middleware. If it's missing, add it to enable cookie encryption.

->withMiddleware(function (Middleware $middleware) {
	$middleware->group('web', [
		\Illuminate\Session\Middleware\StartSession::class,
		//\Illuminate\Cookie\Middleware\EncryptCookies::class,
		...
	]);
})

Another common way to disable cookie encryption is by explicitly removing the EncryptCookies middleware from the web group. If you see this, undo it.

->withMiddleware(function (Middleware $middleware) {
	$middleware->web(remove: [
		\Illuminate\Cookie\Middleware\EncryptCookies::class,
	]);
})

Common Issues and Troubleshooting

Invalid Cookies

If cookies are tampered with or corrupted, Laravel will reject them. This typically results in a DecryptException.

Solution: Ensure your APP_KEY is consistent across all deployments.

Changing the Encryption Key

Changing the APP_KEY invalidates all existing encrypted cookies, which can result in decryption errors and logout issues for users with active sessions.

Solution: Gracefully rotate your app key

APP_KEY="base64:4BgTq8VPzKXzC21GzV+l5nTMeQoJp/WtUnFluJZ97Ug="
APP_PREVIOUS_KEYS="base64:p6TpQGLX+aJ5n8C2YzTLQ7Jq3Vp6K2ozB1uFo9VmXTg="

When you set the APP_PREVIOUS_KEYS environment variable, Laravel will always encrypt values using the “current” encryption key. But when it comes to decrypting, Laravel uses an intelligent approach by first attempting to decrypt with the current key, and if unsuccessful, it checks previous keys sequentially until it finds one that can successfully decrypt the value.

This means that you can safely rotate your encryption keys without breaking existing functionality, as Laravel ensures backward compatibility by checking older keys during decryption.

Conclusion

By encrypting cookies, Laravel ensures that sensitive data remains secure, even if intercepted. Understanding how encryption works, verifying your setup, and handling common issues like key rotation are essential steps to maintaining a secure application.

If you want to go a step further, tools like Sorane can help automate these checks and notify you when potential security issues arise, ensuring your application remains protected without extra manual effort. Secure your application, and let Laravel and Sorane handle the rest!

It takes only one minute to get started

Start monitoring your Laravel applications today

Websites will go down, and errors will happen. With Sorane, you are sure to catch any errors and performance issues the moment they happen.

Takes 1 minute to get started.
No credit card required. Cancel anytime.