Perfect. Let’s go step-by-step and explain Microservice-to-Microservice authentication using the client_credentials
grant, one client per service, and JWT public key verification, in a clean, scalable way.
🎯 Goal
Let one microservice securely call another microservice using Laravel Passport, without storing all other services’ client secrets in .env
.
🧠 Core Concepts
| Concept | Purpose |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| client_credentials
grant | Used for machine-to-machine (service-to-service) auth. No user is involved. |
| One client per service | Each MS gets its own OAuth Client ID/Secret pair. |
| Token verification via public key | Instead of verifying who issued the token by checking secrets, verify the JWT token signature using oauth-public.key
. |
✅ Step-by-Step Implementation
✅ STEP 1: Setup a Central Authentication Service
Create one microservice (e.g., auth-service
) that:
- Runs Laravel Passport
- Manages OAuth clients
- Issues tokens for other services using the
client_credentials
grant
📌 Important: This service does not handle UI logins — it's only for issuing tokens for microservices.
✅ STEP 2: Register One Client Per Microservice
In auth-service
, run:
php artisan passport:client --client
Do this once for each MS.
Example for ms_admin
:
Client ID: 5
Client Secret: xxxxxxxxxxxxx
Repeat for:
ms_college
ms_doctor
- etc.
You will now have 10 clients in auth-service
.
✅ STEP 3: Token Request from Calling Microservice
In ms_admin
, when it needs to call ms_doctor
, it does:
POST https://auth.myhospitalnow.com/oauth/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "5", // ms_admin's ID
"client_secret": "xxxxxxxxxxxx",
"scope": "*"
}
✅ Response:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGci...",
"expires_in": 3600,
"token_type": "Bearer"
}
✅ Now ms_admin
sends this token as:
GET https://myhospitalnow.com/doctors/api/some-data
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGci...
✅ STEP 4: Token Verification in Receiving Microservice (e.g., ms_doctor)
ms_doctor
should:
- NOT care who the caller is
- Just verify the JWT token using the shared
oauth-public.key
🔐 In ms_doctor
, verify the token:
- Use
lcobucci/jwt
or firebase/php-jwt
- Load the public key from
/shared/oauth-public.key
- Validate signature, expiration, etc.
No need to store any client secrets in ms_doctor
.
✅ STEP 5: Add Middleware to Auto-Verify Tokens
In each service (e.g., ms_doctor
), add a middleware like:
public function handle($request, Closure $next)
{
$token = $request->bearerToken();
$publicKey = file_get_contents(storage_path('oauth-public.key'));
// Validate the JWT here (signature, expiration, etc.)
if (!JwtValidator::isValid($token, $publicKey)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $next($request);
}
You can use libraries like firebase/php-jwt
or lcobucci/jwt
to validate JWT tokens in each MS.
✅ Summary Architecture
[ms_admin] --(get token with client_credentials)--> [auth-service]
|
|--(Authorization: Bearer <token>)--> [ms_doctor]
|
|--(Verify JWT via oauth-public.key)
🧰 What Each .env Should Contain
For ms_admin
:
AUTH_URL=https://auth.myhospitalnow.com/oauth/token
OAUTH_CLIENT_ID=5
OAUTH_CLIENT_SECRET=xxxx
For ms_doctor
:
OAUTH_PUBLIC_KEY_PATH=/shared/oauth-public.key
📌 No need to store all 10 services' credentials anymore.
✅ Advantages
| Benefit | Explanation |
| ----------- | -------------------------------------------------------------------- |
| 🔐 Secure | Only each service knows its own credentials. Others don’t need them. |
| 🔁 Scalable | Add/remove services without editing 10 .env
files |
| 🧼 Clean | Public key verification is stateless and doesn’t need DB lookups |
| 🚀 Fast | No need to make token validation calls — just validate JWT locally |
Would you like:
- A working Laravel middleware example for token verification?
- A script to auto-generate the 10 clients from
auth-service
?
- A diagram showing this flow?
Let me know — happy to provide any or all!