Issue
I have googled the depths of the internet, but can't find a decent answer to this anywhere. How can I access the claims within a JWT in a spring service?
We have a standalone authentication service that issues a JWT. I am building a separate spring service that needs to use this Jwt. I have the public key of the private key that was used to sign the JWT and have pieced together enough tutorials to be able to verify the JWT (with the public key) and allow access to the controllers I want.
In my service, I now need to extract the userId claim in the JWT (among others) so that I can call my DB with it, etc.
https://www.baeldung.com/spring-security-oauth-jwt (Section 5.1) seemed to be the most relevant search result:
@GetMapping("/user/info")
public Map<String, Object> getUserInfo(@AuthenticationPrincipal Jwt principal) {
Map<String, String> map = new Hashtable<String, String>();
map.put("user_name", principal.getClaimAsString("preferred_username"));
map.put("organization", principal.getClaimAsString("organization"));
return Collections.unmodifiableMap(map);
}
However when my code runs, principal is always null
. I assume there is some other interface I need to implement somewhere.
All paths in my app require authentication, so I have:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// http.antMatcher("/**").authorizeRequests().anyRequest().permitAll();
http.csrf().disable()
.authorizeRequests()
.antMatchers("/**").authenticated();
}
Solution
@EnableResourceServer
is part of spring-security-oauth
which is end of life, and you should migrate away as it's not recommended for new projects.
Check out the reference for the new oauth2-resource-server support, which should allow @AuthenticationPrincipal Jwt principal
to work correctly in your controller. Also, see this repository's SecurityConfiguration, or follow along with the video presentation from SpringOne 2021.
When reading the reference docs, you would be most interested in overriding Spring Boot's configuration to provide your own @Bean
of JwtDecoder
using your available public key.
You can also optionally provide your own @Bean
of JwtAuthenticationConverter
or Converter<Jwt, AbstractAuthenticationToken>
to get access to the claims and map them into an Authentication
such as JwtAuthenticationToken
as needed.
Answered By - Steve Riesenberg
Answer Checked By - Terry (JavaFixing Volunteer)