How to Encrypt Cookies in Symfony

Prevent cookie tampering in Symfony with custom encryption

.com software
2 min readSep 21, 2022
Photo by Markus Winkler on Unsplash

In today’s publication, we will deal with data security. Do you need to protect your cookies against unauthorized change? Or maybe you need to keep secret data within?

In that case, consider encrypting your cookies.

We will introduce this functionality in Symfony. However, the solution is so universal that the code can be copied from one project to another with virtually no changes!

I’m not fond of the approach proposed by Laravel. A middleware that responds to every request seems like a waste of resources to me.

I am the lord commander of my code and I do not need auto-magic solutions. I tend to rely on clearly defined functionalities using clear interfaces.

Contract definition

We shall create an interface for the new functionality. Since I’m using Symfony HttpFoundation’s classes, this code will also work in Laravel.

Here’s the contract for the cookie encrypter:

and the decrypter:

You might be wondering why I’m using the __invoke magical method. I’ve explained this thoroughly in a publication:

The implementation

The implementation is less important. Only the interfaces are going to be used in the application. Using the dependency injection feature of Symfony we can point out which implementation to use.

I am going to use the OpenSSL extension to encrypt the data. Two details are required beforehand:

  • the encryption cipher to use (can be listed with openssl_get_cipher_methods() ),
  • the encryption key.

I will store the default values inside the .env file:

COOKIE_ENCRYPTION_CIPHER=aes-128-ctr
COOKIE_ENCRYPTION_KEY=629bb089deae5519e3bfbe85fb55fa828b8e5407

And configure the container in the config/services.yaml file:

parameters:
cookie_encryption_cipher: "%env(COOKIE_ENCRYPTION_CIPHER)%"
cookie_encryption_key: "%env(COOKIE_ENCRYPTION_KEY)%"
services:
App\Http\CookieEncryption\OpenSSLCookieEncrypter:
arguments:
- '%cookie_encryption_cipher%'
- '%cookie_encryption_key%'
App\Http\CookieEncryption\OpenSSLCookieDecrypter:
arguments:
- '%cookie_encryption_cipher%'
- '%cookie_encryption_key%'

With the following implementation for the encrypter:

And the implementation for the cookie decrypter:

To use it, include the cookie in the response:

When executed, I can see in the response headers the cookie was sent:

Set-Cookie: secret_name=c03a0346b2f61e778c015aefc14a0c26.7238486e6b626c754a66755a49487346; path=/; httponly

To decrypt:

Returns:

secret_value

Additional validation of encryption parameters

A compiler pass would be nice to validate if the requested cipher is available and the key is correct.

Invalid values to these parameters would result in encryption failure in the runtime. Supported cipher methods may be different between the production and developer environments.

Just remember to include the compiler pass in the Kernel:

As stated previously, this code is portable. The code can be used across many PHP projects, in Symfony & Laravel, at the same time. With clear interfaces, cookie encryption becomes an integral part of your application.

Will you give it a try? I am already using this code in production for some of my projects. What do you think? Please let me know in the comments.

--

--

.com software

Father • PHP developer • entrepreneur • working for a €1bn unicorn startup as a backend engineer >>> https://bit.ly/dotcom-software