REST API and Passport Authentication with Laravel

REpresentational State Transfer or REST is an architectural style for providing standards between computer systems on the web. We need REST API’s to communicate over various mediums like web, desktop or mobile application through the same database. API’s do not maintain session state between requests, except use tokens to authenticate users requests.

We are going to build an API to access the registered user details. So we are going to build the login, registration and the user detail API.

Table of content

Setup Laravel Passport

We required the Laravel Passport that uses the OAuth2 server. Installing the Passport in laravel is pretty easy with the artisan command.

composer require laravel/passport

The above command will install the Passport package in your application. Now you need to add the related table in the database by using the migration command.

php artisan migrate

Now the next step is to run the passport installation. And will create personal access and passport grant clients which will be used to generate the access token.

php artisan passport:install

Now you have to add a few helper methods to your authenticable model which allows you to inspect the authenticated user’s token and scopes. Don’t worry, you don’t need to add that method one by one. You just need to add the Laravel\Passport\HasApiTokens trait to your model.

namespace App;

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

class User extends Authenticatable
{
    use Notifiable, HasApiTokens;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Next step is to add the Passport:route() method. This method will issue the access tokens and revoke access tokens, clients and personal access tokens. This routing method should be added to the boot method of your AuthServiceProvider.

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }
}

The next step is to define the API driver on the auth.php configuration file. Open the auth.php file and change API driver from token to passport.

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

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

Create Login, Registration and User Details API

Let’s start API with the Registration module. First, we will create a controller that will handle the login and registration request without an access token.

php artisan make:controller AuthController

Now open the api.php file from /routes directory add a new registration route to handle our post request.

Route::post('register', 'AuthController@register');

Now open the AuthController and add the registration login on the register method. Once a user is successfully registered, then we will return the registered user details.

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required', 
            'email' => 'required|email', 
            'password' => 'required|min:6'
        ]);


        $user = User::create([
            'name' => $request->name, 
            'email' => $request->email, 
            'password' => bcrypt($request->password)
        ]);

        return response()->json($user);
    }
}

Now let’s make our login route that will handle the login request and will return the access token. This access token we need to access the protected details.

Route::post('register', 'AuthController@register');
Route::post('login', 'AuthController@login');
...

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

    if( Auth::attempt(['email'=>$request->email, 'password'=>$request->password]) ) {
        $user = Auth::user();

        $token = $user->createToken($user->email.'-'.now());

        return response()->json([
            'token' => $token->accessToken
        ]);
    }
}

...

Now if we access the route http://localhost:8000/api/login and send the login details through POST request then we will get something similar response except the access token.

Next step is to define a toke protected route, says user details. We required the access token to access the details from this route.

Route::post('register', 'AuthController@register');
Route::post('login', 'AuthController@login');

Route::middleware('auth:api')->group(function() {

    Route::get('user/{userId}/detail', 'UserController@show');
});

Now create a UserController and add the logic to handle the request.

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function show(Request $request, $userId)
    {
        $user = User::find($userId);

        if($user) {
            return response()->json($user);
        }

        return response()->json(['message' => 'User not found!'], 404);
    }
}

Looking for scopes and permissions?

Please do not forget to check the related post for working with scopes and permissions.

Authenticate User Request

Next step is to authenticate the request by adding the access token. Open the POSTMAN and add the following headers.

"Accept: application/json",
"Authorization: Bearer xxxxxx" // Your access token

And use the http://localhost:8000/api/user/1/detail route to access the user details. And you will get the result like the below screenshot.

YouTube Video

Laravel Passport Authentication