Build authentication into your Laravel API with JSON Web Tokens (JWT)

Connor Leech
Dec 12, 2018 · 6 min read
Image for post
Image for post
tymondesigns/jwt-auth

In this tutorial we’re going to expand the API we built in the previous tutorial to include authentication. By default Laravel includes authentication for session based authentication. Check it out by looking at the Laravel docs on authentication:

At its core, Laravel’s authentication facilities are made up of “guards” and “providers”. Guards define how users are authenticated for each request. For example, Laravel ships with a session guard which maintains state using session storage and cookies. — Laravel 5.7 Authentication docs

Source code for what we’re working on

We can see the config for session based authentication under the “guards” section of config/auth.php:

Cookies are great when the server and the client are on the same domain, but with API driven development we’re likely to have a server running in one place and a client, or multiple clients running on other domains. With multiple domains we can run into Cross Origin Resource Sharing (CORS) errors. When building an API it’s common practice to use JSON Web Tokens (JWT) instead. This means we’ll need to update our auth guards.

In this tutorial we’re going to use tymondesigns/jwt-auth (docs) for our new authentication guard. It can be installed with composer:

Laravel Passport is another package that does similar things to jwt-auth.

The jwt-auth composer package has a config file that we can publish:

A new config file gets generated in config/jwt.php. Next step is to generate a secret key. We’ll use this key to sign all of our tokens.

This command will add a JWT_SECRET value to our .env file. In order to use this jwt-auth package, our User model (or whatever model we’re using to authenticate) must implement the JWTSubject interface. That interface has two methods as we can see here:

In order to implement an interface you need to provide all of the methods of that interface in your class. That means for our User model to implement this interface it needs to have a getJWTIdentifier method and a getJWTCustomClaims method.

Read more about the structure of JSON Web Tokens here: https://jwt.io/introduction/

The subject claim will be a reference to our user. Eloquent provides a “getKey” method on our models that returns the value of the record’s primary key. For the default User table in Laravel the primary key is the “id” column. For the custom claims method, we’re not going to worry about that and instead return an empty array.

We also want to make sure that whenever we save the password we are saving the hashed version. We can do this by using a Laravel Mutator so that whenever we save a value to the “password” column we always save the hashed version.

That’s it! We’re successfully implementing the contract that we need to implement. In our config/auth.php file we need to specify that we’d like to use the jwt guard that this package provides:

So our default auth guard is the “api” guard and that guard uses the “jwt” driver. This keeps us primarily using the built in Laravel auth functionality but powered by jwt-auth driver behind the scenes.

We’re all set up to use the jwt driver as our authentication gaurd. Now we need to define some routes and controller methods. When someone posts to /api/register we’re going to create a user and log them in by sending back a token. When someone posts to /api/login we’re going to verify the credentials are legit and send back a token if they are.

Be sure to scope the Laravel documentation on manually authenticating users

First, define the routes in routes/api.php and create the corresponding controller with php artisan make:controller AuthController.

With these routes established, let’s check out how to implement the methods. Much of this is drawn directly from the tymondesigns/jwt-auth docs.

When a standalone frontend application sends request to your server the browser might sqwak about Cross Origin Resource Sharing (CORS). Install this package:

And add it to app/Http/Kernel.php in the $middleware array:

Image for post
Image for post

Woohoo so it should all be working, but let’s write some tests to prove it.

Theses tests go through and test that we get the right response formats. Pushing up the source code to GitHub!

Source code on GitHub

These were helpful resources apart from the official documentation that were helpful in making sense of JWT authentication in Laravel.

🚀 If you’re a candidate on the job market or startup looking to hire in the Bay Area, feel free to create a profile on Employbl 🤝

Employbl

Find a tech or startup job in the Bay Area.

Connor Leech

Written by

Engineer, writer and community organizer. I built Employbl to help candidates get jobs in the Bay Area: https://employbl.com/

Employbl

Employbl

Find a tech or startup job in the Bay Area.

Connor Leech

Written by

Engineer, writer and community organizer. I built Employbl to help candidates get jobs in the Bay Area: https://employbl.com/

Employbl

Employbl

Find a tech or startup job in the Bay Area.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store