November 21, 2023 - 6 min

Symfony Notifications and Their Security


				
				

Marko Car

PHP Developer

blog cover image

In this article, you’ll learn more about enhancing Symfony backend applications with SMS and Slack notifications as well as fortifying security with phone number verification.


The development of the REST API itself, which is used for creating and retrieving data, is no longer enough. Modern backend applications have progressed, and through the integration of various services, they enrich the experience of use and allow you to enhance the usage of your application.


One of the ways in which we can expand our application is by using notifications. They can be sent and triggered for a variety of reasons: diverse reminders, delivery updates, emergency alerts, etc. The Symfony Notifier component provides sending notifications through different channels. This blog will show you how to send SMS or Slack notifications and how to verify the user’s phone number.


SMS Notifications


For supercharging Symfony applications with SMS notifications, Twilio takes the center stage as our primary tool, a robust platform designed for delivering real-time SMS notifications to mobile phones.

First, let’s include the necessary package. We do that with:


composer require symfony/twilio-notifier

Running this command will create a new notifier.yaml configuration file and add a new variable to the environment file.


TWILIO_DSN=twilio://ACCOUNT_SID:AUTH_TOKEN@default?from=FROM


As we can see, we need some data to fill in from our twilio account. Let’s head to Twilio website and register a new account. After logging in, we land on the homepage console. Under the account info section let’s take necessary data and copy these values to the .env file.


Twilio account


It’s time to send our first SMS using the Symfony application. Service method is presented. It takes two parameters: the message that we want to send and the phone number to which message will be sent.


/** 
* @throws TransportExceptionInterface
*/
public function sendSmsMessage(string $content, string $phoneNumber): SentMessage|null
{
$sms = new SmsMessage(
// the phone number to send the SMS message to
$phoneNumber,
// the content of the message that will be sent
$content,
);

return $this->texter->send($sms);
}

The send () method returns a SentMessage variable that contains information about the message ID and its original contents.


To test this method, we can use a simple console command that receives a message and the mobile number to send to.


<?php

namespace Core\Command;

use Core\Service\SmsNotificationService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class SendSmsNotificationCommand extends Command
{
public function __construct(private readonly SmsNotificationService $smsNotificationService)
{
parent::__construct();
}

protected function configure(): void
{
$this
->setName('app:send-sms-notification')
->setDescription('Send an SMS message')
->addArgument('content', InputArgument::REQUIRED, 'The content of the SMS message')
->addArgument('phoneNumber', InputArgument::REQUIRED, 'The phone number to send the SMS to')
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);

$content = $input->getArgument('content');
$phoneNumber = $input->getArgument('phoneNumber');

$this->smsNotificationService->sendSmsMessage($content, $phoneNumber);
$io->success('SMS message sent successfully.');

return Command::SUCCESS;
}
}

after running the command with:


php bin/console app:send-sms-notification


SMS sent successfully


The mobile phone received the message successfully.



Slack Notifications


This section will demonstrate how to send a message from a Symfony application to Slack in a simple way. This will help illustrate how those delightful Peakon surveys or notifications from Google Calendar find their way to your Slack.

The first step is to include the necessary package:


composer require symfony/slack-notifier


Running this command will add a new variable to the environment file.


SLACK_DSN=slack://TOKEN@default?channel=CHANNEL


To send messages on Slack, of course we first need a Slack workspace, a test one was created for the needs of the blog. The next step is to create a Slack app that will be assigned certain actions within our workspace. Once the app is created in the OAuth & Permissions section, assign scopes to it and then install it into Workspace. After installation, we will receive a Bot User OAuth Token that will allow us to link our backend application with the Slack workspace. Let’s retrieve the token and update the corresponding value in the environment variable.


More detailed installation instructions can be found in the official documentation. Adding Slack notifier also brings some additional configuration to the notifier.yaml file.


# config/packages/notifier.yaml
framework:
notifier:
chatter_transports:
general: '%env(SLACK_GENERAL_DSN)%'
random: '%env(SLACK_RANDOM_DSN)%'

Here we define transports and when sending a message, there is an option to choose what transport will be used. This allows us to control the Slack channel to which specific messages are sent. If not explicitly set, the message will be sent using the default transport, the first one configured.



Sending Slack messages from the Symfony application is then as simple as it gets. A service method is presented. It takes two parameters: the message and transport which will be used to send it.


