Encrypting Queued Jobs, Notifications, Mail, and Listeners in Laravel
Photo by Shahadat Rahman on Unsplash
Introduction
There may be times when your Laravel application's queued jobs, notifications, mailables, or listeners contain sensitive information that you wouldn't want to have exposed. Typically, when storing sensitive information (such as passwords, API keys, etc.) in a database, you'd want to hash or encrypt the data.
Well, you can do the exact same thing with your queued jobs, notifications, mailables, and listeners!
In this article, we're going to quickly look at how to use the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface to encrypt your queued classes for improved security.
Encrypting Laravel Jobs
To understand why we'd want to encrypt your jobs, notifications, mailables, and listeners, let's take a look at a basic example.
We'll imagine our application requires a one-time password (OTP) when signing in. So we generate the OTP and send it to the user (whether this be via an email, SMS, etc.). We may have a job class that looks like so:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendOneTimePassword implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct(public readonly string $oneTimePassword)
{
//
}
// ...
}
In the class above, we're not too bothered about how we're sending the OTP. We're more concerned about the argument that's been passed to the job. In this case, the one-time password.
To run the job, we'd do something like so (notice the 123456
that we're passing as the OTP):
\App\Jobs\SendOneTimePassword::dispatch('123456');
When we dispatch the job, the data is serialized and stored in the queue store (such as the database or Redis). It's held here until the queue worker pulls the job off the queue and processes it.
If you or anyone malicious were to access the queue store, they'd be able to see the following information (beautified for readability) about the pending job:
{
"uuid": "3d05be68-8cd0-4c3a-8d05-71e86871713a",
"displayName": "App\\Jobs\\SendOneTimePassword",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "App\\Jobs\\SendOneTimePassword",
"command": "O:28:\"App\\Jobs\\SendOneTimePassword\":1:
{s:15:\"oneTimePassword\";s:6:\"123456\";}"
}
}
Did you spot it?
The oneTimePassword
property is visible in plain text in the data.command
field! If someone were to access the queue store, they'd be able to see the OTP.
And this could be any other kind of sensitive information that you wouldn't want to be exposed, such as API keys, passwords, social security numbers, etc.
To prevent this, we can update our job class to implement the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendOneTimePassword implements ShouldQueue, ShouldBeEncrypted
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct(public readonly string $oneTimePassword)
{
//
}
// ...
}
As a result of using this interface, Laravel will now encrypt the data before storing it in the queue store, and then decrypt it when pulling the job off the queue to process it.
Let's take a look at what the job data might look like now after using the ShouldBeEncrypted
interface:
{
"uuid": "ea194df6-ebe1-42a6-9e46-b7ece3b61781",
"displayName": "App\\Jobs\\SendOneTimePassword",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "App\\Jobs\\SendOneTimePassword",
"command": "eyJpdiI6IjRpR1FuRG5NTWpMZ28vdytUaGE0Rmc9PSIsInZhbHVlIjoicERX
MnJieGVleHp3czhYb3drb1N3ZnpHdHd2MVB1OFYvK24xbmlEUHdMcHk4K2Rr
ekdQMk9uczVFWFBmVkYvc1NneXMwVWVndlBxQkZySThkaTV6bk5NaVAzWnpG
aTN2MTZkSEVOUElYQzFSMFMxSnl5NzBkL0V1R1JwUDRYVTUiLCJtYWMiOiI0
NTQ4MmU3NmFhMzg1MjZkODcxNDc5YzQyNzE5ZTFlOWQxNzE4OWNlNTE5ODRl
YmJkN2ZiMjljYzI5Nzc4ODIyIiwidGFnIjoiIn0="
}
}
The oneTimePassword
property is now encrypted in the data.command
field! This means that even if someone were to access the queue store, they wouldn't be able to see the OTP.
Of course, this is a very basic example, but you can see how powerful this can be when dealing with sensitive information in your queued classes.
Encrypting Laravel Notifications
Not only can you use the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface with jobs, but you can also use it with queued notifications, mailables, and listeners.
This is great as it can add an extra layer of security to them too when they're stored in the queue store.
Let's take an example notification that could be used for sending a one-time password:
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class SendOneTimePassword extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*/
public function __construct(public readonly string $oneTimePassword)
{
//
}
// ...
}
We can dispatch the notification like so (again, notice the 123456
that we're passing as the OTP):
use App\Notifications\SendOneTimePassword;
$user->notify(new SendOneTimePassword('123456'));
If we were to inspect the data stored in the queue store for the pending notification, we'd see the following:
{
"uuid": "74e8c7d1-151d-4f05-aeae-b4dfcddba1a6",
"displayName": "App\\Notifications\\SendOneTimePassword",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "Illuminate\\Notifications\\SendQueuedNotifications",
"command": "O:48:\"Illuminate\\Notifications\\SendQueuedNotifications\":3:
{s:11:\"notifiables\";O:45:\"Illuminate\\Contracts\\Database
\\ModelIdentifier\":5:{s:5:\"class\";s:15:\"App\\Models\\User\"
;s:2:\"id\";a:1:{i:0;i:1;}s:9:\"relations\";a:0:{}s:10:\"
connection\";s:5:\"mysql\";s:15:\"collectionClass\";N;}s:12:
\"notification\";O:37:\"App\\Notifications\\SendOneTimePassword
\":2:{s:15:\"oneTimePassword\";s:6:\"123456\";s:2:\"id\";s:36
:\"9494b2db-7362-4936-8e31-5179594a1c01\";}s:8:\"channels\";
a:1:{i:0;s:4:\"mail\";}}"
}
}
Again, the oneTimePassword
property is visible in plain text in the data.command
field!
However, we can update our notification class to implement the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface:
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class SendOneTimePassword extends Notification implements ShouldQueue, ShouldBeEncrypted
{
// ...
}
This would now result in the pending notification's data being encrypted when stored in the queue store:
{
"uuid": "6dc8206c-c06c-4f21-a495-659a61546864",
"displayName": "App\\Notifications\\SendOneTimePassword",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "Illuminate\\Notifications\\SendQueuedNotifications",
"command": "eyJpdiI6InV3V0V0dTM0eXRLa0xWdHpnajBqcEE9PSIsInZhbHVlIjoiTkd5M2
pVZUpSMFVOdlJEa0lDY2d4MzdLdE1URW5rUC9iZERoSGFkVEJ4M3ZMSERlcVhi
ZmViUEg4S1R6ZlZzQ2dIY0JQV2N0VXczWGs5dGE3Y3JUUkRwN2hVWkNTRlVtTz
FRQkVnMkVtM0VhWnBRd2U4d05mOS9EVzhuV29JK0pNYkx1cEtIb2hDbm5MbWdH
aVNrR3VPTjI3em5uMkFKbG00dVNRak5BRGFhRkZqeUtodDU0Q2tCaWNBamR2eU
1Ec2pDaTBoN0dSbEpRRnROczl5b09CVUlmT2laVDZVZTdxdU9PbGtwQlV1S0lz
RGRMdTlmVTRWRTZMNnRFbFczZ3NSb25TM0kyYmFyTTIyYmtwY3ZheTJibURhNX
dXQkV1ZjEwSStGRzFBN1gxQmRYZzRodXc3UEY4a05teCtPVU1sVG0yN3hOd3pB
TjdyOFluR0gxckdYeHdNZitYYmJMeUxlcm4yRUl5NVB2NHN4WmRrZzJhYVNiRX
cydzQ3WkM4YTFrZ1dIRnBqLzVndnJOc0U2R1JTUm0vdWVkVVBuUTcvUmcxOWVP
UER1SjN1VTR1cDQ1eDB1a0l0SWFTMHhQWCtEMkVjcDYzS1AvS042djlHTmo1eU
11NWdUcGl0dTlkSWVONVIwLzhOZ2M0SDdHQ1k2S0FJUWh4UTJzT3VRR2dESFpK
MERwZ1dMZUFrRy9aZU55TUdTN3I4SDJjcTQ1M0tjZS9CekZrb3p1OFFucU5YM0
pwTWN1Y1BjTWVCc3E0RDlaSlErSndNRnVZeFFtNExsbzFQSUR6Vmo0WGZSMXJN
TzNteXgvMEZnRGMxRU9CS1pBZUNEbnV1YVB1b0RZb25ENXQ3WjFuN3RZcHFLZ1
ByamxNa1dlTVV1bmZRWE5hcXd6UXpUZmlzOXc9IiwibWFjIjoiYzgyNjA5MGNk
NTA3ZmM2MGNiMGQ3MjFjYzQyNTk2MWI0OWZiMGVmMTUyODFjMjYwNDM1YzM1MW
MyZjY3YmY5YSIsInRhZyI6IiJ9"
}
}
Encrypting Laravel Mailables
Similar to how we encrypted jobs and notifications, we can also encrypt mailables very easily.
Let's take this example mailable class that could be used for sending a one-time password:
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class SendOneTimePassword extends Mailable implements ShouldQueue, ShouldBeEncrypted
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(public readonly string $oneTimePassword)
{
//
}
// ...
}
We can send the mailable like so (again, notice the 123456
that we're passing as the OTP):
use App\Mail\SendOneTimePassword;
use Illuminate\Support\Facades\Mail;
Mail::send(new SendOneTimePassword('123456'));
If we were to inspect the data stored in the queue store for the pending mailable, we'd see the following:
{
"uuid": "07d4671a-b350-4203-9152-d95d10398879",
"displayName": "App\\Mail\\EncryptedMail",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "Illuminate\\Mail\\SendQueuedMailable",
"command": "O:34:\"Illuminate\\Mail\\SendQueuedMailable\":15:{s:8
:\"mailable\";O:22:\"App\\Mail\\EncryptedMail\":2:{s:
15:\"oneTimePassword\";s:6:\"123456\";s:6:\"mailer\";
s:7:\"mailgun\";}s:5:\"tries\";N;s:7:\"timeout\";N;s:
13:\"maxExceptions\";N;s:17:\"shouldBeEncrypted\";b:0;
s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"
chainConnection\";N;s:10:\"chainQueue\";N;s:19:\"
chainCatchCallbacks\";N;s:5:\"delay\";N;s:11:\"afterCommit\"
;N;s:10:\"middleware\";a:0:{}s:7:\"chained\";a:0:{}s:3
:\"job\";N;}"
}
}
Just like with the jobs and notifications, the oneTimePassword
property is visible in plain text in the data.command
field!
But we can update the mailable class to implement the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface:
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class SendOneTimePassword extends Mailable implements ShouldQueue, ShouldBeEncrypted
{
// ...
}
This would now result in the pending mailable's data being encrypted when stored in the queue store:
{
"uuid": "e1296554-44b3-4bbb-b5ff-daa6f1660861",
"displayName": "App\\Mail\\EncryptedMail",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "Illuminate\\Mail\\SendQueuedMailable",
"command": "eyJpdiI6Im1PQUZUWlFmMllYUnNLZmJ2cUxFTlE9PSIsInZhbHVlIjoiUG1SSkJ
kY1NpdmpsNTVhc0U3dHYzcXFabFUxdkw5blZQSlU4OGw5eHNCNy9DUjlhUFEzZl
V3UGFTRVpiNitSaGZFUElZN0xITEcwYnQzMFZtSGk0bGFVdW5GcWNBVlh2K0Vja
FA1dUFmcmVFa1RqNEhDSmthSVJ0c3RweUhlUEJRQTNzUWpmZHhtTVZxVGZSZER3
d1VvZURETFpEb2lPL1VENUhTTjU4eEY2Mk4vemhRL29RTVE4TGVQNklOazAwY1J
wOFRjMTUydVZZZmd4aWZCY2xQUUNvMmw4bXhhczgvYThCV1dnaENZaURFTWw1OG
kybEg2cFVYaDZSS3ZRMERKMzJZZDB4M1c0ZXN0bThJNG1oNlNrdVpGeUZmN2crM
Wl6c09oVkNIN2Y2QVN4dkNXM0hzMGh0N3pDakxpZWpmbjJ2VldHdVdPWWtKcnph
WGRPUW9POTdQN0syVXNWa0ZUa000SmdrelVFQ1hrUkNrYUV3SXhkcGJGamMwZEV
XSjRpOWJhZ25FL0NUZ0lpeERWcG9YWjNkT3ozeEJCVG5LTmVoNzB0bkVPeUs0dm
JxQ2VCRzhsVk42TGF1Y2djYWsxc0ZtQjdPbWtVanF3c3p4cjY5b3d6VTFZRkVPV
mI1SDlJbGRKeHN6Sy9BOTF1K0UrZnJvNjNja0JXME55ZlBNY1FCWkJ6U3BJbnVE
YkJzZFdVNFE1aHdCUDNBTzdva3RBdFkzeDA1WExGTlRacys1V01pNTNzOVU4U2R
ZYUduRHBVSE5lQ3FnSVBQZXVBb2VLSzlKVzVhSkJLaWZKS3gzZm5KUWR3UXRLND
0iLCJtYWMiOiI1NjEyZjljMmZjNjlmMWI3NmIzYjQxM2MwMmQyNWM0YmIxODg4Z
jNlNGM5ODAyOTk4YmRiYzYzOGZjNjZhYjU0IiwidGFnIjoiIn0="
}
}
Encrypting Laravel Listeners
Finally, we can also encrypt listeners using the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface.
Let's imagine we have this event that accepts a one-time password in the constructor:
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MyAwesomeEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*/
public function __construct(public readonly string $oneTimePassword)
{
//
}
// ...
}
We'll then have a queued listener that listens for the event:
namespace App\Listeners;
use App\Events\MyAwesomeEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class QueuedListener implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(MyAwesomeEvent $event): void
{
//
}
}
It's worth noticing that in this case, it's not actually the listener that directly contains the sensitive data. It's the event that contains the sensitive data.
We can dispatch the event like so (once again, notice the 123456
that we're passing as the OTP):
use App\Events\MyAwesomeEvent;
use Illuminate\Support\Facades\Event;
Event::dispatch(new MyAwesomeEvent('123456'));
Sure enough, if we were to inspect the data stored in the queue store for the pending listener, we'd see the following:
{
"uuid": "e395f426-1ae5-463b-bf27-6340528dc845",
"displayName": "App\\Listeners\\QueuedListener",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "Illuminate\\Events\\CallQueuedListener",
"command": "O:36:\"Illuminate\\Events\\CallQueuedListener\":20:{s:5:\"
class\";s:28:\"App\\Listeners\\QueuedListener\";s:6:\"
method\";s:6:\"handle\";s:4:\"data\";a:1:{i:0;O:25:\"App\\
Events\\MyAwesomeEvent\":1:{s:15:\"oneTimePassword\";s:6:\"
123456\";}}s:5:\"tries\";N;s:13:\"maxExceptions\";N;s:7:\"
backoff\";N;s:10:\"retryUntil\";N;s:7:\"timeout\";N;s:13:\"
failOnTimeout\";b:0;s:17:\"shouldBeEncrypted\";b:0;s:3:\"
job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"
chainConnection\";N;s:10:\"chainQueue\";N;s:19:\"
chainCatchCallbacks\";N;s:5:\"delay\";N;s:11:\"afterCommit
\";N;s:10:\"middleware\";a:0:{}s:7:\"chained\";a:0:{}}"
}
}
However, we can update the QueuedListener
class to implement the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface:
namespace App\Listeners;
use App\Events\MyAwesomeEvent;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class QueuedListener implements ShouldQueue, ShouldBeEncrypted
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(MyAwesomeEvent $event): void
{
//
}
}
As a result, the pending listener's data will now be encrypted when stored in the queue store:
{
"uuid": "f6e2d019-95b0-4385-9c8d-9004d998388c",
"displayName": "App\\Listeners\\QueuedListener",
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"maxTries": null,
"maxExceptions": null,
"failOnTimeout": false,
"backoff": null,
"timeout": null,
"retryUntil": null,
"data": {
"commandName": "Illuminate\\Events\\CallQueuedListener",
"command": "eyJpdiI6InJobm5sSTFxdnpueUR3T2k3eHF1NWc9PSIsInZhbHVlIjoiWi9aMGJ
ub0orNmtZbmVtWEVUT1l6T09XU2NvdUxxb3pSZW5PNFlibnFSTWNteHJtU255bN
STBXamlFVVl3UzgrRDBxSkw5UzdHbHF2QmdWenJBL3FPZitaQ3FMRURlcnBVbFB
U4em1tS0NmNWMreUM2R0hTMEwxN0Z2WFEwVnkzQmZjR0NjZ1pOSGt6TzlsRTUOH
MGRIZlFud0h4RzVFSmliUlBnamhrOCtMUWpFRW5JSlVvdTNnUE1OWGRleGhMENq
M4Uk0zdjE3SU8xbVRERFBGOE1meUlrSHZramhYSWZXNkdEanNBVFlDcVUy3NkeE
RGZCcVlDRlFSM09WNlNSdjRZSTJTUHZWdFhUU2thTXpYQUtZa2dPSlQ2SZrS21W
phZEo1S0h2QmFYRlVhR0wzVldEcmxJYzBqbG5HZFdRc25zU2xmNnNNVSIOHIrQ2
UXFJcDZFZ29LSTcxQThsV0l2S0l3S1RqcGtvRTVtWnZ4VUdwcTNvNjgQUpubjRr
lmZ3dCbGdjNkpzQTIyZ3A5ZnJmY2tZdU1JU3hQaUVISlM4aXJnNk1xC9HZk1QRE
Vk1VWGRvL0R0ek1RcURyc1hKZjY2UFZjVExkVm1NSHpSVnFNSGRLchOR1Jyc2Uz
RzSURGL09sUnZ1ekNMYnQ5b2dUL0dMMGdJU0JkN2MraFhPTlJrR2yMEMrRndOVW
RTFKZ0RPTFBidWJ6SlhJMnpheVQyanNvOUFEWnlhWk1QN1g1NHheEVhQmd1amVG
h4SjhhT0FrWnRDNXZIT1dncUdLY1hNMGRydWNyTi9KZjhtdVZEEtxN1BMd2hRMz
dGFvcE5MUElybngzOGtvZzBqSzZNSncrWnNBbDA0U0h1QkMvdBoUm93Wk9VT0Y3
FZM2Eya0xzaWxTK0hmSlJxa0JQa3RxeTAva2UxSWhYM2FyMmqZDJRNUhCbFFNVG
d2xMYXJoSiswU0FNcmVQRy9IIiwibWFjIjoiMTg4NjdhZjUY2MxMGIwZGRmNTgy
lkOTAxNDZjN2EwNWI1MGZjMjIyMmE5ZTNmYzg3NDdlNTg0TVlY2I0MyIsInRhZy
IiJ9"
}
}
Should I Encrypt My Laravel Jobs?
Encrypting your queued classes can be a great way to add an extra layer of security to your applications. It can help protect sensitive information from being exposed if someone were to access the queue store.
And the best part is that it's super easy to do (as we've seen above)! All you need to do is implement the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface in your queued classes.
However, it's worth noting that encrypting and decrypting data will add some overhead to your application. Now, I don't actually have any benchmarks to say how big or small this overhead is. It could potentially be so small that it's negligible. On the other hand, it could be something that has a noticeable impact on your application's performance, especially for larger applications.
If I manage to get any benchmarks, I'll be sure to update this article with the results.
But at a bare minimum, I'd recommend encrypting any queued classes that contain sensitive information. This could be things like passwords, API keys, social security numbers, etc.
If you do some experimenting and find that the overhead isn't too much of a performance hit, then you might want to consider encrypting all your queued classes just for consistency. But again, this is something you'd need to test and see how it affects your application. So it's not a one-size-fits-all answer.
Further Reading
If you're interested in finding out about other ways to protect sensitive information that's being passed around your application, you might also want to check out my "Redacting Sensitive Parameters in PHP" article.
It covers how to use PHP's built-in #[\SensitiveParameter]
to redact sensitive information from logs and stack traces.
Conclusion
Hopefully, this article has given a quick insight into how you can use the Illuminate\Contracts\Queue\ShouldBeEncrypted
interface to encrypt your queued Laravel jobs, notifications, mailables, and listeners for improved security.
If you enjoyed reading this post, I'd love to hear about it. Likewise, if you have any feedback to improve the future ones, I'd also love to hear that too.
You might also be interested in checking out my 220+ page ebook "Battle Ready Laravel" which covers similar topics in more depth.
Or, you might want to check out my other 440+ ebook "Consuming APIs in Laravel" which teaches you how to use Laravel to consume APIs from other services.
If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter.
Keep on building awesome stuff! 🚀
driesvints liked this article
Other articles you might like
Laravel Custom Query Builders Over Scopes
Hello 👋 Alright, let's talk about Query Scopes. They're awesome, they make queries much easier to r...
Access Laravel before and after running Pest tests
How to access the Laravel ecosystem by simulating the beforeAll and afterAll methods in a Pest test....
🍣 Sushi — Your Eloquent model driver for other data sources
In Laravel projects, we usually store data in databases, create tables, and run migrations. But not...
The Laravel portal for problem solving, knowledge sharing and community building.
The community