Laravel and JWT Authentication with custom model
Tags: laravel, jwt, authentication, php
Published: 2022-07-17 18:19:48

* Before we start, this is the first article i write in english, so apologize for any mistakes.

In this article, i will show you how to implement JWT authentication (using tymon/jwt-auth package) in a Laravel api, using a different model than the default (Users). At the end, a link to the repository will be available with the content of this article.

Portuguese version: https://dev.to/wenlopes/laravel-8-e-autenticacao-jwt-tymon-jwt-auth-com-model-customizada-2l7k

So let's go!

## Installation

Run this command to install the package

```bash
composer require tymon/jwt-auth
```

Publish the lib config file in your config folder, with the command

```bash
php artisan vendor:publish - provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
```

Finally, let's generate the JWT secret, running the command (This command will add **JWT_SECRET** env in your `.env` file)

```bash
php artisan jwt:secret
```

If you have questions about this step, [this is the official link to package documentation](https://jwt-auth.readthedocs.io/en/develop/laravel-installation/)

## Model configuration

Now it's time to change our default model. For our example, let's use a Model called Employee.

For this, we gonna make a migration to create a table in our database, with same name of the Model.

```bash
php artisan make:migration create_employee_table --create=employee
```

Our employee migration will have the same user migration structure that comes with the Laravel installation, but it difference will be a new column called "job_title".
Feel free to add new columns, but keep the "email" and "password" columns.

```php
Schema::create('employee', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->string('job_title');
    $table->timestamps();
});
```
Remove user migration and run

```bash
php artisan migrate
```

Create the Employee model

```bash
php artisan make:model Employee
```

*Important: In Employee model, you may need to add the $table variable, because when we create a test user in database (a little later in this article), Laravel will try to find the table name in plural, and it will cause error. If you already created the table in plural (employees), ignore this step.*

```bash
protected $table = 'employee';
```

The next step is to implement JWTSubject and extends Authenticatable class (Laravel) in our Model Employee. Finally, this will be our model content.

{% gist https://gist.github.com/WenLopes/29dbdc460badddfde6388caefa610342 %}

Very well, its time to configure our authentication provider.  For that, you must access the **config/auth.php** file and add the 'employess' index in 'providers' array, containing the driver (for this example, we are using Eloquent) and its Model (employee)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulef6pu5dkta3gfgptmp.png)

Now let's set the "api" guard as our application default. In the same file, access the "defaults" array and set the default guard to "api"

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8a3nu9cmc5hv0a3w3md.png)

We have finished our provider configuration and this should be the final content of **config/auth.php**.

{% gist https://gist.github.com/WenLopes/2ad0b52e47cd2163642e857bb21d4c05 %}

## Creating Controller and Route

It's time to create an auth controller to test our implementation

Create an controller called AuthController, with same content of this [link (official documentation from the package)](https://jwt-auth.readthedocs.io/en/develop/quick-start/) and create a route in your `routes/api.php` file

```php
use App\Http\Controllers\AuthController;

Route::post('auth/login', [AuthController::class, 'login'])->name('auth.login');
```

To test our endpoint, lets create an employee in our database and use this data to authenticate

In the `DatabaseSeeder` file, insert this content in the `run` method

```php
\App\Models\Employee::create([
    'name' => 'Usuário de teste',
    'email' => 'usuario@teste.com.br',
    'password' => bcrypt( 'senha123' ),
    'job_title' => 'Gerente administrativo'
]);
```

And run this command:

```bash
php artisan db:seed
```

Finally, use an API client (Postman, Insomnia...) and consume the **api/auth/login** login route, passing the email and password defined in the seeder. If everything work's fine, the result will be something like this:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk1orw0ooahox8e6n6en.png)

So it's done! Your authentication with an custom model is working.

You can find the repository with this implementation through this [link](https://github.com/WenLopes/laravel8-jwt). In the repository, i'm using Docker as infra, with Nginx, Mysql and Laravel in version 8. Also, i implemented the [pattern Strategy](https://refactoring.guru/pt-br/design-patterns/strategy) to return failed authentication messages and expired token response (in this case, a new valid token is returned).

So, that's all. If you have any questions, please comment and i will respond. Thank's for your attention.