I have a spring MVC application using spring security 4 and I want to add authorization based on the jwt token in the request. what I need to do in the filter is to
- Take token from request header
- Send the token to external API and get the user details
- Set the fetched details in the Security Context
But when I start the application, I get an error saying An AuthenticationManager is required. I am not sure how the UserDetails service apply for my use case. Hence I have added a dummy return value for testing since without the UserDetailsService application is not working. Any idea on this?
Spring security config class
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
prePostEnabled = true
)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("applicationUserService")
UserDetailsService userDetailsService;
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.GET, "/home").hasAnyRole("ADMIN")
.antMatchers(HttpMethod.GET, "/login").hasAnyRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilter(new AuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
Authorization Filter class
public class AuthorizationFilter extends BasicAuthenticationFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizationFilter.class);
public AuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
LOGGER.info("Request Info : {}", req.getRequestURI());
// get token
// fetch details from external API
// set security context
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add((GrantedAuthority) () -> "ROLE_ADMIN");
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user1", null, authorities));
LOGGER.info("security context principle:{}", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
LOGGER.info("authorities context:{}", SecurityContextHolder.getContext().getAuthentication().getAuthorities().toString());
chain.doFilter(req, response);
}
UserDetailsService implementation
@Service
@Qualifier("applicationUserService")
public class ApplicationUserServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return new User("sidath", "123", emptyList());
}
}