Finding user from OAuth2 accessToken using Laravel Passport

Laravel Oct 11, 2019

Once we stuck into the issue where one of our 3rd party application (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 were protected by auth:api middleware. Obviously we were using Laravel Passport package for OAuth2 Server implementation.

The issue was, accessToken was provided in request body of each API call instead of providing it in a request header! Laravel expects accessToken to be in request header to determine if  the request to be 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 result 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 request body and adding it as request header before it reaches to auth:api middleware, but it didn't worked at all as expected :(

With 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 Passport package which is perfectly architectured to extend and to understand.

Finally we managed to get user from accessToken by abstracting piece of code from Passport package, which is in 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 public key (which we generated before creating the app or client in installation steps of Passport) the accessToken is parsed and verified. If 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 better solution for such situation, but this solution works perfectly when your routes are not protected with auth:api but requests has accessToken and you want to determine associated user.

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