Mobile Applications and SPAs(Single Page Applications) are extremely common clients for most modern software products. They typically retrieve data from some RESTful API service and display that data to the user. Even though RESTful APIs offer an easy way to create flexible and scalable systems, you’ll often want to protect data from unauthenticated users. A common way to do this is using JWT. In this tutorial, we’ll go over adding JWT authentication to Laravel. You can find the GitHub project here and related video courses here.

Project Setup

One of the first things that we should do is create a new Laravel project. Run the below command in your terminal.

laravel new auth-demo

Once the project is created, make sure to generate your application keys.

php artisan key:generate

Add Laravel JWT Package

The most common JWT package for Laravel happens to be Passport. It offers the ability to add JWT authentication with multiple OAuth flows. For this tutorial, we’ll be using the personal access token retrieved from our own custom route. This skips requiring redirects and having callbacks.

Let’s add passport to our composer.json file using composer require.

composer require laravel/passport

This will add and automatically register passport to our Laravel project.

Laravel Database Migrations

To finish install passport and have our required tables for our user and database, we will want to add our migrations. In your terminal, run your migration command.

php artisan migrate

Configure Passport

To full install passport run the below command in your terminal. It will add the clients for both personal access tokens and the password OAuth Grant.

php artisan passport:install

Now inside of your AuthServiceProvider.php file, add your routes Passport

public function boot()
    {
        $this->registerPolicies();
        Passport::routes();

        Passport::tokensExpireIn(now()->addDays(15));

        Passport::refreshTokensExpireIn(now()->addDays(30));
        //
    }

Also configure you config/auth.php file to you passport for you api authentication.

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

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

Add JWT to Laravel User Model

The next step is to make sure that your User Model can be used to create JWT.  Inside of your User.php Model, import Passport and has the trait for API Tokens.

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

Creating Custom Laravel JWT Token Endpoints

In order to create our users and retrieve their tokens, we’ll have to create a UserController.php file.

Inside of that controller, we will want to do 4 things. Register Users, Login Users, show that users detail and log them out.

Laravel JWT User Registration

Let’s start off by registering the users

public function register(Request $request) 
    { 
        $validator = Validator::make($request->all(), [ 
            'name' => 'required', 
            'email' => 'required|email', 
            'password' => 'required', 
            'c_password' => 'required|same:password', 
        ]);
        if ($validator->fails()) { 
            return response()->json(['error'=>$validator->errors()], 401);            
        }
        $input = $request->all(); 
        $input['password'] = bcrypt($input['password']); 
        $user = User::create($input); 
        $success['token'] =  $user->createToken('MyApp')-> accessToken; 
        $success['name'] =  $user->name;
        return response()->json(['success'=>$success], $this-> successStatus); 
    }

In this code, we validate the user and make sure that their email address is unique. Then we make sure that the password is valid. If the validation fails, we return a 401 error. After that, we use bcrypt to hash the user’s password and then create the user. We create an access token and then return that token to the user upon the user being registered.

Inside of our api.php file for our routes, we will add the route for that controller method.

Route::post('register', 'API\UserController@register');
Laravel JWT User Registration.

Laravel JWT User Registration.

Laravel JWT User Login

If you’ve already created a user and would like to log an existing user in, you can find that user using their credentials and Eloquent and create a token based on that user.

public function login(Request $request){ 
        if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){ 
            $user = Auth::user(); 
            $success['token'] =  $user->createToken('Password Token')-> accessToken; 
            $success['name'] = $user->name;
            $success['email'] = $user->email;
            return response()->json(['success' => $success], $this-> successStatus); 
        } 
        else{ 
            return response()->json(['error'=>'Unauthorised'], 401); 
        } 
    }
Route::post('login', 'API\UserController@login');
Laravel JWT Login

Laravel JWT Login

Getting User Details from JWT Token And Logout

To test that our token is associated with our user, we can get user details based on that token.

public function details(Request $request) 
    { 
        $user = Auth::user(); 
        return response()->json(['success' => $user], $this-> successStatus); 
    }

One of the issues with personal access token is that they are long-lived tokens. They last for 1 year after creation. This is not what you generally want. You can fix this by allowing the user to revoke their own token upon logout.

public function logout(){
        $value = $request->bearerToken();
        $id = (new Parser())->parse($value)->getHeader('jti');
        $token = $request->user()->tokens->find($id);
        $token->revoke();

        $response = 'You have been logged out';
        return response()->json(['success' => response], 200);
     }

Place your routes inside of your API Auth middleware.

Route::group(['middleware' => 'auth:api'], function(){
    Route::post('details', 'API\UserController@details');
    Route::post('logout', 'API\UserController@logout');
});
Auth Token User Details

Auth Token User Details

Conclusion

Having the ability to create JWT for you Laravel application allows for your app to be more versatile when authenticating your other applications. You can add React, Vue or even Angular applications as your front end and store the token in localStorage and placed in the header of each API request. If you’re interested in learning more, review some of our video courses.

Codebrains Newsletter

Get weekly dev news and tutorials.

Powered by ConvertKit