Chat with us, powered by LiveChat

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.

Launch PHP Websites and Applications in seconds through our 1-Click App Install Launch Now!

Create Token Based API Authentication in Symfony

Updated on July 18, 2017

4 Min Read
Reading Time: 4 minutes

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 code.

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

symfony authentication

In this Symfony authentication example, I will show you how you can work with Guard and authenticate users via API token(s). For the purpose of this article, I am assuming 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.

Create a User Class & Provider

To start user authentication in Symfony, I need to create a user entity class which 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 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;

   }

}

php hosting signup

Register the Provider in security.yml

The next step is to register the above made user provider in 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.

Symfony Guard Component

Guard authentication first introduced in symfony 2.8 and after that it’s now become a part of symfony core. Guard provides different layers of Symfony 3 authentication. With Guard, every step of the Symfony authentication process is handled by only one class: an Authenticator. This class will have to implement the provided GuardAuthenticatorInterface.

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

$ composer require symfony/security-guard

Creating An Authenticator Class

Now an authenticator class is needed which implements the GuardAuthenticatorInterface and extends the AbstractGuardAuthenticator. This class will read the api token in 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 with comments but If you want to learn more about Guard authentication method you can learn on symfony documentation page.

Configuring The Authenticator

To 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 to create custom and simple authentication system which help you to move out from pain of complex authentications. So in this article I have described you how to create a token based Symfony authentication in using Symfony Guard component.

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

Share your opinion in the comment section. COMMENT NOW

Shahroze Nawaz

Shahroze is a PHP Community Manager at Cloudways - A Managed PHP Hosting Platform. Besides his work life, he loves movies and travelling. You can email him at shahroze.nawaz@cloudways.com

Launch PHP websites without the worry of Server Management.

Pre-Installed Optimized Stack with Git, Composer & SSH

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

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

THERE’S MORE TO READ.