First, let's answer the basic question - What is User Authentication?
User authentication is a process that allows an application to verify the identity of someone. Each user is required to log in to the system to access an application. The user supplies the username of an account and a password if the account has one (in a secure system, all accounts must either have passwords or be invalidated). If the password is correct, the user is logged in to that account; the user acquires the access rights and privileges of the account.
Now, What is Laravel Passport?
APIs typically use tokens to authenticate users and do not maintain session state between requests. Laravel makes API authentication a breeze using Laravel Passport, which provides a full OAuth2 server implementation for your Laravel application in a matter of minutes. Passport is built on top of the League OAuth2 server that is maintained by Alex Bilbie.
If a particular user is authenticated, the token that was generated during login will be stored to seamlessly provide API access to the user until the token is explicitly revoked during the logout.
We'll now create a public API endpoint Login
and a protected API endpoint Logout
for logging in and out users in a Laravel application.
What is a public API endpoint?
A public API endpoint is available for any users of the web. Take Login
as an example. A login should be available for everyone in order to login into the application.
What is a protected API endpoint?
A protected API endpoint will only be available for the authenticated users. Take Logout
as an example. An account can be logged out only by a legitimate user.
Let's set up the application.
Before installing Laravel, make sure that you have Apache up and running with MySql and PHP V7.2.
We'll need Composer to install Laravel in our system. Composer is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.
Composer can be either globally installed or locally installed based on your requirement. We'll install it locally now.
Open a suitable directory and run the following command in your terminal -
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
This will create a composer.phar
file in the directory you've chosen. Now, let's install our Laravel Application using the following command-
php composer.phar create-project --prefer-dist laravel/laravel laravel-passport
After installation, create a database and let's name it as passport
and open the application in your favorite editor. I prefer Code ❤️. Don't forget to install the composer again inside your project if you have installed it locally before.
Environent Configuration
It is often helpful to have different configuration values based on the environment where the application is running. For example, you may wish to use a different cache driver locally than you do on your production server.
To make this a cinch, Laravel utilizes the DotEnv PHP library by Vance Lucas. In a fresh Laravel installation, the root directory of your application will contain a .env.example
file. If you install Laravel via Composer, this file will automatically be renamed to .env
. Otherwise, you should rename the file manually.
Now, open the .env
file and update the following -
APP_URL=http://localhost
-> APP_URL=http://localhost/laravel-passport/public
DB_DATABASE=homestead
-> DB_DATABASE=your database name here i.e passport
DB_USERNAME=homestead
-> DB_USERNAME=your db username
DB_PASSWORD=secret
-> DB_PASSWORD=your db password
Let's install Passport
To get started, install Passport via the Composer package manager:
php composer.phar require laravel/passport
After install successfully Passport package in our application we need to set their Service Provider. so, open your config/app.php
file and add following provider in it.
Now, the Passport service provider registers its own database migration directory with the framework, so you should migrate your database after registering the provider. The Passport migrations will create the tables your application needs to store clients and access tokens.
Database: Migrations
Migrations are like version control for your database, allowing your team to easily modify and share the application's database schema. Migrations are typically paired with Laravel's schema builder to easily build your application's database schema. Laravel comes with a default users table
migration. So, we need not write any migration for this application since we'll be using only the email and password for authentication.
To migrate the users and the other passport tables, run the following artisan command:
php artisan migrate
Next, you should run the passport:install
command. This command will create the encryption keys needed to generate secure access tokens. In addition, the command will create "personal access" and "password grant" clients which will be used to generate access tokens:
php artisan passport:install
After running this command, add the Laravel\Passport\HasApiTokens
trait to your App\User(Location - app\User.php)
model. This trait will provide a few helper methods to your model which allow you to inspect the authenticated user's token and scopes:
Next, you should call the Passport::routes
method within the boot method of your AuthServiceProvider(Location - app\Providers\AuthServiceProvider.php)
. This method will register the routes necessary to issue access tokens and revoke access tokens, clients, and personal access tokens:
Finally, in your config/auth.php
configuration file, you should set the driver
option of the api
authentication guard to passport
. This will instruct your application to use Passport's TokenGuard
when authenticating incoming API requests:
Now, let's write a controller for login and logout.
Run php artisan make:controller AuthenticationController
. This will create a AuthenticationController.php
file in app\Http\Controllers
Login
The basic logic behind login will be to find and retrieve the record with the help of the email
value that comes with the request. After retrieval, if the password that came in the request matches the password of the retrieved record - we will generate a token and send it as a response with the 200 status code. If the password mismatch then we'll send the appropriate error message with 422 status code.
If there is no user found with the request email, the same procedure is followed like the password mismatch scenario.
Logout
The logic for logout is to retrieve the token from the request header. Then we will explicitly revoke the token.
Our final controller will look like the following:
Routes
All Laravel routes are defined in your route files, which are located in the routes directory. We'll use api.php
to define our API routes. We'll define two routes, namely - login and logut. Remember, login is a public route and logout is a private route. The route file will now look like the following:
Testing our API using Postman
Postman is a platform that supports and enhances API development.
Before testing, add a record to your users table to test our API. Also, make sure that the storage
and bootstrap/cache
directory of the application is writable.
Testing login - POST http://localhost/laravel-passport/public/api/login
Testing logout - GET http://localhost/laravel-passport/public/api/logout
Now, copy the token and set it as header.
Feel free to check out the final codebase
Top comments (18)
I am trying to implement laravel passport on laravel 6. But I am getting an error.
Login and registration are ok. But I am getting an error when trying to fetch(authentic) pages.
The error is here pastebin.com/1M4iC3u5
My api.php
I don't know how you have set up the flow but here is something that should probably work.
Inside the BrandController add this to the constructor.
Next, the index function inside the controller should look like this:
Then use the Route directly as:
Thanks a lot
Laravel Passport is definitely the best option for api token authentication in Laravel based apps. It automatically generates api token in Laravel apps. This make it easy to configure and efficient to use in your apps.
That's why I wrote the tutorial. 😉
Hi,
Suppose I want to validate this condition while login a user using API
$aCredential = ['username' => $userName, 'password' => $password, 'user_type' => 1, 'status' => 1];
in this case do we need to separately validate each data rather than
if(Auth::attemp(aCredential))
In laravel 5.5, if you use passport attempt() will trigger error - function does not exits. So what will be the solution?
Awesome article! I found it super helpful.
I did have a question for you though. In your logout function, you go through the following steps:
1) Get token from the header
2) Parse token to get the id
3) Retrieve token from user tokens using said id
4) Take this retrieved token, and revoke it.
I wrote my logout function differently as follows
$request->user()->token()->revoke();
1) Grab the user from the request
2) Grab the current toke from user
3) Revoke the token taken from the user
I chose not to use the id at all. My question is should I be using the id? Is there ever a time where the token I'm logging out is not going to be the token assigned to the current user?
Your authentication controller looks more readable/clearer than others I find in other articles. But maybe because I don't have prior knowledge of OAuth. Therefore I should first read the fundamental concepts explained in oauth2.thephpleague.com/ and even in tools.ietf.org/html/rfc6749, before I can proceed to code using Laravel Passport. Now, I know why Laravel documentation suggest that I should get familiar with OAuth before continuing. :)
Without good knowledge in OAuth, I feel I will only be able to copy paste code from others.
I can see you use Password Grant in this example from your AuthenticationController. But when I compare with what I read in Laravel documentation : laravel.com/docs/7.x/passport#requ..., I wonder how you get to use your code for issuing access token with Password Grant flow.
I know the User model uses HasApiTokens trait that has createToken method. But there is no clue, either in that HasApiTokens trait or in your code which specifies sufficient parameters usually required for Password Grant, i.e client_id and client_secret.
Maybe I missed something, but where in your code those parameters for Password grant are supplied for requesting access token ?
As as comparison, this is code snippet I find in other article :
We see it also includes /oauth/token route for requesting access token as always mentioned in Laravel documentation.
Thank you, This helped me so much!
Happy about that.
hey thks for your great tutorial!
how do you then link this to your front end in vue.js for example?
i'm quite new to APIs
cheers
No linking required. Call the appropriate API calls.
if someone has issue to velidate password, try this:
try replacing the if statment with password by
'if(Hash::check($request->password, $user->password)) {//...}'
How would you approach if you have the get the user details from a lumen endpoint?