I am adding a WebFilter to perform JWT authentication inside of SecurityWebFilterChain. We encode a lot of non-auth related information in the JWT that is needed by many of our API endpoints, so I need to be able to extract information out of the JWT and access that info in my API handler methods (eg, LoginController.java). What is the best pattern to achieve this?
Here is my SecurityWebFilterChain showing the WebFilter authentication:
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http
.authorizeExchange()
.pathMatchers("/login", "/")
.authenticated()
.and()
.addFilterAt(basicAuthenticationFilter(), SecurityWebFiltersOrder.HTTP_BASIC)
.authorizeExchange()
.pathMatchers("/adm")
.authenticated()
.and()
.addFilterAt(basicAuthenticationFilter(), SecurityWebFiltersOrder.HTTP_BASIC)
.authorizeExchange()
.pathMatchers("/api/**")
.access(authorizationManager)
.and()
.addFilterAt(bearerAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.build();
}
Here is where I would like to access the claims, in LoginController.java:
@RestController()
@RequestMapping(value = "/login")
public class LoginController {
private final UserMongoRepository repository;
@Autowired
public LoginController(UserMongoRepository repository) {
this.repository = repository;
}
@PostMapping("")
public Mono<User> login(@RequestBody User post,
@RequestParam String user_id,
@RequestParam String username) {
//Need to access information from JWT claims here
return this.repository.findById(user_id);
}
}
I would create a customised Authentication
object and store the required information inside it.
For the user-related data , store inside its Principal
.For the non user-related data , sounds like Details
is a good place to store.
Many built-in AuthenticationProvider
will create a UserDetails
and store to Principal
. That means you can consider just create a customsied UserDetails
if you are using those built-it AuthenticationProvider
.
So depending on how you implement the authentication logic , you need to customise the related AuthenticationProvider
or Filter
etc. The aim is to access the HttpServletRequest
, get JWT from the HTTP header , parse the JWT , setup and configure this customised Authentication
object and set it to the SecurityContext
:
SecurityContextHolder.getContext().setAuthentication(authenication);
To access this Authentication
object in Controller , you can use :
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
CurrentUser user = (CurrentUser) auth.getPrincipal();
CurrentRequestDetail detail= (CurrentRequestDetail) auth.getDetails();
/** CurrentUser and CurrentRequestDetail is the customised Principal and Details**/
If you need to access [Principal
] only , you can use @AuthenticationPrincipal
:
@PostMapping("")
public Mono<User> login(@RequestBody User post,
@RequestParam String user_id,
@RequestParam String username,
@AuthenticationPrincipal CurrentUser currentUser) {
//Need to access information from JWT claims here
return this.repository.findById(user_id);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With