What Is the Use of Start Application at Login? Updated FREE
What Is the Use of Start Application at Login?
When developing a web application, it is generally a good idea to split it into two tiers. A middle-tier API interacts with the database, and a web tier usually consists of a front-end SPA or MPA. This mode, a web application is more loosely coupled, making it easier to manage and debug in the long run.
When the API has been created, setting upwardly hallmark and state in a stateless API context might seem somewhat problematic.
In this article, we'll await at how to implement total user authentication and a elementary form of access control in an API using Laravel and Passport. You should accept feel working with Laravel equally this is not an introductory tutorial.
Installation prerequisites:
- PHP 7+, MySQL, and Apache (developers wanting to install all 3 at once can use XAMPP.)
- Composer
- Laravel 7
- Laravel Passport. Since APIs are generally stateless and do non use sessions, we more often than not use tokens to keep country between requests. Laravel uses the Passport library to implement a full OAuth2 server nosotros tin employ for authentication in our API.
- Postman, curlicue, or Indisposition to exam the API—this is upwards to personal preference
- Text editor of your choice
- Laravel helpers (for Laravel vi.0 and up)—after installing Laravel and Passport, merely run:
composer crave laravel/helpers
With the above installed, we're ready to get started. Make sure to gear up upwardly your database connexion past editing the .env
file.
Laravel Passport Tutorial, Step 1: Add a Controller and Model for Dummy Requests
First, nosotros're going to create a controller and model for dummy requests. The model isn't going to be of much apply in this tutorial, information technology's just to requite an idea of the data the controller is meant to dispense.
Before creating the model and controller, we need to create a migration. In a terminal—or cmd.exe
window, if y'all're using Windows—run:
php artisan make:migration create_articles_table --create=articles
Now, go to the database/migrations
binder 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('manufactures', function (Pattern $table) { $table->increments('id'); $tabular array->string('title'); $table->string('body'); $tabular array->integer('user_id'); $table->timestamps(); });
Adjacent, nosotros'll create an Commodity
model. To practice that, run:
php artisan make:model Commodity
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
form by adding:
use Illuminate\Back up\Facades\Schema
…to the lesser of the imports at the superlative of the file.
And so, in the boot
function, we'll write:
Schema::defaultStringLength(191);
Afterward all of this is done, we tin can run:
php artisan drift
…to apply the migration nosotros created in a higher place.
Laravel Passport Tutorial, Step ii: Create the Necessary Pieces of Middleware
Here, we volition add the pieces of middleware that will be necessary for the API to work.
JSON Responses
The first piece needed is the ForceJsonResponse
middleware, which volition catechumen 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 function handle($request, Closure $next) { $request->headers->set('Accept', 'application/json'); render $side by side($request); }
Side by side, nosotros'll add the middleware to our app/Http/Kernel.php
file in the $routeMiddleware
array:
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,
And so, we'll too add it to the $middleware
array in the same file:
\App\Http\Middleware\ForceJsonResponse::form,
That would make sure that the ForceJsonResponse
middleware is run on every request.
CORS (Cantankerous-origin Resource Sharing)
To allow the consumers of our Laravel Balance API to access it from a different origin, we have to gear up CORS. To do that, we'll create a piece of middleware called Cors
.
In a terminal or command prompt, cd
into the projection root directory and run:
php artisan brand:middleware Cors
And then, in app/Http/Middleware/Cors.php
, add the following lawmaking:
public role handle($asking, Closure $next) { return $side by side($request) ->header('Access-Control-Permit-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, Mail, PUT, DELETE, OPTIONS') ->header('Admission-Control-Allow-Headers', 'Ten-Requested-With, Content-Type, X-Token-Auth, Authorization'); }
To load this piece of middleware, we'll need to add a line to app/Http/Kernel.php
's $routeMiddleware
array:
'cors' => \App\Http\Middleware\Cors::class,
Besides, we'll have to add information technology to the $middleware
array as nosotros did for the previous middleware:
\App\Http\Middleware\Cors::form,
After doing that, we'll append this route group to routes/api.php
:
Road::group(['middleware' => ['cors', 'json.response']], function () { // ... });
All our API routes volition become into that office, as we'll see below.
Laravel Passport Tutorial, Pace 3: Create User Authentication Controllers for the API
At present we desire to create the authentication controller with login
and register
functions.
First, we'll run:
php artisan make:controller Auth/ApiAuthController
Now we'll import some classes to the file app/Http/Controllers/Auth/ApiAuthController.php
. These classes are going to be used in the creation of the login
and annals
functions. Nosotros are going to import the classes past adding:
use App\User; apply Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str;
…to the top of the controller.
Now, to add together Laravel API authentication for our users, we are going to create login
, logout
, and register
(signup) functions in the same file.
The annals
role will look like this:
public part register (Request $asking) { $validator = Validator::brand($request->all(), [ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|cord|min:6|confirmed', ]); if ($validator->fails()) { return response(['errors'=>$validator->errors()->all()], 422); } $request['password']=Hash::make($request['password']); $request['remember_token'] = Str::random(10); $user = User::create($request->toArray()); $token = $user->createToken('Laravel Password Grant Client')->accessToken; $response = ['token' => $token]; render response($response, 200); }
The login
function'due south similar this:
public part login (Request $asking) { $validator = Validator::make($request->all(), [ 'electronic mail' => 'required|string|email|max:255', 'countersign' => 'required|cord|min:half dozen|confirmed', ]); if ($validator->fails()) { render response(['errors'=>$validator->errors()->all()], 422); } $user = User::where('e-mail', $request->email)->first(); if ($user) { if (Hash::cheque($request->password, $user->password)) { $token = $user->createToken('Laravel Countersign Grant Customer')->accessToken; $response = ['token' => $token]; render response($response, 200); } else { $response = ["bulletin" => "Password mismatch"]; return response($response, 422); } } else { $response = ["message" =>'User does not exist']; return response($response, 422); } }
And finally, the logout
office:
public function logout (Request $asking) { $token = $request->user()->token(); $token->revoke(); $response = ['bulletin' => 'You accept been successfully logged out!']; return response($response, 200); }
After this, nosotros need to add together the login
, annals
, and logout
functions to our routes, i.e., within the route group already in the API:
Road::group(['middleware' => ['cors', 'json.response']], function () { // ... // public routes Route::postal service('/login', 'Auth\ApiAuthController@login')->name('login.api'); Route::post('/annals','Auth\ApiAuthController@register')->proper name('register.api'); Route::mail('/logout', 'Auth\ApiAuthController@logout')->name('logout.api'); // ... });
Lastly, we need to add the HasApiToken
trait to the User
model. Navigate to app/User
and make sure you have:
utilize HasApiTokens, Notifiable;
…at the peak of the form.
What Nosotros Have so Far…
If we first the application server—i.e., run php artisan serve
—and so try to send a Get
request to the road /api/user
, we should receive the message:
{ "message": "Unauthenticated." }
This is because we are not authenticated to access that road. To make some routes of your choice protected, we can add them to routes/api.php
just after the Route::post
lines:
Route::middleware('auth:api')->grouping(office () { // our routes to be protected will go in here });
Before moving on, nosotros'll add the logout route to the auth:api
middleware considering Laravel uses a token to log the user out—a token which cannot be accessed from exterior the auth:api
middleware. Our public routes look similar this:
Route::group(['middleware' => ['cors', 'json.response']], function () { // ... // public routes Route::post('/login', 'Auth\ApiAuthController@login')->proper noun('login.api'); Route::mail('/annals', 'Auth\ApiAuthController@register')->proper name('register.api'); // ... });
Our protected routes, on the other mitt, look like this:
Route::middleware('auth:api')->group(role () { // our routes to be protected volition get in here Route::post('/logout', 'Auth\ApiAuthController@logout')->name('logout.api'); });
At present we'll navigate to the ArticleController
nosotros created in app/Http/Controllers/ArticleController.php
and delete the create
and edit
methods in that grade. After that, we'll add the following piece of code, slightly edited, to each remaining part:
$response = ['message' => '<office name> function']; return response($response, 200);
Nosotros'll fill in <function name>
as appropriate. For example, the update
function will have this equally its torso:
$response = ['message' => 'update function']; render response($response, 200);
A Manual Laravel Authentication Exam: Creating a User
To register a user, we'll transport a Postal service
request to /api/register
with the post-obit parameters: name
, email
(which has to be unique), password
, and password_confirmation
.
When the user is created, the API will return a token, which we will use in farther requests as our means to authentication.
To log in, we'll send a Post
asking to /api/login
. If our credentials are correct, we will likewise get a token from our Laravel login API this way.
The authorisation token we get returned from this request we tin can use when nosotros want to access a protected route. In Postman, the "Authorization" tab has a drop-down where the type tin can be set to "Bearer Token," afterward which the token tin get into the token field.
The process is quite similar in Insomnia.
curl users tin do the equivalent by passing the parameter -H "Authorization: Bearer <token>"
, where <token>
is the authorisation token given from the login or annals response.
As with cURL, if developers plan to swallow the API using axios or a library of that sort, they tin add an Authority
header with value Bearer <token>
.
Laravel Passport Tutorial, Stride 4: Create Countersign Reset Functionality
Now that basic authentication is done, it'due south time to gear up a password reset part.
To do this, we tin can choose to create an api_auth
controller directory, create new custom controllers, and implement the function; or we can edit the auth controllers that we can generate with Laravel. In this case, we'll edit the auth controllers, since the whole application is an API.
First, we will generate the auth controllers by running:
composer require laravel/ui php artisan ui vue --auth
Nosotros'll edit the class in app/Http/Controllers/Auth/ForgotPasswordController.php
, calculation these two methods:
protected function sendResetLinkResponse(Request $request, $response) { $response = ['message' => "Countersign reset email sent"]; return response($response, 200); } protected office sendResetLinkFailedResponse(Request $request, $response) { $response = "Email could not be sent to this email address"; return response($response, 500); }
Next, we need to gear up the controller that really resets the password, and so we'll navigate to app/Http/Controllers/Auth/ResetPasswordController.php
and override the default functions like this:
protected part resetPassword($user, $password) { $user->password = Hash::make($password); $user->save(); event(new PasswordReset($user)); } protected office sendResetResponse(Request $request, $response) { $response = ['message' => "Password reset successful"]; return response($response, 200); } protected office sendResetFailedResponse(Request $request, $response) { $response = "Token Invalid"; render response($response, 401); }
We also need to import some classes in the controller past calculation:
utilize Illuminate\Auth\Events\PasswordReset; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash;
…to the summit of the controller.
We'll want to modify which email notification is used, too, because the mail notification that comes with Laravel does not utilise API tokens for authorisation. Nosotros can create a new one under app/Notifications
by running this command:
php artisan make:notification MailResetPasswordNotification
We'll demand to edit the file app/Notifications/MailResetPasswordNotification.php
to look like this:
<?php namespace App\Notifications; employ Illuminate\Bus\Queueable; utilise Illuminate\Notifications\Messages\MailMessage; employ Illuminate\Auth\Notifications\ResetPassword; use Illuminate\Back up\Facades\Lang; class 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 nosotros want here, or use .env to set environmental variables } /** * Get the notification's delivery channels. * * @param mixed $notifiable * @render array */ public function via($notifiable) { render ['postal service']; } /** * Become the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $this->token); } return (new MailMessage) ->subject(Lang::getFromJson('Reset application Password')) ->line(Lang::getFromJson('You are receiving this email because we received a countersign reset request for your business relationship.')) ->action(Lang::getFromJson('Reset Password'), $this->pageUrl."?token=".$this->token) ->line(Lang::getFromJson('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.users.elapse')])) ->line(Lang::getFromJson('If you did not request a countersign reset, no farther activity is required.')); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @render array */ public function toArray($notifiable) { return [ // ]; } }
To make use of this new notification, we need to override the sendPasswordResetNotification
method that User
inherits from the Authenticatable
class. All we demand to do 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 be working at this indicate.
All that is left now is user admission control.
Laravel Passport Tutorial, Step 5: Create Access Control Middleware
Before nosotros create access control middleware, we will need to update the user
table to have a column named type
, which will be used to determine the user level: type 0 is a normal user, type ane is an admin, and blazon 2 is a super-admin.
To update the user
table, we have to create a migration past running this:
php artisan make:migration update_users_table_to_include_type --table=users
In the newly created file of the class database/migrations/[timestamp]_update_users_table.php
, we'll need to update the up
and downward
functions to add together and remove the type
column, respectively:
public function upward() { Schema::table('users', function (Blueprint $tabular array) { $table->integer('type'); }); } /** * Reverse the migrations. * * @render void */ public function down() { Schema::table('users', function (Pattern $table) { $tabular array->dropIfExists('blazon'); }); }
Next, we'll run php artisan migrate
. Once this is done, we have to edit our register
function in the ApiAuthController.php
file, adding this simply before the line with $user = User::create($asking->toArray());
:
$request['blazon'] = $request['type'] ? $asking['type'] : 0;
Also, we'll need to add together this line to the $validator
assortment:
'type' => 'integer',
The first of these two edits will make all registered users "normal users" by default, i.e., if no user type is entered.
The Access Control Middleware Itself
At present nosotros're in a position to create 2 pieces of middleware to use for access command: 1 for admins and i for super-admins.
So we'll run:
php artisan make:middleware AdminAuth php artisan make:middleware SuperAdminAuth
First, we'll navigate to app/Http/Middleware/AdminAuth.php
and import Illuminate\Support\Facades\Auth
, so edit the handle
role like so:
public role handle($request, Closure $next) { if (Auth::guard('api')->bank check() && $request->user()->type >= 1) { return $next($request); } else { $message = ["bulletin" => "Permission Denied"]; return response($message, 401); } }
We'll besides need to edit the handle
role in app/Http/Middleware/SuperAdminAuth.php
:
public function handle($request, Closure $next) { if (Auth::baby-sit('api')->cheque() && $request->user()->type >= 2) { return $next($request); } else { $bulletin = ["message" => "Permission Denied"]; return response($message, 401); } }
You should also import the Auth
class at the top of both files past calculation:
utilize Illuminate\Back up\Facades\Auth;
…to the bottom of the imports found there.
In order to utilize our new middleware, we'll reference both classes in the kernel—i.eastward., in app/Http/Kernel.php
—by calculation the following lines to the $routeMiddleware
array:
'api.admin' => \App\Http\Middleware\AdminAuth::class, 'api.superAdmin' => \App\Http\Middleware\SuperAdminAuth::course,
If developers want to use the middleware in a given route, all you demand to do is add it to the route function similar this:
Route::post('route','Controller@method')->middleware('<middleware-name-here>');
<middleware-name-hither>
in this case can exist api.admin
, api.superAdmin
, etc., as appropriate.
That's all that's needed to create our middleware.
Putting It All Together
In gild to test that our authentication and access control is working, there are some boosted steps to go through.
Testing Laravel Hallmark and Access Control: Step one
Nosotros need to change the ArticleController
'south alphabetize
function and register the road. (In real-world projects, we would use PHPUnit and exercise this as part of an automated exam. Hither, we're manually calculation a route for testing purposes—information technology tin be removed afterward.)
We'll navigate to the ArticleController
controller at app/Http/Controllers/ArticleController
and modify the alphabetize
function to look like this:
public function index() { $response = ['message' => 'commodity index']; render response($response, 200); }
Next, we'll register the function in a route by going to the routes/api.php
file and appending this:
Route::middleware('auth:api')->group(function () { Road::get('/articles', 'ArticleController@index')->name('articles'); });
Testing Laravel Hallmark and Access Command: Step two
Now nosotros can try to access the route without an authentication token. We should receive an hallmark error.
Testing Laravel Authentication and Access Control: Step 3
Nosotros can too effort to admission the same route with an authorization token (the i nosotros got from registering or logging in before in this article).
Sometimes, this might cause an error similar to this:
Unknown cavalcade 'api_token' in 'where clause' (SQL: select * from `users` where `api_token` = ...
If this happens, developers should make sure to have run a Passport migration and accept ['guards']['api']['driver']
gear up to passport
in config/auth.php
:
'guards' => [ 'spider web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
After that, the configuration cache needs updating as well.
Once that is fixed, nosotros should accept admission to the route.
Testing Laravel Hallmark and Access Control: Footstep iv
It's fourth dimension to test admission control. Let'southward suspend ->middleware('api.admin')
to the articles route, and then it looks like this:
Road::get('/manufactures', 'ArticleController@index')->middleware('api.admin')->proper name('articles');
We made it such that a newly created user is automatically assigned type 0, as nosotros tin encounter via the api/user
route.
Considering of that, we should get an error trying to access the manufactures
endpoint as such a user.
For the purpose of testing, allow'southward modify the user in the database to have a type
of ane. Afterward verifying that alter via the api/user
route again, nosotros're ready to attempt over again to GET
the /articles/
route.
It works perfectly.
Developers who are making more complex applications should note that proper access controls will not exist this simple. In that instance, other third-party applications or Laravel's gates and policies tin can be used to implement custom user access command. In the second function of this series, nosotros'll wait at more robust and flexible admission control solutions.
Laravel API Hallmark: What Nosotros've Learned
In this Laravel Passport tutorial, we discussed:
- Creating a dummy controller and model to have something to use while testing our Laravel Passport instance.
- Creating the middleware necessary to brand our API run smoothly, addressing CORS and forcing the API to always return JSON responses.
- Setting upward basic Laravel API authentication: registering, logging in, and logging out.
- Setting upwards "password reset" functionality based on Laravel's default.
- Creating admission command middleware to add together user say-so permission levels to different routes.
These are essential skills for anyone working in the field of Laravel development services. Readers will detect the cease result in this GitHub repo and should now be well-positioned to implement hallmark with Laravel. We wait forrard to comments beneath.
What Is the Use of Start Application at Login?
DOWNLOAD HERE
Source: https://www.toptal.com/laravel/passport-tutorial-auth-user-access
Posted by: nelsontyrdeed.blogspot.com