This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

📣 Try the fastest hosting platform with pay-as-you-go pricing & 24/7 expert support! MIGRATE NOW →

How to Create Token Based API Authentication in Symfony

Updated on March 13, 2024

5 Min Read

In the prior installment of this series, I wrote about creating a REST API in Symfony. I used HTTP codes with API responses and threw exceptions on bad response codes.

What if you want to apply token-based Symfony authentication and authenticate users through an API key? Symfony provides a straightforward solution in the form of a Symfony Guard authentication bundle. This bundle works with API keys and implements methods to handle Symfony user authentication and their credentials.

How to Authenticate Users via API Token(s)

We will learn to work with Guard and authenticate users via API token(s). I assume that you have already launched a PHP stack server and application on Cloudways, which is widely known for its best PHP hosting. For help on this prerequisite, check out this guide on installing Symfony on Cloudways.

1) Create a User Class & Provider

To start user authentication in Symfony, I must create a user entity class that implements UserInterface and a user provider. Symfony authentication process depends on the UserProvider. When the user hits the submit button, the user-provider values are checked. After this, further verification of the password takes place.

Following is the entity code:

<?php

namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**

* @ORM\Entity

* @ORM\Table(name="user")

*/

class User implements UserInterface

{

   /**

    * @ORM\Id

    * @ORM\GeneratedValue

    * @ORM\Column(type="integer")

    */

   private $id;

   /**

    * @ORM\Column(type="string", unique=true)

    */

   private $username;

   /**

    * @ORM\Column(type="string", unique=true)

    */

   private $email;

   /**

    * @ORM\Column(type="string")

    */

   private $password;

   /**

    * @ORM\Column(type="json_array")

    */

   private $roles = array();

   /**

    * @ORM\Column(type="string", unique=true)

    */

   private $apiToken;

   public function getId()

   {

       return $this->id;

   }

   public function getUsername()

   {

       return $this->username;

   }

   public function setUsername($username)

   {

       $this->username = $username;

   }

   public function getEmail()

   {

       return $this->email;

   }

   public function setEmail($email)

   {

       $this->email = $email;

   }

   public function getPassword()

   {

       return $this->password;

   }

   public function setPassword($password)

   {

       $this->password = $password;

   }

   /**

    * Returns the roles or permissions granted to the user for security.

    */

   public function getRoles()

   {
       $roles = $this->roles;

       // guarantees that a user always has at least one role for security

       if (empty($roles)) {

           $roles[] = 'ROLE_USER';

       }

       return array_unique($roles);

   }

   public function setRoles($roles)

   {
       $this->roles = $roles;

   }

   /**

    * Returns the salt that was originally used to encode the password.

    */

   public function getSalt()

   {
       return;

   }

   /**

    * Removes sensitive data from the user.

    */

   public function eraseCredentials()

   {

       // if you had a plainPassword property, you'd nullify it here

       // $this->plainPassword = null;

   }

   /**

    * @param string $apiToken

    */

   public function setApiToken($apiToken)

   {

       $this->apiToken = $apiToken;

   }

}

First PHP Website Migration Is Free At Cloudways

Cloudways Engineers can migrate your website Flawlessly

2) Register the Provider in security.yml

The next step is registering the above-made user provider in the security.yml file. To do that, add the following code:

providers:

       api_key_user_provider:

           entity:

               class: AppBundle:User

               property: apikey

I have done it here now. Before creating an authenticator class, let’s install Guard first.

3) Symfony Guard Component

Guard authentication was first introduced in Symfony 2.8 and has become part of Symfony core. Guard provides different layers of Symfony 3 authentication. With Guard, every Symfony authentication process is handled by only one class: an Authenticator. This class will have to implement the provided GuardAuthenticatorInterface.

However, Composer is still the preferred way to install Guard in Symfony. Install with the following command:

$ composer require symfony/security-guard

4) Creating An Authenticator Class

An authenticator class is needed to implement the GuardAuthenticatorInterface and extend the AbstractGuardAuthenticator. This class will read the API token in the header request and find the respective user. Create a new file: src/AppBundle/Security/TokenAuthenticator.php

namespace AppBundle\Security;



use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;


class TokenAuthenticator extends AbstractGuardAuthenticator

{

   /**
    * Called on every request. Return whatever credentials you want to
    * be passed to getUser(). Returning null will cause this authenticator
    * to be skipped.
    */

