How to implement authentication & authorization between microservices & API Gateway using Laravel
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Securing Microservices: Implementing Authentication and Authorization with Laravel and an API Gateway
Implementing robust security across a distributed system of microservices is one of the most complex challenges in modern software architecture. When you have an API Gateway, a dedicated User Service, and several independent services, the key is establishing a clear chain of trust for user identity and permissions.
The scenario you've described—where authentication happens in one service (User Service) and authorization needs to flow to others—is very common. As a senior developer, the right approach involves centralizing Authentication at the gateway and leveraging stateless tokens (like JWTs) for distributed Authorization.
Here is a comprehensive breakdown of the right way to implement this pattern using Laravel principles.
The Core Principle: Separation of Concerns (AuthN vs. AuthZ)
Before diving into the code, it’s crucial to distinguish between Authentication and Authorization:
- Authentication (AuthN): Verifying who the user is (e.g., checking if the provided token is valid and belongs to an existing user). This happens primarily at the entry point (API Gateway).
- Authorization (AuthZ): Determining what the authenticated user is allowed to do (e.g., checking if User X has the 'admin' role before accessing Service Y's endpoint). This should happen within the microservices themselves.
Step 1: Centralizing Authentication with JWTs
Since you are already using laravel/passport in your User Microservice, you are perfectly set up to generate secure JSON Web Tokens (JWTs). The token itself will carry the necessary identity information for downstream services.
Structuring the JWT Payload
The key to passing authorization context is what you put inside the token payload. Do not store sensitive data here; focus on claims needed for authorization.
Best Practice: Include the User ID and essential Roles/Scopes.
// Example structure of the payload generated by your Laravel Passport setup
$payload = [
'sub' => $user->id, // Subject: The user ID
'roles' => ['admin', 'billing'], // Authorization context
'iat' => time(), // Issued at
'exp' => time() + (60 * 60) // Expiration time
];
$token = JWT::encode($payload, $user->token_secret);
By including roles in the token, you are essentially pushing the authorization context to the client, which the gateway can then use for preliminary checks.
Step 2: The Role of the API Gateway (Authentication Enforcement)
The API Gateway acts as the single point of entry and the primary gatekeeper for authentication.
- Token Reception: The Gateway receives the request with the JWT in the
Authorizationheader. - Validation: The Gateway validates the token's signature, expiry, and issuer using the public key or shared secret (which should be managed securely). If validation fails, the request is immediately rejected (401 Unauthorized).
- Information Propagation: If the token is valid, the Gateway extracts the necessary user claims (e.g.,
user_idandroles) from the payload. - Header Injection: The Gateway then injects this validated information into a new, internal header before forwarding the request to the target microservice.
# Request sent by API Gateway to the downstream service
GET /api/products
Authorization: Bearer [VALID_JWT]
X-User-ID: 12345 // Injected by the Gateway
X-User-Roles: admin // Injected by the Gateway
This process ensures that downstream services trust the user context because the token was cryptographically signed and validated by a trusted entity (the gateway).
Step 3: Implementing Authorization in Microservices
Now, how do the five other microservices handle authorization without knowing the full database? They rely entirely on the data passed by the API Gateway.
- Trust the Header: The microservice trusts that if it receives a request with a valid token signed by the system, the claims in the header are accurate representations of the user's permissions.
- Internal Policy Check: Inside the service logic, when an endpoint is hit (e.g.,
/products/delete/{id}), the service performs its specific authorization check:
// Inside a Laravel Controller within a Microservice
public function deleteProduct(Request $request, $id)
{
// 1. Check if the request has the required user context from the header
$userId = $request->header('X-User-ID');
$requiredRole = 'admin';
// 2. Perform Authorization check based on extracted claims
if (!in_array($request->header('X-User-Roles'), ['admin', 'owner'])) {
abort(403, 'Unauthorized action.'); // User lacks permission
}
// 3. Proceed with the business logic (e.g., delete the product)
// ... actual deletion logic
}
Conclusion: A Secure and Scalable Blueprint
By adopting this layered approach—using Laravel Passport for token generation, the API Gateway for centralized authentication enforcement, and JWTs carrying essential roles for downstream authorization—you achieve a scalable and secure microservices architecture. This pattern ensures that your services remain loosely coupled while maintaining strict security boundaries. As you build these systems, remember that leveraging frameworks like those provided by laravelcompany.com provides the perfect foundation for building these robust API layers.