Force Gmail Api to Authenticate Again Java

When developing a web application, it is generally a proficient idea to split it into two tiers. A centre-tier API interacts with the database, and a spider web tier unremarkably consists of a front-stop SPA or MPA. This way, a web awarding is more than loosely coupled, making it easier to manage and debug in the long run.

When the API has been created, setting upwardly hallmark and land in a stateless API context might seem somewhat problematic.

In this article, we'll await at how to implement full user hallmark and a simple form of access control in an API using Laravel and Passport. You should have experience working with Laravel equally this is non an introductory tutorial.

Installation prerequisites:

  • PHP 7+, MySQL, and Apache (developers wanting to install all three at in one case can apply XAMPP.)
  • Composer
  • Laravel 7
  • Laravel Passport. Since APIs are generally stateless and do not utilize sessions, we generally apply tokens to keep country betwixt requests. Laravel uses the Passport library to implement a full OAuth2 server we can use for hallmark in our API.
  • Postman, curlicue, or Insomnia to test the API—this is up to personal preference
  • Text editor of your pick
  • Laravel helpers (for Laravel 6.0 and up)—subsequently installing Laravel and Passport, but run:
          composer crave laravel/helpers                  

With the above installed, nosotros're prepare to get started. Make sure to set upwardly your database connection past editing the .env file.

Laravel Passport Tutorial, Stride 1: Add a Controller and Model for Dummy Requests

First, we're going to create a controller and model for dummy requests. The model isn't going to be of much use in this tutorial, it'due south just to give an idea of the data the controller is meant to manipulate.

Before creating the model and controller, nosotros need to create a migration. In a terminal—or cmd.exe window, if you're using Windows—run:

          php artisan brand:migration create_articles_table  --create=manufactures                  

Now, get to the database/migrations folder and open the file with a name similar to xxxx_xx_xx_xxxxxx_create_articles_table.php.

In the upward function of the grade, we'll write this:

          Schema::create('articles', function (Blueprint $table) {     $tabular array->increments('id');     $table->string('title');     $tabular array->cord('body');     $table->integer('user_id');     $table->timestamps(); });                  

Next, we'll create an Article model. To exercise that, run:

          php artisan brand:model Article                  

We then create the ArticleController controller by running:

          php artisan make:controller ArticleController --resource                  

Adjacent, we'll edit the file app/Providers/AppServiceProvider.php and import the Illuminate\Support\Facades\Schema grade past adding:

          use Illuminate\Support\Facades\Schema                  

…to the lesser of the imports at the superlative of the file.

Then, in the kick function, we'll write:

          Schema::defaultStringLength(191);                  

After all of this is done, we can run:

          php artisan migrate                  

…to apply the migration we created above.

Laravel Passport Tutorial, Step ii: Create the Necessary Pieces of Middleware

Hither, nosotros will add the pieces of middleware that will be necessary for the API to work.

JSON Responses

The outset piece needed is the ForceJsonResponse middleware, which volition convert all responses to JSON automatically.

To do this, run:

          php artisan make:middleware ForceJsonResponse                  

And this is the handle function of that middleware, in App/Http/Middleware/ForceJsonReponse.php:

          public office handle($request, Closure $next) {     $asking->headers->set('Accept', 'application/json');     return $side by side($request); }                  

Adjacent, we'll add the middleware to our app/Http/Kernel.php file in the $routeMiddleware assortment:

          'json.response' => \App\Http\Middleware\ForceJsonResponse::class,                  

Then, nosotros'll besides add it to the $middleware array in the aforementioned file:

          \App\Http\Middleware\ForceJsonResponse::form,                  

That would brand sure that the ForceJsonResponse middleware is run on every asking.

CORS (Cantankerous-origin Resource Sharing)

To allow the consumers of our Laravel Residual API to admission it from a different origin, we accept to prepare CORS. To do that, we'll create a slice of middleware called Cors.

In a terminal or command prompt, cd into the project root directory and run:

          php artisan make:middleware Cors                  

Then, in app/Http/Middleware/Cors.php, add together the post-obit code:

          public function handle($request, Closure $next) {     return $next($request)         ->header('Access-Control-Permit-Origin', '*')         ->header('Access-Control-Permit-Methods', 'Go, Mail service, PUT, DELETE, OPTIONS')         ->header('Access-Control-Permit-Headers', 'X-Requested-With, Content-Type, X-Token-Auth, Authority'); }                  

