DEV Community

loading...
Cover image for Create API Rest with Laravel 7.X Passport Authentication And Implement Refresh Token (Part 2)

Create API Rest with Laravel 7.X Passport Authentication And Implement Refresh Token (Part 2)

Mohammad Reza
Software Engineer at Cafe Bazaar
・3 min read

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

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');
});

Enter fullscreen mode Exit fullscreen mode

Step 2. Add functions to UserController.php

You need to add these functions in your controller

...
    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); 
    } 
...
Enter fullscreen mode Exit fullscreen mode

Step 3. Add middleware

First add you middleware

php artisan make:middleware CheckClientCredentials
Enter fullscreen mode Exit fullscreen mode

Then you should change CheckClientCredentials.php it like this

<?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) {}
}

Enter fullscreen mode Exit fullscreen mode

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

<?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';
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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

    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
    ];

Enter fullscreen mode Exit fullscreen mode

Add CheckClientCredentials in $middlewarePriority (you don't have this variable in kernel class and you should overwrite it)

    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
    ];
Enter fullscreen mode Exit fullscreen mode

Step 5. Now you can test it

You can test new urls and see the result
details
Alt Text
logout
Alt Text

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)

Discussion (1)

Collapse
atomico001 profile image
Atomico001

Hello, how can i use getTokenAndRefreshToken with a social login ?
with social i haven't password, can i ask for a refreshtoken without a password?