Method of Auth Authentication Using Passport in Laravel5.5

  • 2021-08-21 19:52:58
  • OfStack

Preface

Recently, I am writing a front-end separation project. I originally wanted to develop it with Jwt-auth + Dingo, but it was a little cumbersome, so I thought of Passport of Laravel and Api Resource of 5.5. Laravel Passport is a package of OAuth2 server-side implementations

OAuth is an open network standard for licensing (authorization), which is widely used all over the world. The current version is version 2.0.

OAuth 2.0 is a popular practice at present, which was first used by Google, Yahoo, Microsoft, Facebook and so on. It was labeled 2.0 because there was originally a 1.0 protocol, but this 1.0 protocol was too complicated and poor in ease of use, so it didn't get popular. 2.0 is a new design with a simple and clear protocol, but it is not compatible with 1.0, so it has nothing to do with 1.0.

So let's not go into details here. Let's see how to install it first.

Installation

Installing Passport

1. Execute the following commands in your Shell


composer require laravel/passport

If you are using an Laravel version below 5.5, you need to manually add the following code to the providers array of the config/app. php file


Laravel\Passport\PassportServiceProvider::class,

2. Run the migration file

Execute the following command in your Shell


php artisan migrate

The Passport service provider uses the framework to register its own migration directory, so after registering the service, you can run php artisan migrate directly to generate the required data tables for Passport

3. Generate encryption keys

Execute the following command in your Shell


php artisan passport:install

This command creates the encryption key needed to generate the secure access token, and it also creates the Personal Access client and Password Authorization used to generate the access token.

Step 4 Add Trait

Adding LaravelPassportHasApiTokens Trait to the AppUser model


<?php
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
 use HasApiTokens, Notifiable;
}

5. Register the route

Called in the boot method of AuthServiceProvider Passport::routes Function.


class AuthServiceProvider extends ServiceProvider
{
 public function boot()
 {
  $this->registerPolicies();
  Passport::routes();
 }
}

If your program requires OAuth authentication in the form of front-end separation instead of multi-platform authentication, you can pass an anonymous function in the routers () method to define the route you need to register. I have a separate front-end authentication form here, so I only need to provide Auth authentication for my front-end Client, so I only registered the route to get Token, and I also customized the prefix name for it.


Passport::routes(function(RouteRegistrar $router) {
 $router->forAccessTokens();
},['prefix' => 'api/oauth']);

6. Change the watchdog driver

Change the driver option for api of the authorization watchdog guards in the configuration file config/auth. php to passport. This tuning will allow your application to use TokenGuard of Passport when validating incoming API requests


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

So far, Passport has been installed. For the front-end part mentioned in the rest of the documents, because I only need to use it to authenticate Auth, I don't need to realize the complete OAuth function, so we can completely avoid using the front-end page.

Use

For the convenience of Api returning data, I encapsulated several functions


function respond($status, $respond)
{
 return response()->json(['status' => $status, is_string($respond) ? 'message' : 'data' => $respond]);
}
function succeed($respond = 'Request success!')
{
 return respond(true, $respond);
}
function failed($respond = 'Request failed!')
{
 return respond(false, $respond);
}

respond function can do basic return, succeed and failed are re-encapsulated on respond function to return request success and request failure data.

Then we need to use Layer 1 proxy.

First of all, the reason for using proxy in 1 is that the process of Passport authentication is that the slave application takes the master application

The generated Client Token and the account password entered by the user request the Passport Token route of the main application to obtain access token (access token) and refresh token (refresh token), and then access the route under auth: api with the obtained access token. But we don't have a dependent application, This token is requested by the front end separated from the front end. If you want to pull this access token from the front end, you need to write Client token in the front end. This is very unreasonable, so we can write an agent internally, and the application itself requests itself with Client token to obtain access token. This may have 1 point around, and the request process is as follows

1. The front end requests the server with the account password entered by the user

2. The server takes the account number and password received from the front end, and adds Client_id and Client_token, then requests its own Passport authentication route with these parameters, and then returns the authenticated Access token and refresh token

The following is the code implementation, I created a new ProxyHelpers Trait under AppHttpControllersTraits, of course, this function is my own encapsulation according to my business logic, if not suitable for your business logic you can adjust.


<?php

namespace App\Http\Controllers\Traits;

use GuzzleHttp\Client;
use App\Exceptions\UnauthorizedException;
use GuzzleHttp\Exception\RequestException;

trait ProxyHelpers
{
 public function authenticate()
 {
  $client = new Client();
  try {
   $url = request()->root() . '/api/oauth/token';
   $params = array_merge(config('passport.proxy'), [
    'username' => request('email'),
    'password' => request('password'),
   ]);
   $respond = $client->request('POST', $url, ['form_params' => $params]);
  } catch (RequestException $exception) {
   throw new UnauthorizedException(' Request failed, server error ');
  }
  if ($respond->getStatusCode() !== 401) {
   return json_decode($respond->getBody()->getContents(), true);
  }
  throw new UnauthorizedException(' Wrong account number or password ');
 }
}

config/passport. php reads as follows


Laravel\Passport\PassportServiceProvider::class,
0

The env file reads as follows


Laravel\Passport\PassportServiceProvider::class,
1

The client token we need to use is client token with id being 2, don't make a mistake ~

Then we just need use in the controller, Trait, and then call $this->authenticate() If the request fails, you can use token to catch errors and throw exceptions.


Laravel\Passport\PassportServiceProvider::class,
2

The resulting tokens returns in the following format


{
 "token_type": "Bearer",
 "expires_in": 31536000,
 "access_token": "token_str",
 "refresh_token": "token_str"
}

After this 1 cut, you can request the server from the front end


Laravel\Passport\PassportServiceProvider::class,
4

If the request is successful, you will get the user's information and access token, refresh token.

Then add a parameter Authorization to your front-end http request header


Laravel\Passport\PassportServiceProvider::class,
5

Then use the middleware auth: api in the route you need to use auth authentication, and you are done with 1 cut ~

Summarize


Related articles: