Create API Rest with Laravel 7.X Passport Authentication And Implement Refresh Token (Part 2)
Tags: php, laravel, authentication, api
Published: 2020-03-13 22:51:17

In this part we need to add some routes , some middlewares and some functions to the controller so lets start 

## Step 1. Change api.php
We need to define three routes like this (we need "/unauthorized" for exception handling)
```php
<?php

use Illuminate\Support\Facades\Route;

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

Route::get('/unauthorized', 'UserController@unauthorized');
Route::group(['middleware' => ['CheckClientCredentials','auth:api']], function() {
    Route::post('logout', 'UserController@logout');
    Route::post('details', 'UserController@details');
});

```

## Step 2. Add functions to UserController.php
You need to add these functions in your controller
```php
...
    public function details() { 
        $user = Auth::user(); 
        return response()->json($user, $this->successStatus); 
    } 

    public function logout(Request $request) {
        $request->user()->token()->revoke();
        return response()->json([
            'message' => 'Successfully logged out'
        ]);
    }

    public function unauthorized() { 
        return response()->json("unauthorized", 401); 
    } 
...
```

## Step 3. Add middleware
First add you middleware
```
php artisan make:middleware CheckClientCredentials
```
Then you should change CheckClientCredentials.php it like this
```php
<?php

namespace App\Http\Middleware;

use Closure;
use Laminas\Diactoros\StreamFactory;
use Laminas\Diactoros\ResponseFactory;
use Laminas\Diactoros\UploadedFileFactory;
use Laminas\Diactoros\ServerRequestFactory;
use Laravel\Passport\Http\Middleware\CheckCredentials;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;

class CheckClientCredentials extends CheckCredentials
{
    public function handle($request, Closure $next, ...$scopes)
    {
        $psr = (new PsrHttpFactory(
            new ServerRequestFactory,
            new StreamFactory,
            new UploadedFileFactory,
            new ResponseFactory
        ))->createRequest($request);

        try {
            $psr = $this->server->validateAuthenticatedRequest($psr);
        } catch (OAuthServerException $e) {
            return response()->json($e->getPayload(), $e->getHttpStatusCode()); 
        }

        return $next($request);
    }

    protected function validateCredentials($token) {}
    protected function validateScopes($token, $scopes) {}
}

```
After that you need to change Authenticate.php (for exception handling)
```php
<?php

namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return '/api/unauthorized';
        }
    }
}
```

## Step 4. Change Kernel.php
We need to change some things in Kernel and add CheckClientCredentials middleware to $routeMiddleware and add it also in $middlewarePriority because we need to show CheckClientCredentials first!
Add CheckClientCredentials in $routeMiddleware
```php
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'CheckClientCredentials' => \App\Http\Middleware\CheckClientCredentials::class #changed
    ];

```
Add CheckClientCredentials in $middlewarePriority (you don't have this variable in kernel class and you should overwrite it)
```php
    protected $middlewarePriority = [
        \App\Http\Middleware\CheckForMaintenanceMode::class, #changed
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class
    ];
```

## Step 5. Now you can test it
You can test new urls and see the result 
details 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wnz51jtkurdmndviee0h.png)
logout
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kzwj6yv7iv1lizu6fgfx.png)

In next part we try to implement the refresh token

[Create API Rest with Laravel 7.X Passport Authentication And Implement Refresh Token (Part 3)](https://dev.to/azibom/create-api-rest-with-laravel-7-x-passport-authentication-and-implement-refresh-token-part-3-1b4d)