(EN) Laravel 8: Adding Passport Auth to API
Installation
The first steps will be the installation steps for a new laravel project:
sudo service mysql start //if mysql is not running
composer create-project laravel/laravel my-project-name
cd my-project-name
php artisan key:generate
php artisan serve
Navigate to http://localhost:8000 to check if your server is up and running.
Database
go to the .env
file to check your database settings.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
If you are running on Ubuntu I do not recommend using the root
user.
Try accessing MySQL and creating a new one, unless you already have one.
See more details here.
sudo mysql -u root //sudo is necessary unless settings are changed.
mysql> USE mysql;
mysql> CREATE USER 'new_user'@'localhost' IDENTIFIED BY 'new_password';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'new_user'@'localhost';
mysql> UPDATE user SET plugin='mysql_native_password' WHERE User='new_user';
mysql> FLUSH PRIVILEGES;
mysql> exit;
sudo service mysql restart
Then change user and password in the .env
file.
DB_USERNAME=new_user
DB_PASSWORD=new_password
Set up the passport
Run:
composer require laravel/passport
php artisan migrate
php artisan passport:install
php artisan passport:client --personal
Go to app/User.php
and remove the following if found:
use Laravel\Sanctum\HasApiTokens;
Then add Laravel\Passport\HasApiTokens.
Making if finally look like this:
<?php
namespace App;
...
use Laravel\Passport\HasApiTokens; // include this
class User extends Authenticatable
{
use HasApiTokens, ... ; // update this line
...
}
Switch to the app/Providers/AuthServiceProvider
file and chenge the following three lines:
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport; // add this
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy', // uncomment this line
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes(); // Add this
}
}
In the app.php
file add the passport service provider:
<?php
return [
...
'providers' => [
...
Laravel\Passport\PassportServiceProvider::class, //this line
],
...
];
Finally switch to the config/auth
file and change/add the 'api' section like so:
<?php
return [
...
'guards' => [
'web' => [
...
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
],
...
];
Change/Create Users table
Now create your tables (follow the laravel guide if necessary for this step.
If you decided to directly add to the already existent User table and had to run
php artisan migrate:fresh
remember to run
php artisan passport:install --force
php artisan passport:client --personal
afterwards.
Login/Register
Back to the terminal run:
php artisan make:controller API/AuthController
This will create a file in app/Http/Controllers/API/AuthController.php
.
Change it as following:
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
class AuthController extends Controller
{
public function register(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|max:55',
'email' => 'email|required|unique:users',
'password' => 'required|confirmed'
]);
$validatedData['password'] = bcrypt($request->password);
$user = User::create($validatedData);
$accessToken = $user->createToken('authToken')->accessToken;
return response([ 'user' => $user, 'access_token' => $accessToken]);
}
public function login(Request $request)
{
$loginData = $request->validate([
'email' => 'email|required',
'password' => 'required'
]);
if (!auth()->attempt($loginData)) {
return response(['message' => 'Invalid Credentials']);
}
$accessToken = auth()->user()->createToken('authToken')->accessToken;
return response(['user' => auth()->user(), 'access_token' => $accessToken]);
}
}
Now go to the routes/api.php
and create yout login/register routes:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\AuthController;
use App\Http\Controllers\API\UserController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::post('register', [AuthController::class,'register']);
Route::post('login', [AuthController::class,'login']);
...
Now you're all set for your api's!
To create an api that necessitates authentication add the auth:api
middleware:
Route::get('users', [UserController::class,'index'])->middleware('auth:api'); //example code
restart to update your .env
.
Use Ctrl+C
to stop the service if still running:
php artisan cache:clear
php artisan route:clear
php artisan config:clear
php artisan serve
check your routes using
php artisan route:list
In my case I have the routes:
POST http://127.0.0.1:8000/api/login
POST http://127.0.0.1:8000/api/register
GET http://127.0.0.1:8000/api/users
Set up redirection route
To set up the redirection route add the following class unauthenticated inside app/Http/Middleware/Authenticate
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
// new class
protected function unauthenticated($request, array $guards)
{
abort(response()->json(
[
'api_status' => '401',
'message' => 'UnAuthenticated',
], 401));
}
}
Discussion