Finding user from OAuth2 accessToken using Laravel Passport

Photo by ZSun Fu on Unsplash

Finding user from OAuth2 accessToken using Laravel Passport

Once we stuck into the issue where one of our 3rd party applications (Alexa App) was using Implicit Grant Tokens to authenticate the users and it was consuming some special APIs of one of the Laravel application which was protected by auth:api middleware. Obviously, we were using the Laravel Passport package for OAuth2 Server implementation.

The issue was, that accessToken was provided in the request body of each API call instead of providing it in a request header! Laravel expects accessToken to be in the request header to determine if the request is permitted or not when using auth:api as middleware.

We wanted to determine the user who invoked the Alexa skill (API), so we can return results specifically for that user. E.g. Pending tasks of User X who is calling the API.

We tried multiple ways to transform the incoming request by plucking accessToken from the request body and adding it as a request header before it reaches to auth:api middleware, but it didn't work at all as expected :(

With the context of incoming we were only having user's accessToken to determine the associated user in our application and in Passport, there is no easy approach to retrieve the associated user from accessToken. But huge thanks to the Passport package which is perfectly architectured to extend and to understand.

Finally, we managed to get user from accessToken by abstracting a piece of code from the Passport package, which is in the following Trait.

<?php

namespace App\Traits;

use Laravel\Passport\Passport;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Rsa\Sha256;

trait CustomPassportTrait
{
    public function parseToken($accessToken)
    {
        $key_path = Passport::keyPath('oauth-public.key');
        $parseTokenKey = file_get_contents($key_path);

        $token = (new Parser())->parse((string) $accessToken);

        $signer = new Sha256();

        if ($token->verify($signer, $parseTokenKey)) {
            $userId = $token->getClaim('sub');

            return $userId;
        } else {
            return false;
        }
    }
}

parseToken() gets accessToken as input and using the public key (which we generated before creating the app or client in the installation steps of Passport) the accessToken is parsed and verified. If the token is verified successfully, parseToken() returns the associated user's ID from which we can find out the user in our application.

There would be a better solution for such a situation, but this solution works perfectly when your routes are not protected with auth:api but requests have accessToken and you want to determine the associated user.

That is it! This is my first blog post, hope it is useful. Would love to know your thoughts on this @twitter.