How to consume Laravel Passport JWT Tokens with Javascript

This is an easy method that I use for almost all of my applications. In this post I will discuss how we can generate JWT Tokens for a user, and use it for performing authenticated actions and how to store it for later usage, as well as how to consume Laravel Passport JWT Tokens with Javascript (Axios, Angular and jQuery).

Assumptions:

You already know how to use Laravel. You are already familiar with axios/jQuery/Angular’s HTTP module. This is not for the very beginners.

We’re also assuming that the API is created with laravel and is separated from the front end project. The front end project is not made with Laravel Mix and is a standalone project of its own.

We’re also going to use a controller named AuthCtrl.php to handle some authentication functions.

Note: if you see /... anywhere, it means some text has been removed for brevity and you should keep what you have in the original file in there.

Step 1: Install Passport

Install Laravel Passport by typing this in the command line:

composer require laravel/passport

Once composer finishes, run the migrations it comes with:

php artisan migrate

Tables are ready, to start generating token type this in:

php artisan passport:install

Edit the file User.php and add this line:

<?php

namespace App;

use Laravel\Passport\HasApiTokens; // this line
// ...... other uses

class User extends Authenticatable
{
    use HasApiTokens, Notifiable; // add HasApiTokens
}

Optional step

We’re just going to issue personal tokens, so we don’t really need this. But, if you want to go the full blown oAuth way, find the file App\Providers\AuthServiceProvider.php and add these lines:

<?php

namespace App\Providers;

use Laravel\Passport\Passport; // this line
//....

class AuthServiceProvider extends ServiceProvider
{
    //.....
    
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes(); // this line
    }
}

Step 2: Add Passport to the API routes to act as the middleware logic

Find the file config/auth.php and make the following change:

'guards' => [
    //...

    'api' => [
        'driver' => 'passport', // change this to passport
        'provider' => 'users',
    ],
],

That’s it. We’re now ready to start generating JWT Tokens (aka Bearer tokens).

Step 3: Setting up CORS for cross-site requests

Since an API is meant to be consumed from multiple sources that may not be hosted in the same domain, we’ll need to make sure that our API support cross origin requests. By default all requests are filtered out if it’s not from the same origin. We’re going to take care of that.

Install the package Laravel CORS to solve this issue. The github page has very nice instructions for you to follow and takes a minute to set it up.

Notes:
☼ There is no need to generate setting files.
☼ Only allow CORS for the API.

Step 4: Generating token with the controller

Create a controller named AuthCtrl.php using php artisan make:controller AuthCtrl in your console/command prompt.

Add a route to the api.php file:

Route::post('/login', '[email protected]');

Let’s edit the file AuthCtrl.php and write the login method:

<?php
// file: Http\Controllers\AuthCtrl.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User; //  <--
use Illuminate\Support\Facades\Auth; // <--

class AuthCtrl extends Controller
{

    public function login(Request $request)
    {
        $rules = [
            'email' => 'required|exists:users',
            'password'  => 'required'
        ];

        $request->validate($rules);

        $data = [
            'email' => $request->get('email'),
            'password'  =>  $request->get('password'),
            'is_active' => true
        ];

        if(Auth::attempt($data))
        {
            $user = Auth::user();
            // the $user->createToken('appName')->accessToken generates the JWT token that we can use 
            return response()->json([
                'user'  =>  $user, // <- we're sending the user info for frontend usage
                'token' =>  $user->createToken('yourAppName')->accessToken // <- token is generated and sent back to the front end
            ]);
        }
        else
        {
            return response()->json('Unauthorized', 401);
        }

    }
}

Using with Javascript

I will show below how to use this with Axios, Angular and jQuery. Basically, all of your XHR requests must have this header: Authorization: Bearer[space]huge-long-string-token . As you understand, [space] = a space.

So, the basic idea is to:

  1. Get the Token by logging the user in.
  2. Store the token for later use
  3. Make sure that from that point onwards, all requests by the XHR library includes the Authorization header.

Alright. Let’s get to it.

Axios

axios
  .post("http://localhost:8000/api/login", user)
  .then(resp => {
    this.user = resp.data.user;
    this.token = resp.data.token;
    localStorage.setItem("your_app_token", resp.data.token);
    axios.defaults.headers.common["Authorization"] =
      "Bearer " + resp.data.token; // mind the space
  })
  .catch(err => {
    console.log(err);
    localStorage.removeItem('your_app_token');
  });

From that point onwards, your requests will have the bearer token in them and you can fetch the token from the localStorage . Keep in mind that these tokens expire, so you should make sure that the users log in often to refresh it.

Angular

In Angular, you need an http intercepter to add the header. This post has excellent information about it. It’s got a full-stack example too. It’s way better than how I could word it.

jQuery

Can work with both $.post() and $.ajax. Here we’re going to use ajax.

$.ajax({
	method: "POST",
	url: "login url",
	data : {email : email, password: password}
}).done(function(data, status) {
	localStorage.setItem('appname_token', data.token);
	// the following part makes sure that all the requests made later with jqXHR will automatically have this header.
	$( document ).ajaxSend(function( event, jqxhr, settings ) {
	    jqxhr.setRequestHeader('Authorization', "Bearer " + data.token); 
	});
}).fail(function(error){
	// handle the error
});

However, you can also use the header with ajax calls on the fly like:

$.ajax({ 
	url: 'foo/bar', 
	headers: { 
		'Authorization': 'Bearer ' + localStorage.getItem('appname_token') 
	} 
});

This is basically it. Feel free to leave comments with corrections/suggestions.

4 comments / Add your comment below

    1. Hi Amir. If you’re using normal Session based login, you do not need to store the token because you don’t get the JWT token back. You just need the CSRF key in your requeest headers. Laravel comes with that ready to use. Make a fresh Laravel installation and see how it is shipped with that set up.
      If you are using Laravel Mix and Vue, you can use the default system that it comes with. The aforementioned method is for separate use with an API and JWT Tokens. Let me know if this helps.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.