Super Easy Way to Authenticate an API User in Your Laravel Application Without Using Laravel Passport

Super Easy Way to Authenticate an API User in Your Laravel Application Without Using Laravel Passport


Apr 07 2018, 14:15 in Web Development

Since Laravel 5.3, Laravel Passport is the main way to authenticate an API consumer with an access token. I say it's the main way because it's the only way described in the Laravel documentation.

Simply try to search "auth:api" on the Laravel Documentation website and the only results will be related to Laravel Passport.

The thing is that in some cases you don't need the complexity of Laravel Passport for your needs.

For example, I'm building a website that provides to my users a few api routes that the user can call to update his datas. I don't need a full OAuth system, I don't need multiple database table to store tokens that could expire, I don't need the full Laravel Passport package.

I just need to provide a unique token to my users, and let them use it in their API calls in order to be authenticated.

Very simple stuff, but pretty unclear on how to achieve that. Here's how:

Step One : Database

You obviously need to provide a token to your user so you need to store that in your database. Storing that in your users table is perfectly fine:

php artisan make:migration add_api_token_field_to_users_table

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('api_token', 36)->unique();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('api_token');
    });
}

Step Two : Generate Token

Now that your database is ready, you should either allow your users to generate an API Token for their account, or generate one yourself for each user. There are multiple ways to do that, here's mine. Since Laravel 5.6 provides a UUID generator helper, let's use that. In my User.php model, I have a very short and simple method:

// app/User.php
public function setNewApiToken()
{
    $this->api_token = Str::uuid();
    $this->save();
}

// Usage
auth()->user()->setNewApiToken();
// or
$user->setNewApiToken();

Step Three : Check your config

By default the auth.php configuration file is already correctly configured so you don't need to change anything, but just to make sure it's ok:

// config/auth.php
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'token', // This is what you need
        'provider' => 'users',
    ],
],

Step Four : Middleware

All your API routes needs to be located in the routes/api.php file. For the specific routes that needs authentication middleware, you should use the auth:api middleware, like this:

// routes/api.php
// POST /api/post?api_token=UNIQUE_TOKEN
Route::post('post', 'Api\PostController@store')->middleware('auth:api');

Now your users will need to add a query string parameter to their request. If you are maybe using javascript on your website to make AJAX calls on your own backend, you will maybe need to that as well. Here's an example with axios, where a user is using a form on your website to update is profile in AJAX:

axios.put('/api/user/profile', {
    name: this.newName,
    some_field: this.newFieldValue,
}, {
    params: {
        'api_token': this.user.api_token
    }
})
.then(response => {
    // whatever
});

But wait a second ! That won't work just yet :)

Step Five : Tell Laravel to authenticate the user with the token

This is specifically the missing piece of the Laravel Documentation. Hopefully, there's not a ton of things to do, and Laravel provides everything you need, you just need to register the right class at the right place.

Let's head to the AuthServiceProvider.php

// app/Providers/AuthServiceProvider.php
use Illuminate\Auth\TokenGuard;
use Illuminate\Support\Facades\Auth;

// ...

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

Auth::extend('token', function ($app, $name, array $config) {
    return new TokenGuard(Auth::createUserProvider($config['provider']), $app->request);
});

}

And basically that's it! In the Laravel documentation, you're invited to create your own TokenGuard class, but there's not much info there... Thankfully, Laravel already provides a TokenGuard class, you just need to know that it exists !

If you're curious you can check it out on github here.


Share:
Like:

Disable AdBlock on this domain and offer me a cup of coffee :)