Cover image
Back-end
13 minute read

Full User Authentication and Access Control: A Laravel Passport Tutorial, Pt. 1

Setting up authentication and state in a stateless API context might seem somewhat problematic. But Laravel Passport gives developers a clean, straightforward way to add OAuth 2.0 to an app’s API.

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 way, 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 up authentication and state in a stateless API context might seem somewhat problematic.

In this article, we’ll look at how to implement full user authentication and a simple form of access control in an API using Laravel and Passport. You should have experience working with Laravel as this is not an introductory tutorial.

Installation prerequisites:

  • PHP 7+, MySQL, and Apache (developers wanting to install all three at once can use XAMPP.)
  • Composer
  • Laravel 7
  • Laravel Passport. Since APIs are generally stateless and do not use sessions, we generally use tokens to keep state between requests. Laravel uses the Passport library to implement a full OAuth2 server we can use for authentication in our API.
  • Postman, cURL, or Insomnia to test the API—this is up to personal preference
  • Text editor of your choice
  • Laravel helpers (for Laravel 6.0 and up)—after installing Laravel and Passport, just run:
composer require laravel/helpers

With the above installed, we’re ready to get started. Make sure to set up your database connection by editing the .env file.

Laravel Passport Tutorial, Step 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’s just to give an idea of the data the controller is meant to manipulate.

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

php artisan make:migration create_articles_table  --create=articles

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

In the up function of the class, we’ll write this:

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

Next, we’ll create an Article model. To do that, run:

php artisan make:model Article 

We then create the ArticleController controller by running:

php artisan make:controller ArticleController --resource

Next, we’ll edit the file app/Providers/AppServiceProvider.php and import the Illuminate\Support\Facades\Schema class by adding:

use Illuminate\Support\Facades\Schema

…to the bottom of the imports at the top of the file.

Then, in the boot 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 2: Create the Necessary Pieces of Middleware

Here, we will 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 will 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 function handle($request, Closure $next)
{
    $request->headers->set('Accept', 'application/json');
    return $next($request);
}

Next, we’ll add the middleware to our app/Http/Kernel.php file in the $routeMiddleware array:

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

Then, we’ll also add it to the $middleware array in the same file:

\App\Http\Middleware\ForceJsonResponse::class,

That would make sure that the ForceJsonResponse middleware is run on every request.

CORS (Cross-origin Resource Sharing)

To allow the consumers of our Laravel REST API to access it from a different origin, we have to set up CORS. To do that, we’ll create a piece 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 the following code:

