Ezrab_'s avatar

Laravel Passport Guide

I'm trying to find a good trustworthy guide to setup laravel with react. Does anyone know where to find such guide. I would like to know how to set it up and use it to:

  1. Register users
  2. Log users in
  3. Define gates

I know people will tell me to read the official docs, but they are a little bit hard for me to understand with implementing these features. So any guides that are trustworthy would be very much appreciated.

0 likes
6 replies
Exotelis's avatar

I'd say it depends on what you which grant type you want to implement. Can you go a bit more in details?

Ezrab_'s avatar

Yeah I want to use the password grant_type I think.

I have for my frontend a React App running on one server

And for my backend I have this Laravel app running. And I want to use Laravel's power to do the following:

  • register
  • login
  • define gates
  • automatically request new access token if it expires via the refresh token

I hope this clears it up

Exotelis's avatar

Ok, maybe this will help you. The frontend framework doesn't really matter.

Basically you just have to follow a couple of simple steps:

  • Install passport: composer require laravel/passport
  • Run migrations: php artisan migrate
  • Create keys and clients: php artisan passport:install

The install command will create a public and a private key. Please keep the private key private, that means whatever you do, don't place the key in the public folder or anywhere else users can have access to. It is also going to create two clients. A client is more or less a gateway to get an access token. One of the clients is the personal client, this one can be used by any authenticated user to generate personal token. This is important when your users want to call you api directly without using your react frontend. The other one is the password client. That one can be used to implement the password grant type ;) There are some other types of clients, but they are not really important for your plans, unless you want to create tokens that are not assigned to a user etc.

The command will print the client ids as well as the client secrets to the console. I suggest storing those information either in a config file or your .env file. e.g.

OAUTH_PERSONAL_CLIENT_ID=1
OAUTH_PERSONAL_CLIENT_SECRET=5Q2HnWKkP5D2foWmfPGm4XFBkpPTncjYgOwYRrzt
OAUTH_PASSWORD_CLIENT_ID=2
OAUTH_PASSWORD_CLIENT_SECRET=aE5HCnORF6S9q83QDeV43Xcg2cVaZBAMT84m3ysm

Add the trait HasApiTokens to your User model

Next, you should call the Passport::routes method within the boot method of your AuthServiceProvider. Also add this to your config/auth.php

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

Once this is done, you can use Postman or any other client that can send api requests, and try if everthing is working. Just send a request to <yourapiendpoint>/token with the following body:

grant_type     password
client_id      2
client_secret  aE5HCnORF6S9q83QDeV43Xcg2cVaZBAMT84m3ysm
username       username
password       password
scope          *

This should return an access and refresh token.

You don't need Oauth to register users. I assign every user a default user role on registration. Those roles have different permissions, which I use as scopes for oauth. Tokens will authenticate a user, but scopes will authorize a user. That means that I don't use gates, but when the user signs in, I get the users permissions and set them as the scope. Oh btw the * means that this user has any permissions. The scope could be something like:

scope ['user-write', 'users-read', 'users-delete', 'comments-read']

You can then use the passport middleware to check for permissions:

'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,

I hope this will help you to get started ;)

Ezrab_'s avatar

First of all I'd like to thank you very much for your time and effort in your answer. Now some questions.

  • When you register a user doesn't the user get an access_token, and if not how do you log the user in? Seems like a bad user experience to let the user log in with the credentials they just filled in.
  • How do you validate that the token is still valid and if not how do you give them a new one?
  • Aren't you using any custom Controllers to handle the registration and login part? Because that's what I see a lot on the internet when looking at how other people implement passport.

Thanks in advance! :-)

Exotelis's avatar
  • When you register a user doesn't the user get an access_token, and if not how do you log the user in? Seems like a bad user experience to let the user log in with the credentials they just filled in.

hmm not necessarily. Of course you can do this - I'd like to wait until the email has been verified. But that's a implementation detail :) I you have seen the video, the guy explains how to keep the client secret hash private. Basically you add a resource that just forwards the request to the oauth token resource. I added a resource called auth to sign the user in and in the AuthController@login issue the token. In my code it looks like that:

// AuthController@login
$permissions = $this->user->role->permissions->pluck('slug');
$http = new Client;

// Request forwarding
$response = $http->post(url(apiPrefix() . '/oauth/token'), [
    'json' => [
        'grant_type' => 'password',
        'client_id' => env('OAUTH_PASSWORD_CLIENT_ID'),
        'client_secret' => env('OAUTH_PASSWORD_CLIENT_SECRET'),
        'username' => $request->username,
        'password' => $request->password,
        'scope' => $permissions
    ],
]);

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

Note: I'm using guzzle to send the request to my url(apiPrefix() . '/oauth/token') resource. Of course you have to replace the url with yours ;) You could call the token resource from you auth/register resource to issue a token. Keep in mind that you don't want to store the client secret in your javascript frontend code. So, when the registration was successful you can of course get the token immediately. As I said, that's an implementation detail :)

  • How do you validate that the token is still valid and if not how do you give them a new one?

The validation is done by Oauth you don't have to take care about that part. If the token is expired you could use the refresh token to get a new access token. But I haven't implemented this yet, still on my todo list as well :-) I'm not quite sure yet how and where I want to store the refresh token. Btw just storing the access token in the local storage makes it vulnerable to xss attacks. Peter Locke is talking about this in his article

  • Aren't you using any custom Controllers to handle the registration and login part? Because that's what I see a lot on the internet when looking at how other people implement passport.

I do use a separate controller. Especially to keep the client secret secure.

Ezrab_'s avatar

Thanks again for your reply!

So I read some articles on where to store the access_token. One article pointed out that it would be best to put the token crypted in a cookie.

What do you think is the best way to store the token and where should I start when writing the logic on where to store it the token?

Looking forward to hear back from you :-)

Please or to participate in this conversation.