Back to blog

DeltaBlue

Authentication API Client

x min read

Let an API use the Json Web Token to retrieve user information.Published on 10/21/2018Authentication API Client

In the previous post we have setup an authentication API and we have added the refresh-token feature. Now it's time to let our clients use the received JWT to retrieve user information.

Clients can of course be written in all languages. To focus on the logic more then the code itself, this client is another symfony 4 application.

At it's most basic form, clients just need to know if the JWT is valid or not. Therefore, the only thing we need is the JWT Public key from the Authentication API.

This means you can use composer require lexik/jwt-authentication-bundle again, but with a minor difference in configuration, as the client will only validate the JWT Token, but will not generate a JWT token. No need in generating a new private key, or setting it in the configuration.

Configuration for lexik jwt:

lexik_jwt_authentication:
    private_key_path: ""
    public_key_path: "%kernel.project_dir%/%env(JWT_PUBLIC_KEY_PATH)%"
    pass_phrase: "%env(JWT_PASSPHRASE)%"

We need a user entity, so let's use the default JWTUser, to keep this as simple as possible.

Setup security.yaml:

security:
    providers:
        jwt_user_provider:
            lexik_jwt:
                class: Lexik\Bundle\JWTAuthenticationBundle\Security\User\JWTUser
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            provider: jwt_user_provider
            stateless: true
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator

And there you have it. When a user or client connects to this API using JWT, the API can check if the user has been validated by the authentication API, and can even get it's id and roles. Easy peasy!

Of course this setup is VERY basic. You can add more user details to your JWT token, such as email, username, first & lastname etc, but always bare in mind not to overload your JWT tokens with data that is irrelevant for simple authentication.

If you do add information to the JWT, you can add an extra User Entity to your API Client ( and replace the JWTUser class in configuration with your custom user). That user should of course implement the JWTUserInterface and UserInterface, and have a createFromPayload method to decode the JWT into the user Entity.

In the case of a closed ecosystem, where users are actually always the same entity, it would be advisable to move the user Entity, with its serialization to a dedicated bundle, so you can serialize the user into the JWT in the authentication API, and deserialize the JWT back into the user Entity on the client side. Unfortunatly, deserialization is not so simple.


To deserialize JWT data into a User entity, you will need a custom UserProvider and a custom authenticator. The Authenticator would look something like :

class TokenAuthenticator extends JWTTokenAuthenticator
{
    /**
     * Loads the user to authenticate.
     *
     */
    protected function loadUser(UserProviderInterface $userProvider, array $payload, $identity)
    {
        if ($userProvider instanceof UserProvider) {
            return $userProvider->loadUserByUsername($identity, $payload);
        }

        return $userProvider->loadUserByUsername($identity);
    }
}

and the userprovider:

class UserProvider implements UserProviderInterface
{
    /**
     * @var SerializerInterface
     */
    private $serializer;

    /**
     * UserProvider constructor.
     * @param SerializerInterface $serializer
     */
    public function __construct(SerializerInterface $serializer)
    {
        $this->serializer = $serializer;
    }

    public function loadUserByUsername($username, array $payload = [])
    {
        if (isset($this->cache[$username])) {
            return $this->cache[$username];
        }
        $this->cache[$username] = $this->serializer->deserialize(json_encode($payload), User::class, 'json', ['groups' => ['public']]);
        return $user;
    }

Don't forget to pass the serializer to the UserProvider in services.yaml:

App\Security\UserProvider:
    arguments:
        - "@serializer"

So, final state: Users or clients can request a JWT token from the Authentication API and client API's can check if the JWT Token is valid AND reconstruct the user entity. Mission accomplished.

The authentication API as it is now is of course not very useful. Next step would be to add calls so clients can create, update, delete or fetch user information. Stay tuned for more.

Let's talk!

Have a question, need advice, or just want to learn more about what we offer? Our team is here to help—whether you're exploring solutions, planning your next move, or already deep into a project.

We'll connect you with the right experts to give you practical, honest input tailored to your situation. No pressure, no hard sell—just a genuine conversation about how we can support your goals.

From technical questions to partnership opportunities, we're all ears. Drop us a line and let's see where we can make a difference.

Contact us