-
Notifications
You must be signed in to change notification settings - Fork 0
Forwarding JWT Token
This feature introduces secure JWT token propagation from the main backend application to the legacy API. It ensures that the authenticated user's identity and roles are preserved across service boundaries, enabling consistent authorization and auditing throughout the system.
-
JWT Injection into Outbound Requests
A new Spring component,JwtForwarderRequestInitializer, is responsible for injecting the current user's JWT into theAuthorizationheader of outbound HTTP requests targeting the legacy API. -
RestClient Configuration
The legacy API'sRestClientbean is configured to use theJwtForwarderRequestInitializer, ensuring all requests carry the bearer token. -
User Context Extraction
A helper class,LoggedUserHelper, safely extracts the JWT from Spring Security'sSecurityContextHolder, making it reusable across components. -
Legacy API Security Enablement
The legacy service is now configured as a Spring Security resource server, capable of validating JWTs and enforcing access control based on token claims. -
Testing Enhancements
Integration tests now use@WithMockJwtto simulate authenticated requests and validate token propagation and access control logic.
-
Spring Security Compatibility
By leveraging Spring Security's built-in support for JWT-based authentication, the system ensures robust and standardized security practices. -
Token Consistency
Forwarding the same JWT across services maintains a unified authentication context, eliminating discrepancies between systems. -
Minimal Intrusion
The implementation avoids custom session bridging or proprietary headers, relying instead on standard HTTP authorization mechanisms.
-
Cross-Service Authorization
The legacy API can now enforce role-based access control using the same JWT issued by the identity provider, allowing for fine-grained filtering based on user roles or identity. -
Improved Auditability
Actions performed in the legacy system can be reliably traced back to the authenticated user, enhancing accountability and compliance. -
Simplified Architecture
Removes the need for custom headers or session replication logic, reducing complexity and potential security pitfalls. -
Future-Proofing
Aligns the legacy system with modern authentication standards, paving the way for smoother integration with other services or identity providers.
Absolutely! Here's a Mermaid sequence diagram that illustrates how JWT forwarding works between the main backend and the legacy API, based on your PR implementation:
Got it, Paulo! Based on the actual implementation from the PR’s “Files changed” tab, here’s the real code that forwards the JWT from the backend to the legacy service:
This helper extracts the JWT from the current security context:
public String getToken() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
if (authentication instanceof JwtAuthenticationToken jwtAuth) {
return jwtAuth.getToken().getTokenValue();
}
return null;
}This Spring component injects the JWT into outbound HTTP requests:
@Component
@RequiredArgsConstructor
public class JwtForwarderRequestInitializer implements ClientHttpRequestInitializer {
private final LoggedUserHelper userHelper;
@Override
public void initialize(ClientHttpRequest request) {
request.getHeaders()
.add(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", userHelper.getToken()));
}
}The legacy API client is configured to use the JWT forwarder:
@Bean
public RestClient legacyApi(
HrsConfiguration configuration,
JwtForwarderRequestInitializer jwtForwarder
) {
return RestClient
.builder()
.baseUrl(configuration.getLegacyApi().getAddress())
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.requestInitializer(jwtForwarder)
.build();
}sequenceDiagram
participant User
participant Frontend
participant Backend
participant LegacyAPI
User->>Frontend: Login & receive JWT
Frontend->>Backend: Request with JWT
Backend->>LoggedUserHelper: Extract JWT from SecurityContext
Backend->>JwtForwarderRequestInitializer: Add JWT to Authorization header
Backend->>LegacyAPI: Request with forwarded JWT
LegacyAPI->>Spring Security: Validate JWT
LegacyAPI->>LegacyAPI: Apply role-based filtering
LegacyAPI-->>Backend: Response
Backend-->>Frontend: Response
Frontend-->>User: Display filtered data