Integrating JWT Authentication with External Auth API in Laravel 12 and Native PHP
Ron Chaplin
How we transformed a traditional Laravel authentication system to work with an external JWT-based auth server
The Challenge
We started with a standard Laravel 12 application using the built-in session-based authentication system. However, our requirements called for integrating with an external authentication API that uses JWT tokens. This meant we needed to completely overhaul how authentication works in our application while maintaining the familiar Laravel authentication patterns that developers expect.
The Solution Overview
Instead of storing user credentials locally and managing sessions, our application now:
- Authenticates users via external API calls
- Stores JWT tokens in encrypted sessions
- Uses a custom authentication guard to validate tokens
- Returns proper User model instances for seamless integration
Key Components Implemented
1. AuthApiService - The API Communication Layer
We created app/Services/AuthApiService.php to handle all communication with our external auth server. This service provides methods for:
- User login and registration
- Password reset workflows
- Token refresh and validation
- User profile retrieval
- Account management
The service abstracts away the HTTP communication details and provides a clean interface for our authentication components.
2. Custom JWT Authentication Guard
The heart of our integration is the custom JwtGuard class (app/Guards/JwtGuard.php). This guard:
- Implements Laravel's Guard interface for seamless integration
- Validates JWT tokens by calling the external API
- Returns proper User model instances instead of plain objects
- Handles token expiration and automatic cleanup
- Caches user data to avoid repeated API calls during a request
3. Updated Livewire Authentication Components
We modified all the existing Livewire auth components to use our API service:
- Login Component: Calls external API and stores JWT tokens
- Registration Component: Creates accounts via API
- Password Reset: Handles forgot/reset password flows through API
- Logout Action: Properly invalidates tokens on the auth server
4. Configuration Updates
Several configuration changes were needed:
- Auth Guard Configuration: Changed from 'session' to 'jwt' driver
- Service Configuration: Added auth API base URL configuration
- Provider Registration: Registered our custom AuthServiceProvider
Technical Implementation Details
Authentication Flow
- User submits credentials via Livewire login component
- AuthApiService makes API call to external auth server
- JWT token is returned and stored in encrypted session
- JwtGuard validates token on subsequent requests
- User model is created from API profile data
Token Management
- Storage: JWT tokens are stored in Laravel's encrypted session storage
- Validation: Each request validates the token with the auth API
- Refresh: Automatic token refresh (when implemented on API side)
- Cleanup: Invalid tokens are automatically removed from session
User Model Integration
Our JwtGuard creates proper User model instances from API data, ensuring:
- All existing User methods work (like
initials()) - Relationships can be added if needed
- Laravel conventions are maintained
- No database queries for authentication
Benefits of This Approach
1. Centralized Authentication
All authentication logic is handled by a single external service, making user management consistent across multiple applications.
2. Scalability
The auth server can handle authentication for multiple applications without duplicating user data.
3. Security
- JWT tokens provide stateless authentication
- No local password storage
- Centralized security policies
- Token-based access control
4. Developer Experience
- Familiar Laravel authentication patterns
- Existing code continues to work
- Standard
auth()helper functions - Seamless Livewire integration
Configuration Required
Environment Variables
AUTH_API_BASE_URL=http://localhost:8000
Service Configuration
The auth API service is configured in config/services.php with the base URL for the external authentication server.
Authentication Guard
The default 'web' guard is configured to use our custom 'jwt' driver instead of the standard 'session' driver.
Future Enhancements
Token Refresh
Implement automatic token refresh to handle expired tokens gracefully without requiring user re-authentication.
Offline Support
Add local caching of user data for limited offline functionality in the desktop application.
Role-Based Access Control
Extend the system to handle roles and permissions from the external auth API.
Multi-Tenant Support
Add support for tenant-specific authentication if required.
Conclusion
This integration successfully bridges Laravel's traditional authentication system with a modern JWT-based external auth API. The implementation maintains Laravel's conventions while providing the flexibility and scalability benefits of centralized authentication.
The key to success was creating a custom authentication guard that properly implements Laravel's Guard interface while handling the JWT token lifecycle. This approach ensures that existing Laravel authentication patterns continue to work while the underlying authentication mechanism is completely different.
For developers working on similar integrations, the most important considerations are:
- Proper Guard implementation that follows Laravel conventions
- Robust error handling for API communication failures
- Secure token storage using Laravel's encrypted sessions
- Maintaining User model compatibility for existing code
This architecture provides a solid foundation for JWT-based authentication in Laravel applications while maintaining the developer experience that makes Laravel so productive.