To load this slice of middleware, we'll need to add together a line to app/Http/Kernel.php'due south $routeMiddleware array:

          'cors' => \App\Http\Middleware\Cors::class,                  

As well, nosotros'll accept to add it to the $middleware array as we did for the previous middleware:

          \App\Http\Middleware\Cors::class,                  

Later on doing that, we'll append this route group to routes/api.php:

          Route::grouping(['middleware' => ['cors', 'json.response']], part () {     // ... });                  

All our API routes will become into that office, every bit nosotros'll see beneath.

Laravel Passport Tutorial, Step 3: Create User Authentication Controllers for the API

Now we desire to create the authentication controller with login and register functions.

Commencement, nosotros'll run:

          php artisan make:controller Auth/ApiAuthController                  

Now nosotros'll import some classes to the file app/Http/Controllers/Auth/ApiAuthController.php. These classes are going to exist used in the creation of the login and register functions. We are going to import the classes by adding:

          apply App\User; use Illuminate\Support\Facades\Hash; utilize Illuminate\Support\Facades\Validator; use Illuminate\Support\Str;                  

…to the top of the controller.

Now, to add Laravel API authentication for our users, we are going to create login, logout, and register (signup) functions in the same file.

The register office will look like this:

          public function register (Request $request) {     $validator = Validator::make($request->all(), [         'name' => 'required|string|max:255',         'email' => 'required|string|email|max:255|unique:users',         'countersign' => 'required|string|min:six|confirmed',     ]);     if ($validator->fails())     {         render response(['errors'=>$validator->errors()->all()], 422);     }     $request['password']=Hash::make($request['countersign']);     $asking['remember_token'] = Str::random(ten);     $user = User::create($asking->toArray());     $token = $user->createToken('Laravel Password Grant Client')->accessToken;     $response = ['token' => $token];     return response($response, 200); }                  

The login part'southward like this:

          public function login (Asking $asking) {     $validator = Validator::make($request->all(), [         'e-mail' => 'required|string|email|max:255',         'password' => 'required|cord|min:6|confirmed',     ]);     if ($validator->fails())     {         return response(['errors'=>$validator->errors()->all()], 422);     }     $user = User::where('email', $request->email)->first();     if ($user) {         if (Hash::check($request->countersign, $user->countersign)) {             $token = $user->createToken('Laravel Countersign Grant Client')->accessToken;             $response = ['token' => $token];             return response($response, 200);         } else {             $response = ["message" => "Countersign mismatch"];             return response($response, 422);         }     } else {         $response = ["message" =>'User does non be'];         return response($response, 422);     } }                  

And finally, the logout function:

          public function logout (Request $asking) {     $token = $request->user()->token();     $token->revoke();     $response = ['message' => 'You have been successfully logged out!'];     render response($response, 200); }                  

After this, we need to add the login, register, and logout functions to our routes, i.east., inside the route group already in the API:

          Route::grouping(['middleware' => ['cors', 'json.response']], function () {      // ...      // public routes     Route::postal service('/login', 'Auth\ApiAuthController@login')->proper name('login.api');     Road::post('/annals','Auth\ApiAuthController@register')->name('annals.api');     Route::postal service('/logout', 'Auth\ApiAuthController@logout')->name('logout.api');      // ...  });                  

Lastly, we demand to add the HasApiToken trait to the User model. Navigate to app/User and make sure you have:

          use HasApiTokens, Notifiable;                  

…at the top of the class.

What We Take and so Far…

If we kickoff the application server—i.due east., run php artisan serve—and and then try to transport a Get request to the road /api/user, nosotros should receive the message:

          {     "message": "Unauthenticated." }                  

This is because we are non authenticated to access that route. To make some routes of your pick protected, nosotros can add them to routes/api.php but later on the Route::post lines:

          Route::middleware('auth:api')->grouping(function () {     // our routes to be protected will go in here });                  

Before moving on, we'll add the logout route to the auth:api middleware considering Laravel uses a token to log the user out—a token which cannot exist accessed from exterior the auth:api middleware. Our public routes look like this:

          Route::grouping(['middleware' => ['cors', 'json.response']], function () {      // ...      // public routes     Road::postal service('/login', 'Auth\ApiAuthController@login')->proper noun('login.api');     Route::post('/annals', 'Auth\ApiAuthController@register')->name('register.api');      // ...  });                  

Our protected routes, on the other mitt, look like this:

          Route::middleware('auth:api')->group(function () {     // our routes to be protected will go in here     Route::mail service('/logout', 'Auth\ApiAuthController@logout')->name('logout.api'); });                  

Now we'll navigate to the ArticleController we created in app/Http/Controllers/ArticleController.php and delete the create and edit methods in that grade. Afterward that, we'll add the post-obit slice of code, slightly edited, to each remaining function:

          $response = ['message' =>  '<function name> function']; return response($response, 200);                  

We'll make full in <office proper noun> as appropriate. For example, the update function will have this as its body:

          $response = ['message' => 'update part']; render response($response, 200);                  

A Manual Laravel Hallmark Test: Creating a User

To register a user, we'll send a POST request to /api/register with the post-obit parameters: name, email (which has to be unique), password, and password_confirmation.

A screenshot of sending a POST request to /api/register using Postman.

When the user is created, the API volition return a token, which we volition apply in further requests as our means to authentication.

To log in, we'll send a POST request to /api/login. If our credentials are correct, we volition besides go a token from our Laravel login API this style.

A screenshot of sending a POST request to /api/login using Postman.

The authorization token we get returned from this request we can utilise when we desire to admission a protected route. In Postman, the "Authorization" tab has a drop-down where the type can be set to "Bearer Token," after which the token can get into the token field.

The procedure is quite similar in Insomnia.

whorl users can do the equivalent by passing the parameter -H "Authorization: Bearer <token>", where <token> is the authority token given from the login or annals response.

As with curlicue, if developers plan to consume the API using axios or a library of that sort, they can add an Authorization header with value Bearer <token>.

Laravel Passport Tutorial, Footstep 4: Create Password Reset Functionality

Now that basic authentication is done, it'southward time to prepare up a password reset function.

To do this, we can choose to create an api_auth controller directory, create new custom controllers, and implement the function; or nosotros can edit the auth controllers that we can generate with Laravel. In this instance, we'll edit the auth controllers, since the whole application is an API.

First, nosotros will generate the auth controllers by running:

          composer require laravel/ui php artisan ui vue --auth                  

We'll edit the form in app/Http/Controllers/Auth/ForgotPasswordController.php, adding these 2 methods:

          protected function sendResetLinkResponse(Asking $asking, $response) {     $response = ['message' => "Password reset e-mail sent"];     return response($response, 200); } protected office sendResetLinkFailedResponse(Request $request, $response) {     $response = "E-mail could not be sent to this electronic mail address";     return response($response, 500); }                  

Next, we need to prepare the controller that really resets the password, so we'll navigate to app/Http/Controllers/Auth/ResetPasswordController.php and override the default functions like this:

          protected function resetPassword($user, $countersign) {     $user->password = Hash::make($password);     $user->save();     outcome(new PasswordReset($user)); } protected function sendResetResponse(Request $request, $response) {     $response = ['message' => "Countersign reset successful"];     render response($response, 200); } protected office sendResetFailedResponse(Request $asking, $response) {     $response = "Token Invalid";     return response($response, 401); }                  

Nosotros as well need to import some classes in the controller by calculation:

          use Illuminate\Auth\Events\PasswordReset; apply Illuminate\Http\Request; use Illuminate\Support\Facades\Hash;                  

…to the acme of the controller.

Nosotros'll desire to alter which email notification is used, too, considering the mail service notification that comes with Laravel does not utilize API tokens for authorization. We can create a new one under app/Notifications by running this control:

          php artisan make:notification MailResetPasswordNotification                  

We'll need to edit the file app/Notifications/MailResetPasswordNotification.php to look like this:

          <?php  namespace App\Notifications; utilise Illuminate\Motorcoach\Queueable; utilize Illuminate\Notifications\Messages\MailMessage; use Illuminate\Auth\Notifications\ResetPassword; use Illuminate\Support\Facades\Lang; grade MailResetPasswordNotification extends ResetPassword {     use Queueable;     protected $pageUrl;     public $token;     /**     * Create a new notification instance.     *     * @param $token     */     public function __construct($token)     {         parent::__construct($token);         $this->pageUrl = 'localhost:8080';             // we can set whatever we desire hither, or utilise .env to set environmental variables         }     /**     * Go the notification'due south delivery channels.     *     * @param  mixed  $notifiable     * @return array     */     public office via($notifiable)     {         return ['mail'];     }     /**     * Get the post representation of the notification.     *     * @param  mixed  $notifiable     * @render \Illuminate\Notifications\Messages\MailMessage     */     public office toMail($notifiable)     {         if (static::$toMailCallback) {             return call_user_func(static::$toMailCallback, $notifiable, $this->token);         }         return (new MailMessage)             ->discipline(Lang::getFromJson('Reset awarding Password'))             ->line(Lang::getFromJson('You lot are receiving this electronic mail because nosotros received a password reset request for your account.'))             ->activity(Lang::getFromJson('Reset Password'), $this->pageUrl."?token=".$this->token)             ->line(Lang::getFromJson('This password reset link volition elapse in :count minutes.', ['count' => config('auth.passwords.users.elapse')]))             ->line(Lang::getFromJson('If you did not request a password reset, no further action is required.'));     }     /**     * Get the array representation of the notification.     *     * @param  mixed  $notifiable     * @return array     */     public function toArray($notifiable)     {         return [             //         ];     } }                  

To brand use of this new notification, we need to override the sendPasswordResetNotification method that User inherits from the Authenticatable course. All we need to practise is add this to app/User.php:

          public function sendPasswordResetNotification($token) {     $this->notify(new \App\Notifications\MailResetPasswordNotification($token)); }                  

With a properly functioning postal service setup, notifications should exist working at this bespeak.

All that is left now is user admission command.

Laravel Passport Tutorial, Step 5: Create Access Control Middleware

Earlier we create admission command middleware, we volition need to update the user table to have a column named type, which volition be used to make up one's mind the user level: type 0 is a normal user, blazon one is an admin, and blazon 2 is a super-admin.

To update the user table, we have to create a migration by running this:

          php artisan make:migration update_users_table_to_include_type --tabular array=users                  

In the newly created file of the form database/migrations/[timestamp]_update_users_table.php, nosotros'll demand to update the up and down functions to add and remove the type column, respectively:

          public function up() {     Schema::table('users', function (Blueprint $table) {         $table->integer('type');     }); } /**  * Reverse the migrations.  *  * @return void  */ public office down() {     Schema::tabular array('users', function (Pattern $table) {         $table->dropIfExists('type');     }); }                  

Next, we'll run php artisan drift. Once this is done, we take to edit our register function in the ApiAuthController.php file, adding this just before the line with $user = User::create($request->toArray());:

          $request['type'] = $request['type'] ? $request['type']  : 0;                  

As well, we'll need to add together this line to the $validator array:

          'type' => 'integer',                  

The starting time of these ii edits will make all registered users "normal users" by default, i.east., if no user type is entered.

The Access Control Middleware Itself

Now nosotros're in a position to create two pieces of middleware to employ for access control: i for admins and one for super-admins.

So we'll run:

          php artisan make:middleware AdminAuth php artisan brand:middleware SuperAdminAuth                  

Outset, we'll navigate to app/Http/Middleware/AdminAuth.php and import Illuminate\Support\Facades\Auth, then edit the handle function like so:

          public role handle($request, Closure $next) {     if (Auth::guard('api')->bank check() && $asking->user()->blazon >= 1) {         render $next($asking);     } else {         $bulletin = ["message" => "Permission Denied"];         render response($message, 401);     } }                  

We'll too need to edit the handle part in app/Http/Middleware/SuperAdminAuth.php:

          public function handle($request, Closure $adjacent) {     if (Auth::guard('api')->bank check() && $request->user()->type >= 2) {         render $next($request);     } else {         $bulletin = ["message" => "Permission Denied"];         return response($message, 401);     } }                  

You should also import the Auth class at the superlative of both files by adding:

          use Illuminate\Support\Facades\Auth;                  

…to the lesser of the imports found there.

In order to use our new middleware, we'll reference both classes in the kernel—i.e., in app/Http/Kernel.php—by adding the post-obit lines to the $routeMiddleware assortment:

          'api.admin' => \App\Http\Middleware\AdminAuth::course, 'api.superAdmin' => \App\Http\Middleware\SuperAdminAuth::class,                  

If developers want to employ the middleware in a given road, all you need to exercise is add it to the route function similar this:

          Route::post('route','Controller@method')->middleware('<middleware-proper name-here>');                  

<middleware-name-hither> in this case can be api.admin, api.superAdmin, etc., equally appropriate.

That's all that's needed to create our middleware.

Putting It All Together

In society to examination that our authentication and admission control is working, at that place are some additional steps to become through.

Testing Laravel Authentication and Access Control: Step 1

We need to alter the ArticleController's index function and register the road. (In real-world projects, we would utilise PHPUnit and do this equally part of an automated test. Here, we're manually adding a route for testing purposes—information technology tin be removed subsequently.)

We'll navigate to the ArticleController controller at app/Http/Controllers/ArticleController and modify the alphabetize part to look similar this:

          public function index() {     $response = ['bulletin' => 'commodity index'];     return response($response, 200);  }                  

Next, we'll register the role in a route by going to the routes/api.php file and appending this:

          Route::middleware('auth:api')->group(office () { Route::get('/manufactures', 'ArticleController@index')->name('articles'); });                  

Testing Laravel Authentication and Access Control: Stride 2

Now we can try to access the road without an authentication token. We should receive an hallmark error.

A screenshot of sending a GET request to /api/articles using Postman, receiving a message "Unauthenticated" in response.

Testing Laravel Hallmark and Access Control: Step 3

We tin can also try to access the aforementioned road with an authorization token (the ane we got from registering or logging in earlier in this article).

Sometimes, this might cause an fault similar to this:

          Unknown column 'api_token' in 'where clause' (SQL: select * from `users` where `api_token` = ...                  
A screenshot of the unknown column error from GETting the api/articles route using Postman.

If this happens, developers should make certain to have run a Passport migration and have ['guards']['api']['commuter'] fix to passport in config/auth.php:

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

After that, the configuration cache needs updating also.

Once that is fixed, nosotros should have access to the route.

A screenshot of sending a GET request to /api/articles using Postman, with a normal JSON response.

Testing Laravel Authentication and Admission Command: Step iv

It's time to examination access control. Let's append ->middleware('api.admin') to the articles road, so information technology looks like this:

          Road::become('/articles', 'ArticleController@index')->middleware('api.admin')->name('articles');                  

Nosotros made information technology such that a newly created user is automatically assigned type 0, equally we tin run into via the api/user route.

A screenshot of sending a GET request to /api/user using Postman. The response includes an ID, name, email, null email verification timestamp, filled-in created and updated timestamps, and a type.

Because of that, we should get an mistake trying to access the articles endpoint as such a user.

A screenshot of sending a GET request to /api/articles using Postman, with a Permission Denied JSON response.

For the purpose of testing, let'due south modify the user in the database to have a type of ane. Subsequently verifying that change via the api/user road again, nosotros're ready to try again to Go the /manufactures/ route.

A screenshot of sending a GET request to /api/articles as a Laravel-authenticated user using Postman, identical to an earlier request, with the exception that this one's response time was 1,280 ms instead of 890 ms.

It works perfectly.

Developers who are making more complex applications should note that proper access controls will not be this unproblematic. In that case, other third-party applications or Laravel's gates and policies tin can be used to implement custom user access control. In the second part of this series, we'll look at more than robust and flexible admission control solutions.

Laravel API Authentication: What Nosotros've Learned

In this Laravel Passport tutorial, nosotros discussed:

  1. Creating a dummy controller and model to take something to use while testing our Laravel Passport example.
  2. Creating the middleware necessary to make our API run smoothly, addressing CORS and forcing the API to ever render JSON responses.
  3. Setting up basic Laravel API authentication: registering, logging in, and logging out.
  4. Setting up "password reset" functionality based on Laravel's default.
  5. Creating access control middleware to add user authorization permission levels to different routes.

These are essential skills for anyone working in the field of Laravel evolution services. Readers will find the cease result in this GitHub repo and should now be well-positioned to implement hallmark with Laravel. We look forward to comments below.

grafpord1975.blogspot.com

Source: https://www.toptal.com/laravel/passport-tutorial-auth-user-access

Belum ada Komentar untuk "Force Gmail Api to Authenticate Again Java"

Posting Komentar

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel