Sunday, 28 October 2018

Laravel Passport grant Flow for first-party apps

I'm using Laravel Passport to give access to some parts of my API to third-party apps.

But, I also use my own API through my own first-party Native Android App. So, I looked over the whole internet for the best practice in this case, but getting stuck to get to a conclusion.

Here are the possibilities I found :
1) I can follow the User Credential Password Grant Flow (see https://laravel.com/docs/5.7/passport#password-grant-tokens).
In this case I need to pass a client_secret and client_id to the authorization server. In order to keep them safe I can't write them in my mobile application's source code (APKs are decompilable...).

So, I have 2 choices :
1a) Proxyfying through my own server and inject the secret before calling the oauth endpoint :

$proxy = Request::create('/oauth/token', 'post', [
    'grant_type' => 'password',
    'client_id' => 1,
    'client_secret' => 'myownclientsecretishere',
    'username' => $username,
    'password' => $password
]);
$proxy->headers->set('Accept', 'application/json');
$response = app()->handle($proxy);

1b) Inject the secret when calling the oauth endpoint using a Middleware :

class InjectPasswordGrantSecret
{
    public function handle($request, Closure $next)
    {
        $request->request->add([
            'client_id' => 1,
            'client_secret' => 'myownclientsecretishere'
        ]);
        return $next($request);
    }
}

These are working examples, but they are also greedy in resources.. I tried to use apache benchmark on my local machine and I got something like 9 requests/second.

2) I can follow the Personal Access Grant (see https://laravel.com/docs/5.7/passport#personal-access-tokens).
This one doesn't look like a standard in OAuth2, it allows us to create a token through any custom route, just like this :

if (! auth()->attempt(compact('username', 'password'))) {
    return error_response(__('auth.failed'));
}
$user = auth()->user();
$token = $user->createToken(null)->accessToken;

Using apache benchmark I get better result (something like 30 requests/second).
But, token lifetime is not configurable by default and is set to 1 year (note that there are workarounds to get this lifetime configurable using a Custom Provider).
I am really wondering if this solution is meant to be used in a production environment.

Initially, I used JWT tymon lib (https://github.com/tymondesigns/jwt-auth) because I only had my own app. But now that I need to get it to work with first-party AND third-party apps, I thought that OAuth2 (through Laravel Passport) would be a good solution...

I hope someone can help me out with this, and explain what could be a good solution to get it to work securely and [not slowly] on production servers.



from Laravel Passport grant Flow for first-party apps

No comments:

Post a Comment