   public function getCredentials(Request $request)

   {
       if (!$token = $request->headers->get('X-AUTH-TOKEN')) {

           // No token?

           $token = null;

       }

       // What you return here will be passed to getUser() as $credentials

       return array(

           'token' => $token,

       );

   }

   public function getUser($credentials, UserProviderInterface $userProvider)

   {
       $apikey = $credentials['token'];

       if (null === $apikey) {

           return;

       }
       // if null, authentication will fail

       // if a User object, checkCredentials() is called

       return $userProvider->loadUserByUsername($apikey);

   }

   public function checkCredentials($credentials, UserInterface $user)

   {
       // check credentials - e.g. make sure the password is valid

       // no credential check is needed in this case



       // return true to cause authentication success

       return true;

   }

   public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)

   {

       // on success, let the request continue

       return null;

   }

   public function onAuthenticationFailure(Request $request, AuthenticationException $exception)

   {

       $data = array(

           'message' => strtr($exception->getMessageKey(), $exception->getMessageData())

           // or to translate this message

           // $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())

       );

       return new JsonResponse($data, Response::HTTP_FORBIDDEN);

   }

   /**

    * Called when authentication is needed, but it's not sent

    */

   public function start(Request $request, AuthenticationException $authException = null)

   {
       $data = array(

           // you might translate this message

           'message' => 'Authentication Required'

       );

       return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);

   }

   public function supportsRememberMe()

   {
       return false;

   }

}

The authentication methods are explained in the comments, but if you want to learn more about the Guard authentication method, you can learn about it on the Symfony documentation page.

5) Configuring The Authenticator

configure the authenticator, I need to update the firewall:

security:
   # ...
   firewalls:
       # ...
       main:
           anonymous: ~
           logout: ~
           guard:
               authenticators:
                   - AppBundle\Security\TokenAuthenticator

After that, register the authenticator as a service in service.yml:

services:
   api_key_authenticator:
       class: AppBundle\Security\TokenAuthenticator
       arguments: ["@router"]

That’s it finally, everything is done now. To check the response, you can use curl to request it.

 curl -H "X-AUTH-TOKEN: username" http://your_app_url

You will be authenticated and redirected to the homepage.

You might also like How To Implement User Authentication In Symfony Using Auth0

Final Words

Guard allows you to create a custom and simple authentication system that helps you to move out from the pain of complex authentications. So, in this article, I describe how to create a token-based Symfony authentication using the Symfony Guard component.

If you have any questions or queries, you can comment below.

Q. How do I authenticate API requests?

You can authenticate API requests in Symfony using its built-in authentication system. Configure authentication methods such as token-based authentication or OAuth2 to ensure secure access to your API endpoints.

Q. How does Symfony authentication work?

Symfony authentication works by integrating security features into your application’s routing and controllers. You can use Symfony’s authentication component to authenticate users via various methods like HTTP basic, form login, or JWT tokens, ensuring robust security for your API.

Q. How to do API key authentication?

You can implement API key authentication in Symfony by creating a custom authentication provider or using Symfony bundles tailored for API key authentication. Secure your API endpoints by requiring clients to include a valid API key in their requests for authorization.

Q. What is the best authentication for API?

The best authentication for API often depends on your project’s specific requirements and security needs. However, Symfony provides versatile authentication options such as token-based authentication, OAuth2, and API key authentication, allowing you to choose the method that best suits your application’s architecture and security standards.

Share your opinion in the comment section. COMMENT NOW

Share This Article

Shahroze Nawaz

Shahroze is a PHP Community Manager at Cloudways - A Managed PHP Hosting Platform. Besides his work life, he loves movies and travelling.

×

Get Our Newsletter
Be the first to get the latest updates and tutorials.

Thankyou for Subscribing Us!

×

Webinar: How to Get 100% Scores on Core Web Vitals

Join Joe Williams & Aleksandar Savkovic on 29th of March, 2021.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Want to Experience the Cloudways Platform in Its Full Glory?

Take a FREE guided tour of Cloudways and see for yourself how easily you can manage your server & apps on the leading cloud-hosting platform.

Start my tour

CYBER WEEK SAVINGS

  • 0

    Days

  • 0

    Hours

  • 0

    Mints

  • 0

    Sec

GET OFFER

For 4 Months &
40 Free Migrations

For 4 Months &
40 Free Migrations

Upgrade Now