public function handle($request, Closure $next)
{
    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
        ->header('Access-Control-Allow-Headers', 'X-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,

Also, we’ll have to add it to the $middleware array as we did for the previous middleware:

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

After doing that, we’ll append this route group to routes/api.php:

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

All our API routes will go into that function, as we’ll see below.

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

Now we want 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 register functions. We are going to import the classes by adding:

use App\User;
use Illuminate\Support\Facades\Hash;
use 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 function 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',
        'password' => 'required|string|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];
    return response($response, 200);
}

The login function’s like this:

public function login (Request $request) {
    $validator = Validator::make($request->all(), [
        'email' => 'required|string|email|max:255',
        'password' => 'required|string|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->password, $user->password)) {
            $token = $user->createToken('Laravel Password Grant Client')->accessToken;
            $response = ['token' => $token];
            return response($response, 200);
        } else {
            $response = ["message" => "Password mismatch"];
            return response($response, 422);
        }
    } else {
        $response = ["message" =>'User does not exist'];
        return response($response, 422);
    }
}

And finally, the logout function:

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

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

Route::group(['middleware' => ['cors', 'json.response']], function () {

    // ...

    // public routes
    Route::post('/login', 'Auth\ApiAuthController@login')->name('login.api');
    Route::post('/register','Auth\ApiAuthController@register')->name('register.api');
    Route::post('/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:

use HasApiTokens, Notifiable;

…at the top of the class.

What We Have so Far…

If we start the application server—i.e., run php artisan serve—and then try to send a GET request to the route /api/user, we should receive the message:

{
    "message": "Unauthenticated."
}

This is because we are not authenticated to access that route. 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')->group(function () {
    // our routes to be protected will go in here
});

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

Route::group(['middleware' => ['cors', 'json.response']], function () {

    // ...

    // public routes
    Route::post('/login', 'Auth\ApiAuthController@login')->name('login.api');
    Route::post('/register', 'Auth\ApiAuthController@register')->name('register.api');

    // ...

});

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

Route::middleware('auth:api')->group(function () {
    // our routes to be protected will go in here
    Route::post('/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 class. After that, we’ll add the following piece of code, slightly edited, to each remaining function:

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

We’ll fill in <function name> as appropriate. For example, the update function will have this as its body:

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

A Manual Laravel Authentication Test: Creating a User

To register a user, we’ll send a POST request to /api/register with the following 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 will return a token, which we will use 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 will also get a token from our Laravel login API this way.

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

The authorization token we get returned from this request we can use when we want to access 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 go into the token field.

The process is quite similar in Insomnia.

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

As with cURL, 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, Step 4: Create Password Reset Functionality

Now that basic authentication is done, it’s time to set 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 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

We’ll edit the class in app/Http/Controllers/Auth/ForgotPasswordController.php, adding these two methods:

protected function sendResetLinkResponse(Request $request, $response)
{
    $response = ['message' => "Password reset email sent"];
    return response($response, 200);
}
protected function sendResetLinkFailedResponse(Request $request, $response)
{
    $response = "Email could not be sent to this email address";
    return response($response, 500);
}

Next, we need to set up the controller that actually 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, $password)
{
    $user->password = Hash::make($password);
    $user->save();
    event(new PasswordReset($user));
}
protected function sendResetResponse(Request $request, $response)
{
    $response = ['message' => "Password reset successful"];
    return response($response, 200);
}
protected function sendResetFailedResponse(Request $request, $response)
{
    $response = "Token Invalid";
    return response($response, 401);
}

We also need to import some classes in the controller by adding:

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

…to the top of the controller.

We’ll want to modify which email notification is used, too, because the mail notification that comes with Laravel does not use API tokens for authorization. We can create a new one under app/Notifications by running this command:

php artisan make:notification MailResetPasswordNotification 

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

<?php

namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\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 we want here, or use .env to set environmental variables
        }
    /**
    * Get the notification's delivery channels.
    *
    * @param  mixed  $notifiable
    * @return array
    */
    public function via($notifiable)
    {
        return ['mail'];
    }
    /**
    * Get 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 password reset request for your account.'))
            ->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.expire')]))
            ->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 make use of this new notification, we need to override the sendPasswordResetNotification method that User inherits from the Authenticatable class. All we need to do is add this to app/User.php:

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

With a properly functioning mail setup, notifications should be working at this point.

All that is left now is user access control.

Laravel Passport Tutorial, Step 5: Create Access Control Middleware

Before we 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 1 is an admin, and type 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 --table=users

In the newly created file of the form database/migrations/[timestamp]_update_users_table.php, we’ll need 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 function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropIfExists('type');
    });
}

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 just before the line with $user = User::create($request->toArray());:

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

Also, we’ll need to add this line to the $validator array:

'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

Now we’re in a position to create two pieces of middleware to use for access control: one for admins and one 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, then edit the handle function like so:

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

We’ll also need to edit the handle function in app/Http/Middleware/SuperAdminAuth.php:

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

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

use Illuminate\Support\Facades\Auth;

…to the bottom 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 following lines to the $routeMiddleware array:

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

If developers want to use the middleware in a given route, all you need to do is add it to the route function like this:

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

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

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

Putting It All Together

In order to test that our authentication and access control is working, there are some additional steps to go through.

Testing Laravel Authentication and Access Control: Step 1

We need to modify the ArticleController’s index function and register the route. (In real-world projects, we would use PHPUnit and do this as part of an automated test. Here, we’re manually adding a route for testing purposes—it can be removed afterward.)

We’ll navigate to the ArticleController controller at app/Http/Controllers/ArticleController and modify the index function to look like this:

public function index()
{
    $response = ['message' => 'article index'];
    return 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 () {
Route::get('/articles', 'ArticleController@index')->name('articles');
});

Testing Laravel Authentication and Access Control: Step 2

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

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

Testing Laravel Authentication and Access Control: Step 3

We can also try to access the same route with an authorization token (the one we got from registering or logging in earlier in this article).

Sometimes, this might cause an error 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 sure to have run a Passport migration and have ['guards']['api']['driver'] set to passport in config/auth.php:

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

    'api' => [ 
        'driver' => 'passport', 
        'provider' => 'users', 
    ], 
],

After that, the configuration cache needs updating as well.

Once that is fixed, we 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 Access Control: Step 4

It’s time to test access control. Let’s append ->middleware('api.admin') to the articles route, so it looks like this:

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

We made it such that a newly created user is automatically assigned type 0, as we can see 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 error 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’s modify the user in the database to have a type of 1. After verifying that change via the api/user route again, we’re ready to try again to GET the /articles/ 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 simple. In that case, other third-party applications or Laravel’s gates and policies can be used to implement custom user access control. In the second part of this series, we’ll look at more robust and flexible access control solutions.

Laravel API Authentication: What We’ve Learned

In this Laravel Passport tutorial, we discussed:

  1. Creating a dummy controller and model to have 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 always return 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 development services. Readers will find the end result in this GitHub repo and should now be well-positioned to implement authentication with Laravel. We look forward to comments below.

Understanding the basics

Laravel Passport is an OAuth 2.0 server implementation for API authentication using Laravel. Since tokens are generally used in API authentication, Laravel Passport provides an easy and secure way to implement token authorization on an OAuth 2.0 server.

Laravel Passport is a package used to implement authentication in a Laravel REST API.

Laravel Passport is an OAuth 2.0 server implementation for stateless authentication. OAuth 2.0 is the most recent OAuth protocol, and yes, it is secure.

A stateless API is one where each request to it is completely isolated and each request’s response is totally dependent on the request alone. This is unlike in a stateful application, where each request's response is dependent on the “state” of the server and the request.

Comments

aito77
Excellent Tutorial! Well explained and correct. Thanks!
Salvador Sanchez
Hello, first of all excellent work thank you very much. I have a question, how can I test the reset password?
Ihtisham Ahmad
Hey Layo Folaranmi, thanks for the awesome work. It will help many newbies and save their time.
Ihtisham Ahmad
I liked that you forced the API to always return JSON responses. This is good for security.
Ihtisham Ahmad
Layo Folaranmi, I was just curious about one thing. Do the rest APIs make the process slower or not. Like you have to communicate to database through the rest API, which is actually built in the web application. Like no direct communication with database. Did you get my point?
Osama Diab
thanks so much, but i got an error via logout function -> error Call to a member function token() on null
Gagan Adlakha
Yeah I have tried same and also getting exactly same error. (Call to a member function token() on null)
Gagan Adlakha
Hi Osama, $token = $request->user()->token()->revoke(); worked for me but only when I pasted my Route to api:auth middleware as it was shown under Forcejson,cors middleware group. Hope for the best !
Alitnk
This is one great tutorial! thanks a lot man. appreciate the time you put on it.
Oli Ver
Hi gotta ask. When he used the middleware to add header like <code>$request->headers->set('Accept', 'application/json');</code> Does that mean I don't have to do converting results to API resources like UserResource to similar to that
HIRWA INNOCENT
What is the name of that software sir? The one you're using to test?? Thanks https://uploads.disquscdn.com/images/6f340f3b098b64b426b7e6caa2a9f38f22dc8a77d93f1daaaa5ad700a19bc728.png
Olanrewaju Olayinka Ahmed
https://uploads.disquscdn.com/images/68ce1b330e81a8ae7e027856658e3bc32fe25c298464490c7be67bd9b53c47c6.png <code> public function logout (Request $request) { $token = $request->user()->token(); $token->revoke(); $response = ['message' => 'You have been successfully logged out!']; return response($response, 200); } </code> The logout method is not working for after i tested the login method and the user is authenticated so i copied the token and use it in postman but my authorization tab does not have Bearer
Olanrewaju Olayinka Ahmed
Now works for me after i moved the logout route inside the auth:api middleware
Juan Francisco Giordana
Postman
Layo Folaranmi
My mistake, will edit the post to reflect this.
Layo Folaranmi
Thanks for reading through! Most appreciated!
Layo Folaranmi
Sorry for the late reply but as Olanrewaju Olayinka Ahmed said, move the logout route to the "auth:api" middleware group and it should work. I'd work to edit the post to reflect that.
Layo Folaranmi
Hi Ihtisham Ahmad, I get your point. I do not have a factual answer to that, but based on personal bias I'd say the difference in time is significantly inconsequential. If you don't use rest API's you would still use a model to communicate with the db and then spend some time manipulating it before sending it to your view. Meanwhile using rest API's you get the information from the db, then pass it to your SPA which then manipulates it and displays it. You see the process is very similar, I think the efficiency of each method lies with the programmer and how he/she pulls data from the db and manipulates it not with the software architecture used. Also as a lot of big companies use rest APIs, if it made applications significantly slower, they will have stopped. Gmail is an SPA and it doesn't seem slow does it? Thanks for your question though, before this I haven't given much thought to the speed of SPAs+ rest APIs, so, great question!
Layo Folaranmi
Hi, sorry for the late reply, but forcing json only means your application will always return a json output. API resources on the other hand is a way to abstract the output, it also allows you to manipulate the output. Without using API resources, if you pull data from the db, the rest API returns the data as-is to the user (a db field of "user_name" returns as "user_name" in the API response), if you use API resources, you can manipulate the data returned to look different from the data in the db, so a db field of "user_name" can be "username" in the API response. I hope I explained it clearly. Great question though!
Layo Folaranmi
You welcome! Thanks for taking the time to read through!
Layo Folaranmi
Thanks aito77 !
Layo Folaranmi
Hi Salvador you can use mailtrap. You have to edit your .env file reflect mailtrap's SMTP config though.
Osama Diab
thank you so much really
Salvador Sanchez
Thanks Saludos desde CDMX
Demahou Florentin
Hello Layo . Thank you for the clearful tutorial. I use smtp service for password reset. but if i call /password.reset it returns crsf mismatch. is there any screenshot of how you call it using postman ?
James Young
You probably don't want password confirmation on login, only register. Also, <code>Schema::defaultStringLength(191);</code> is a hack and is only applicable where MySQL is being used and the character set is utf8mb4, which assumes 4 bytes for each character. Laravel assumes the character set is utf8mb4, which is of no practical benefit in most cases. It handles emojis and extras like that. Otherwise set your charset to utf8 and this problem goes away. You can change these settings in your config/database.php file: <code> 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', </code> Replace this with: <code> 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', </code> if you are using MySQL and have problems trying to run migrations and experience the 'specified key was too long' error. This is a good tutorial, it should be expanded to include more resources than just articles (and how about something more interesting than articles? Also, modify the API to accept JSON and still be able to run a validator on the input.
Demahou Florentin
Hello Layo . Thank you for the clearful tutorial. I use smtp service for password reset. but if i call /password.reset it returns crsf mismatch. is there any screenshot of how you call it using postman ?
Layo Folaranmi
Hi Demahou, I'd send the screenshots, if I come across your error, I'd also update the blog post to show a fix for it. Thanks for the feedback!
Aloh Benjamin Stanley
Thanks Mr Layo. This tutorial was helpful. I was reading about the passport on Laravel 7.x and I came about password grant and one other kinda grant. Can you elaborate what it means?
Alan Hidalgo Pagoto
Very nice article. Appreciated it @layofolaranmi:disqus . Thank you.
Toni
Hi...a fresh Laravel 7 installation commes with build in cors and middleware ( \Fruitcake\Cors\HandleCors::class). Configure it in config cors.php. The Article is very nice and helped me alot :) thank you
Stephen D. Scotti
Nice tutorial. All pretty new to me, but looks like it is mostly working. I am using MySQL, so I had to use: php artisan passport:keys --length=512 --force to change the length of the key because it was too large for my MySQL table (MySQL said: Specified key was too long; max key length is 3072 bytes) Also, I presume that the api_token) is supposed to be saved to the database after a user logs in or registers ? It isn't doing that for me. I was able to test the routes using Postman by just manually putting the api_token into the database and testing that way. Wondering how to fix that. Also, How hard is it to integrate some Vue.js pages into Laravel ?
Rav Olivar
Hi Layo, how can I integrate the front-end to this API authentication? Do you have tutorial for that? Thanks
Fooz Barakat
I got this error when I tried to create user, any one knows what is wrong!
Fooz Barakat
https://uploads.disquscdn.com/images/a79128a07272dfe93014df2b4a9939eb730a80fcf62b0510a2c3b027a15fefc1.png
Fooz Barakat
https://uploads.disquscdn.com/images/7d5ae824430e0b1d4d95071c74257f58cb89a7ffc0483187d43d70ac7233762c.png I got this error instead of getting the token as response, and the new user is created in the database, I also got the same error when I tried to login, I don't get the token as response. please help!
vim kndll
sir how to protect that bearer token from other ...If the peoople get that token from local storage then they can impersonating me ...Have you thought about security
marik_v
verry nice. thanks
Junior Frogie
I got error in AdminAuth "message": "Trying to get property 'type' of non-object", "exception": "ErrorException",
Fadli Saad
👏 For the author. Good basic tutorial for starting up with laravel. Appreciate if you can update this for laravel 8. As it seem very different from laravel 7
cocl jr
What will happen when token expired?
cocl jr
why my logout redirect to login page. no json response.
cocl jr
$request['remember_token'] = Str::random(10); What is the purpose of this? I don't see any changes in database.
justice
Can you be explaining your codes
Jehu Cummings
Try: <code>$tokens = Auth::user()->tokens; foreach($tokens as $token) { $token->revoke(); }</code>
victor
First one I find not using auth()->attempt() .... Nice man
Tharindu Lakshitha
How to generate refresh token along with access token ?
Thet Paing Htut
Hello Bro! I'm getting null for user object in authorization with login token. https://uploads.disquscdn.com/images/f0f1f690ed19035acc22ced1c1a866bdd33a3b9190ac5632f77941432e46bcef.png
Ralph Höglund
Great article. Can you please give me a short description on using a login.blade, logout.blade and when logged in the route to a navigation blade. I have problems to get that to work. Thank you, Ralph in Sweden
dgloria
Hi, this is brilliant! I can't thank enough for you to write this. I got to the point where I send the client credentials and get the token, but then I can't make the token work in a GET request, it returns 401 all the time. I can't understand why. it might be the route, the middleware, or I am not sending the required headers, but there is no other error message than 401. Please help.
dgloria
This article is good and useful as is. I bet he have spent more time writing it than you did to comment on it, so at least please appreciate that he did. Any addition to this article would make it more difficult for non-engineers like me, and gave chance to more errors in the setup. I was happy if I could make it work, no need to put more interesting stuff. However you can always write a better article, there are plenty of space on the internet for your genuine ideas.
dgloria
Not very different, however I got issue accepting the token. Maybe that's why, mine is L8.
dgloria
Hi Guys, anyone managed to add the password reset function to the router?
Layo Folaranmi
Do you still have this issue? Could you post a screenshot of the error?
dgloria
Hi, nope, I've spent weeks to build the app, and it works now. Got all raked together from several sites. Now I'm at the password reset, and trying to figure out how to setup the api route and what to write in the apiAuthController's reserPassword function. :) Works like charm so far, but not easy to make it work with a vue frontend. Thank you.
Layo Folaranmi
Thanks a lot for your nice comments! For the resetPassword function, you can try to copy Laravel's built in reset password functionality from Laravel Breeze, then modify it to work with api tokens. On the other hand, if you check the git repo for this tutorial, there is some code in <code>App\Http\Controllers\Auth\ForgotPasswordController</code> and <code>App\Http\Controllers\Auth\ResetPasswordController</code> that might be of help. Apologies that I can't go in-depth on the solution, it would be a super long write.
dgloria
Hi, yes, that's the plan. Super great work from you. Thanks.
Tasnim Tarannoom
Hello Sir, It's an awesome tutorial. But my password reset mail is not working. It's getting sendResetLinkFailedResponse. Can you tell me why please
comments powered by Disqus