/**
* @throws TransportExceptionInterface
*/
public function sendSlackMessage(string $content, string $transport): SentMessage|null
{
$message = (new ChatMessage($content))->transport($transport);
return $this->chatter->send($message);
}

It’s time to test sending a message to the general channel. For this purpose, a console command which calls the service method was created.


<?php

namespace Core\Command;

use Core\Service\SlackNotificationService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class SendSlackNotificationCommand extends Command
{
public function __construct(private readonly SlackNotificationService $slackNotificationService)
{
parent::__construct();
}

protected function configure(): void
{
$this
->setName('app:send-slack-notification')
->setDescription('Send a Slack message')
->addArgument('content', InputArgument::REQUIRED, 'The content of the message')
->addArgument('destination', InputArgument::REQUIRED, 'The Slack channel');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);

$content = $input->getArgument('content');
$destination = $input->getArgument('destination');

$this->slackNotificationService->sendSlackMessage($content, $destination);
$io->success('Slack message sent successfully.');

return Command::SUCCESS;
}
}

Let’s execute it with:


php bin/console app:send-slack-notification "Whatever the Q, We got the A." "general"

Slack message sent successfully


As shown in the picture, the message has reached the general channel successfully.


Received message on Slack


Importance of phone number verification


A phone number isn’t just any number, it’s a unique identifier linked to a person. Unlike email addresses that can be easily created and kept anonymous, phone numbers are usually associated with a person’s identity. This connection helps prevent duplication and fraud, making them essential for establishing trust, security, and responsibility in various applications.


It can be significant in a scenario that involves account recovery, or forgetting passwords. Having a phone number that is verified is a reliable method for recovering an account. After examining the benefits, let’s move on to implementing phone verification within the Symfony framework.


We must include a package that will help us with the verification process. Run:


composer require twilio/sdk

After that, construct a configuration that will enable us to automatically autowire the Twilio client into service class.


# config/services.yaml
services:
app.twilio_client:
class: Twilio\Rest\Client
arguments: ['%env(ACCOUNT_SID)%', '%env(AUTH_TOKEN)%']

Twilio\Rest\Client: '@app.twilio_client'

In order to use the verification service inside the app, we must also have the verify service token. The official documentation page provides more information on how to issue this token.


Now everything is ready to be utilized. The following is the implementation of the service that can be used for number verification.

Using the send verification code method, a unique code is sent via SMS to a mobile phone. The second method serves to check and verify the mobile number. Based on the number and unique code provided, it determines if the code sent to the specified phone number matches the given code.


<?php

namespace Core\Service;

use Twilio\Rest\Client;
use Twilio\Rest\Verify\V2\Service\VerificationCheckInstance;
use Twilio\Rest\Verify\V2\Service\VerificationInstance;

class SmsNotificationService
{

public function __construct(
private Client $twilioClient,
private string $verifyServiceSid
) {
}

public function sendVerificationCode(string $phoneNumber): VerificationInstance
{
// Generate a unique code for verification
return $this->twilioClient
->verify->v2->services($this->verifyServiceSid)->verifications
->create($phoneNumber, 'sms');
}

public function checkVerificationCode(string $phoneNumber, string $code): VerificationCheckInstance
{
// Check if the verify code corresponds to send one
return $this->twilioClient
->verify->v2->services($this->verifyServiceSid)->verificationChecks
->create(['Code' => $code, 'To' => $phoneNumber]);
}
}

Let’s perform the action of sending verification code.


2-factor-authentication


Let’s pass the code to the second method. A status attribute is included in an instance of the verification check that is returned. Successful verification is indicated when this status matches the approved state. That allows us to proceed with further actions such as setting the verified flag in the database.


if ($verificationCheckInstance->status === 'approved') {
// Take various actions here, suggested is to mark the user's phone as verified.
$user->setPhoneVerified(true);
}

Conclusion


We’ve seen how simple it is to set up and use notifications in Symfony. This blog post showcased Slack and SMS, but there are also other channels for sending notifications like Nexmo, Amazon SNS, LinkedIn, Telegram, Twitter and so on. We also demonstrated how to verify a mobile phone number in a safe way to ensure that communication remains trustworthy.


Give Kudos by sharing the post!

Share:

ABOUT AUTHOR

Marko Car

PHP Developer

Marko is a backend Symfony developer who works on various projects within Q. When he gets the chance, he likes developing his skills even further, and currently holds the Zend PHP Engineering Certificate as well as the AWS Certified Cloud Practitioner Certificate.