Laravel Passport Authentication with RSA (Enterprise-Grade API Security)

Laravel Passport Authentication with RSA (Enterprise-Grade API Security)

This tutorial shows how to build a secure, enterprise-grade authentication system in Laravel using Laravel Passport (OAuth2) combined with RSA encryption for login passwords.

Laravel Passport already uses RSA internally to sign OAuth2 tokens.
In this guide, we add RSA encryption for login passwords to protect credentials in transit.

🧠 How It Works (High-Level Flow)

Frontend └── Encrypt password using RSA Public Key Backend ├── Decrypt password using RSA Private Key ├── Authenticate user └── Passport issues OAuth2 access token (RSA signed)

✅ What This Tutorial Covers

  • Laravel Passport (OAuth2 authentication)

  • RSA public / private key encryption

  • Secure Register, Login, Logout APIs

  • RSA-encrypted login passwords

  • Token-based API authentication

  • Protected API routes

  • Production-ready best practices

📦 Requirements

  • PHP 8.1+

  • Laravel 10 / 11 / 12

  • Composer

  • OpenSSL enabled (PHP & CLI)

  • Postman (for API testing)

  • Basic Laravel knowledge

1️⃣ Create a New Laravel Project

composer create-project laravel/laravel laravel-passport-auth

Open the project in VS Code:

code laravel-passport-auth

2️⃣ Install Laravel API Scaffolding

php artisan install:api

✅ This enables API middleware and prepares Laravel for token-based authentication.

3️⃣ Configure Database

Edit .env:

DB_DATABASE=passport_api DB_USERNAME=root DB_PASSWORD=

Run migrations:

php artisan migrate

4️⃣ Install Laravel Passport

Install Passport:

composer require laravel/passport

Run Passport migrations:

php artisan migrate

Install Passport (generates RSA keys automatically):

php artisan passport:install

📁 Passport RSA Keys (AUTO-GENERATED)

storage/ ├── oauth-private.key 🔐 DO NOT COMMIT └── oauth-public.key 🔓

👉 Used internally by Passport to sign OAuth2 tokens.

5️⃣ Generate RSA Keys for Login Encryption

These keys are ONLY for encrypting login passwords.

mkdir -p storage/rsa

Generate private key:

openssl genrsa -out storage/rsa/private.pem 2048

Generate public key:

openssl rsa -in storage/rsa/private.pem -pubout -out storage/rsa/public.pem

📁 RSA Login Keys Structure

storage/rsa/ ├── private.pem 🔐 Keep secret! Do NOT commit └── public.pem 🔓 Safe to share with frontend

6️⃣ Configure API Auth Guard

Edit config/auth.php:

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

7️⃣ Update User Model

Edit app/Models/User.php:

use Laravel\Passport\HasApiTokens; class User extends Authenticatable { use HasApiTokens, Notifiable; protected $fillable = [ 'name', 'email', 'password', ]; protected $hidden = [ 'password', 'remember_token', ]; }

8️⃣ Create Authentication Controller

Generate controller:

php artisan make:controller Api/AuthController

Edit app/Http/Controllers/Api/AuthController.php:

<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; class AuthController extends Controller { private string $privateKey; public function __construct() { $this->privateKey = file_get_contents(storage_path('rsa/private.pem')); if (!$this->privateKey) { throw new \Exception('RSA private key not found or not readable'); } } // Register user public function register(Request $request) { $data = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users', 'password' => 'required|string|min:6|confirmed', ]); User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); return response()->json([ 'message' => 'User registered successfully' ], 201); } // Login with RSA-encrypted password public function login(Request $request) { $request->validate([ 'email' => 'required|email', 'password' => 'required|string', ]); $encryptedPassword = base64_decode($request->password); $decryptedPassword = null; if (!openssl_private_decrypt( $encryptedPassword, $decryptedPassword, $this->privateKey )) { return response()->json(['message' => 'Password decryption failed'], 400); } if (!Auth::attempt([ 'email' => $request->email, 'password' => $decryptedPassword ])) { return response()->json(['message' => 'Invalid credentials'], 401); } $user = Auth::user(); $token = $user->createToken('API Access Token'); return response()->json([ 'user' => $user, 'access_token' => $token->accessToken, 'token_type' => 'Bearer', ]); } // Get profile public function profile(Request $request) { return response()->json($request->user()); } // Logout public function logout(Request $request) { $request->user()->token()->revoke(); return response()->json([ 'message' => 'Logged out successfully' ]); } }

9️⃣ Define API Routes

Edit routes/api.php:

use App\Http\Controllers\Api\AuthController; Route::prefix('auth')->group(function () { Route::post('/register', [AuthController::class, 'register']); Route::post('/login', [AuthController::class, 'login']); Route::middleware('auth:api')->group(function () { Route::get('/profile', [AuthController::class, 'profile']); Route::post('/logout', [AuthController::class, 'logout']); }); });

▶️ Run the Application

php artisan serve

API Base URL:

http://localhost:8000

🚀 Testing with Postman

1️⃣ Register User

POST /api/auth/register

{ "name": "StarCode Kh", "email": "starcodekh@example.com", "password": "12345678", "password_confirmation": "12345678" }

✅ Check success response
✅ Verify user exists in database

2️⃣ Login User (RSA Encrypted)

POST /api/auth/login

{ "email": "starcodekh@example.com", "password": "ENCRYPTED_PASSWORD_BASE64" }

📌 Password must be encrypted using storage/rsa/public.pem

Response:

{ "user": {...}, "access_token": "token_here", "token_type": "Bearer" }

3️⃣ Get Profile

GET /api/auth/profile Authorization: Bearer {access_token}

4️⃣ Logout

POST /api/auth/logout Authorization: Bearer {access_token}

Token is revoked immediately.

🔁 Authentication Flow Summary

  • Register → Password hashed

  • Login → Password encrypted with RSA public key

  • Backend → Decrypt using private key

  • Passport → Issues OAuth2 token (RSA signed)

  • Access protected routes using Bearer token

  • Logout → Token revoked

⚠️ Common Errors & Fixes

❌ Personal access client not found

php artisan passport:install

✅ Production Best Practices

  • Always use HTTPS

  • Never commit private keys

  • Protect oauth-private.key

  • Protect rsa/private.pem

  • Use short-lived access tokens

  • Enable refresh tokens if needed

  • Rotate RSA keys periodically

  • Restrict token scopes

🎯 Final Result

You now have a secure, scalable, enterprise-ready Laravel authentication system using:

  • 🔐 RSA-encrypted login passwords

  • 🔑 OAuth2 with Laravel Passport

  • 🛡 Secure API authentication best practices

Want the full source code?

Download the complete Laravel Passport Authentication with RSA example on my GitHub repo here.

Souy Soeng

Souy Soeng

Hi there 👋, I’m Soeng Souy (StarCode Kh)
-------------------------------------------
🌱 I’m currently creating a sample Laravel and React Vue Livewire
👯 I’m looking to collaborate on open-source PHP & JavaScript projects
💬 Ask me about Laravel, MySQL, or Flutter
⚡ Fun fact: I love turning ☕️ into code!

Post a Comment

CAN FEEDBACK
close