Passport: How to use for simple mobile app API authentication

Created on 10 May 2017  路  7Comments  路  Source: laravel/passport

I'm new to API world.

In my mind and based on internet research, I guess this is how basic API authentication works (please correct me if I'm wrong):

  • Client (like a mobile app), make a request to the server with username/email and password entered from mobile app
  • Server will validate those credentials and if they are correct, create an access token and send back in response
  • For all other subsequent requests, client will send that token in the request so that server can authenticate and process the request

Basically, I want to achieve exact above thing.

But as far as I know in Oauth2, you need to create a client on the API server to get the client id and client secret. And then you have to send those two along with other parameters in the request.

What I don't understand is the request parameters to get an access token:

https://laravel.com/docs/master/passport#password-grant-tokens

$http = new GuzzleHttp\Client;

$response = $http->post('http://your-app.com/oauth/token', [
    'form_params' => [
        'grant_type' => 'password',
        'client_id' => 'client-id',
        'client_secret' => 'client-secret',
        'username' => '[email protected]',
        'password' => 'my-password',
        'scope' => '',
    ],
]);

return json_decode((string) $response->getBody(), true);

I thought to just get an access token just email/username and password are enough parameters. So I'm confused about the extra parameters in the above request.

Do I have to first create a client on API server to get client_id and client_secret and then need to send them in the login request?
Do I need to create a separate client(client_id and client_secret) for each and every users of the app?

I read the entire doc but I didn't get that how can I use it to achieve what I want. I also read about the Oauth2 but it is a bit complicated for me.

Any help would be appreciated.

Thanks

Most helpful comment

If you ran the artisan command php artisan passport:install per the docs you should have already gotten two clients. You will find the id and secrets in the database for the entry that says password_client = 1. For me I don't use passport as a multi client auth server (yet) so I only need one client. I made a seeder that inserts the only password client I need (instead of running the artisan passport:install command).

        $client = ClientModel::find(1);

        if (!$client) {
            $client = new ClientModel();
        }
        $client->id = 1;
        $client->name = "Password Grant Client";
        $client->user_id = null;
        $client->secret = '';
        $client->redirect = '';
        $client->personal_access_client = 0;
        $client->password_client = 1;
        $client->revoked = 0;
        $client->save();

Then I have a middleware that I put in front of my custom authenticate route that fills in the oauth parameters automatically.

    public function handle($request, \Closure $next)
    {
        $convenienceData = [
            'grant_type' => 'password',
            'client_id' => 1,
            'client_secret' => '',
            'username' => $request->input('email'),
        ];

        $request->merge($convenienceData);

        $response = $next($request);

        return $response;

    }

And lastly my custom endpoint controller just extends AccessTokenController

class OauthController extends AccessTokenController
{

    public function oauthHandle(ServerRequestInterface $request)
    {

        $resp = $this->issueToken($request);
        // you can do other custom logic here
        return $resp;

    }
}

All 7 comments

If you ran the artisan command php artisan passport:install per the docs you should have already gotten two clients. You will find the id and secrets in the database for the entry that says password_client = 1. For me I don't use passport as a multi client auth server (yet) so I only need one client. I made a seeder that inserts the only password client I need (instead of running the artisan passport:install command).

        $client = ClientModel::find(1);

        if (!$client) {
            $client = new ClientModel();
        }
        $client->id = 1;
        $client->name = "Password Grant Client";
        $client->user_id = null;
        $client->secret = '';
        $client->redirect = '';
        $client->personal_access_client = 0;
        $client->password_client = 1;
        $client->revoked = 0;
        $client->save();

Then I have a middleware that I put in front of my custom authenticate route that fills in the oauth parameters automatically.

    public function handle($request, \Closure $next)
    {
        $convenienceData = [
            'grant_type' => 'password',
            'client_id' => 1,
            'client_secret' => '',
            'username' => $request->input('email'),
        ];

        $request->merge($convenienceData);

        $response = $next($request);

        return $response;

    }

And lastly my custom endpoint controller just extends AccessTokenController

class OauthController extends AccessTokenController
{

    public function oauthHandle(ServerRequestInterface $request)
    {

        $resp = $this->issueToken($request);
        // you can do other custom logic here
        return $resp;

    }
}

xparthx I was able to get access_token and use it after sending from angular
let data = {
"grant_type": "password",
"client_id": "2",
"client_secret": "MToEmN4nw7j4kqeMmzqPsM1MnyxDaQZdFAlh3akA",
"username": "[email protected]",
"password": "123456",
"scope": "*"
};

    return new Promise(resolve => {
        this.http.post(this.baseUrl + "/oauth/token", data, headers)
            .subscribe(res => resolve(res.json()));
    });

Maybe you can explain me where you store it for reuse in mobile app, or how you can reuse that token at a later time !?
Or if we will generate that tokens for 10 minutes life, than we have to put a cron to clean up older tokens ?

I solved this issue by using passports implicit grant token. Refer to documentation here

For those looking to bypass the full OAuth2 authentication flow and in situations where the client credentials cannot be securely stored, such as a mobile application, implicit grant tokens are best used

When i want all user only send username and password, you can try this:

use Laravel\Passport\Http\Controllers\AccessTokenController;

class SimpleController extends AccessTokenController
{
/*
.
.
.
*/

/**
     * @param ServerRequestInterface|\Zend\Diactoros\ServerRequest $request
     * @return \Illuminate\Http\Response
     */
    public function simpleIssueToken(ServerRequestInterface $request)
    {
        $getBody = $request->getParsedBody();
        $newBody = array_merge([
            'grant_type' => "password",
            'client_id' => 1,
            'client_secret' => "secret",
            'scope' => '*'
        ], $getBody);
        $newRequest = $request->withParsedBody($newBody);

        return parent::issueToken($newRequest);
    }
}

Is quite similar like rickshawhobo's solution

@rickshawhobo Is that the right way of doing it though? I need to implement this for Laravel/ Mobile app project, where mobile app users will be clients (one per user) and Laravel app is a server. Since I can't save client_id and client_secret anywhere on the mobile (security reasons and reset password reasons) I had to create a middleware which intercepts requests, looks up username in the oauth_clients database, fetches the client_id and client_secret and replaces it in the request, then passes it on.

Is there an easier way of implementing api login from mobile apps via Passport?

You'll have to send along the client_id and client_secret to passport can identify the client which you're sending your auth requests to.

Note: It is no longer best practice to use the Implicit Grant. Industry best practice recommends using the Authorization Code Grant with PKCE (Proof Key For Code Exchange) for native and browser-based apps.
I found this helpful: https://oauth2.thephpleague.com/authorization-server/which-grant/
and also: https://laravel.com/docs/6.x/passport#code-grant-pkce

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MarkVilludo picture MarkVilludo  路  3Comments

ghost picture ghost  路  3Comments

Adesubomi picture Adesubomi  路  4Comments

gbgelado picture gbgelado  路  3Comments

brryfrmnn picture brryfrmnn  路  3Comments