Reputation: 2593
I have a resource server which is receiving requests with valid Bearer token. I can either use @AuthenticationPrincipal Jwt token
for all requests where I need to get claims from the token or I should be able to get the user information from SecurityContextHolder
right? I would like to get it from the context holder. I would assume I need to define jwt converter in my SecurityConfig
? I cannot find any information on the recommended approach.
The code from here works with some legacy versions of spring security... I am using the newest spring boot with Spring security 5.4.2
@Configuration
@EnableWebSecurity
@Order(1)
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwkSetUri;
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.formLogin(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.authorizeRequests(authorize -> authorize
.mvcMatchers(HttpMethod.GET, "/test/**").authenticated()
.mvcMatchers(HttpMethod.POST, "/test/**").authenticated()
)
.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("entGrps");
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri(this.jwkSetUri).build();
}
}
Upvotes: 2
Views: 25791
Reputation: 86
If our only concern is to retrieve the token from the header, the simplest solution I came up with is to use the DefaultBearerTokenResolver:
public class CheckAuthTokenFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
String token = new DefaultBearerTokenResolver().resolve((HttpServletRequest) servletRequest);
}
}
Upvotes: 0
Reputation: 43
If you are plan to use spring-security-oauth2-resource-server dependency,
I think would be better to use @AuthenticationPrincipal Jwt token
to get token's claims.
That's simplier and less boilerplate code.
But that's up to you, Imranmadbar's solution is also working)
Upvotes: 2
Reputation: 5470
If you want information from SecurityContextHolder, you have to keep it on there.
Here is the easiest solution for this:
And you have to do this every Request Using an HTTP Request Filter (OncePerRequestFilter).
Like:
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.madbarsoft.config.MyUserDetailsService;
import com.madbarsoft.utility.JwtUitl;
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtUitl jwtUitl;
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chin)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
System.out.println("Authorization Header #:"+authorizationHeader);
String userName = null;
String jwtStr = null;
if(authorizationHeader != null && authorizationHeader.startsWith("Bearer ")){
jwtStr = authorizationHeader.substring(7);
userName = jwtUitl.extractUserName(jwtStr);
System.out.println("Form JWT userName: "+userName);
}
System.out.println("In Filter Before set #: "+SecurityContextHolder.getContext().getAuthentication());
if(userName != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userName);
if(jwtUitl.validateToken(jwtStr, userDetails)){
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
System.out.println("In Filter After Set #: "+SecurityContextHolder.getContext().getAuthentication());
}
chin.doFilter(request, response);
}
}
Now you can access user info from anywhere in the Entire Project.
(It's a working Project, You can take some info from gitLink here.)
Upvotes: 0