I created a Spring Boot Rest Api with custom JWT authentication (that I'll change someday with Keycloak).
The custom filter is this:
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
#Override
protected void doFilterInternal(
#NonNull HttpServletRequest request,
#NonNull HttpServletResponse response,
#NonNull FilterChain filterChain
) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;
if(authHeader == null || !authHeader.startsWith("Bearer ")){
filterChain.doFilter(request, response);
return;
}
// Extract token
jwt = authHeader.substring(7);
// Extract username or email from JWT token
userEmail = jwtService.extractUsername(jwt);
if(userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
if(jwtService.isTokenValid(jwt, userDetails)){
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
The security configuration:
public class SecurityConfiguration {
private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenticationProvider;
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception{
httpSecurity
.csrf()
.disable()
.authorizeHttpRequests()
.requestMatchers("/api/v1/auth/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
}
The problem is that when I encounter any exception during runtime (IllegalArgumentException, RuntimeException etc.) all of them are returned to the caller as a "403 Forbidden".
I want to return the actual exception to whoever made the call.
What am I missing here?
You need to allow access to /error.
.requestMatchers("/api/v1/auth/**", "/error").permitAll()
Related
I am using jwt token based spring security.
I have an endpoint '/sample-endpoint' which requires authentication. However, I need to bypass security for this endpoint when the request comes from a specific domain called xyz.com.
Is it possible to do so? If so, how to do that?
Here is what I have so far.
SecurityConfig
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// cant add the end point here as it would open up for everybody.
public static final String[] unauthedUrls = { "healthcheck","some-other-endpoint"}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.disable()
.csrf()
.disable()
.cors()
.and()
.headers().frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.addFilterAfter(jwtSecurityFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers(unauthedUrls)
.permitAll()
.anyRequest()
.authenticated();
}
Here is JwtSecurityFilter implementation.
public class JwtSecurityFilter extends OncePerRequestFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(JwtSecurityFilter.class);
private static final String JWT_PREFIX = "Bearer ";
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
setAuthenticationContext(request);
chain.doFilter(request, response);
}
private void setAuthenticationContext(HttpServletRequest request) {
try {
String token = getJwt(request);
if (StringUtils.isBlank(token)) {
throw new RuntimeException("Authorization token not provided");
}
// some logic here...
} catch (Exception ex) {
if (request != null && Arrays.stream(SecurityConfig.unauthedUrls).anyMatch(url -> request.getRequestURI().contains(url))) {
// it's a URL that isn't authenticated so an exception here is normal
// if we couldn't get a token
return;
}
LOGGER.warn("Unable to authenticate request: {} {}", ex.getMessage(), request == null ? null : request.getRequestURI());
}
}
private String getJwt(HttpServletRequest request) {
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if (StringUtils.isBlank(authHeader) || !authHeader.startsWith(JWT_PREFIX)) {
return "";
}
return authHeader.replaceFirst(Pattern.quote(JWT_PREFIX), "");
}
}
What you want is to ignore certain URLs for this override the configure method that takes WebSecurity object and ignores the pattern. For example, using the api:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/signup");
}
And remove that line from the HttpSecurity part. This will tell Spring Security to ignore this URL and don't apply any filters to them.
I have a better way:
http
.authorizeRequests()
.antMatchers("/api/v1/signup/**").permitAll()
.anyRequest().authenticated()
I'm a junior web developper and I need to customize the 403 error page using react js, I've found other projects implementing the AccessDeniedHandler interface but I don't know how to use it in my Security Configuration class.
This is my CustomAccessDeniedHandler class :
#Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private static Logger logger = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
#Override
public void handle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AccessDeniedException e) throws IOException, ServletException {
System.out.println("accessDenied");
Authentication auth
= SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
logger.info("User '" + auth.getName()
+ "' attempted to access the protected URL: "
+ httpServletRequest.getRequestURI());
}
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/accessDenied");
}
}
This is the Security Configuration class :
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
AppUserService userDetailsService;
#Autowired
private AccessDeniedHandler accessDeniedHandler;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {})
.and()
.authenticationProvider(getProvider())
.formLogin()
.loginPage("/login")
.successHandler(new AuthentificationLoginSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
.invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/api/categories").hasAuthority("USER")
.antMatchers("/api/createCategory").hasAuthority("ADMIN")
.anyRequest().permitAll();
}
private class AuthentificationLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_OK);
}
}
private class AuthentificationLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
#Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_OK);
}
}
#Bean
public AuthenticationProvider getProvider() {
AppAuthProvider provider = new AppAuthProvider();
provider.setUserDetailsService(userDetailsService);
return provider;
}
#Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
}
What you have to do is to create #Bean
#Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
which you already have and then add that handler in http security object like this:
http.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {}) //remove this line or use Http401UnauthorizedEntryPoint instead
.and()
.authenticationProvider(getProvider())
.formLogin()
.loginPage("/login")
.successHandler(new AuthentificationLoginSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
.invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/api/categories").hasAuthority("USER")
.antMatchers("/api/createCategory").hasAuthority("ADMIN")
.anyRequest().permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
As you can see you are missing:
.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler());
Additional, remove
#Autowired
private AccessDeniedHandler accessDeniedHandler;
because you shouldn't autowire bean, you should create it with custom implementation.
EDIT:
If you have #RestControllerAdvice or #ControllerAdvice as global exception handler you should do following:
#ExceptionHandler(Exception.class)
public ResponseEntity<?> exception(Exception exception) throws Exception {
if (exception instanceof AccessDeniedException) {
throw exception;
}
...
then it should work because when you throw exception it will go to custom handler which we do what you wrote. Also you can debug ExceptionTranslationFilter method handleSpringSecurityException
code from ExceptionTranslationFilter
private void handleSpringSecurityException(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, RuntimeException exception)
throws IOException, ServletException {
if (exception instanceof AuthenticationException) {
logger.debug(
"Authentication exception occurred; redirecting to authentication entry point",
exception);
sendStartAuthentication(request, response, chain,
(AuthenticationException) exception);
}
else if (exception instanceof AccessDeniedException) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
logger.debug(
"Access is denied (user is " + (authenticationTrustResolver.isAnonymous(authentication) ? "anonymous" : "not fully authenticated") + "); redirecting to authentication entry point",
exception);
sendStartAuthentication(
request,
response,
chain,
new InsufficientAuthenticationException(
messages.getMessage(
"ExceptionTranslationFilter.insufficientAuthentication",
"Full authentication is required to access this resource")));
}
else {
logger.debug(
"Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
exception);
accessDeniedHandler.handle(request, response,
(AccessDeniedException) exception);
}
}
}
where you can see that
accessDeniedHandler.handle(request, response,(AccessDeniedException) exception);, in you caseCustomAccessDeniedHandler, get called.
I just tried it and it is working fine with (I have #ControllerAdvice as global exception handler)
EDIT2:
You have to remove this line
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {})
from SecurityConfig, or change it to use Http401UnauthorizedEntryPoint instead. This is the problem in your case.
I'm implementing Spring Security on API-REST, of we are developing.
My product manager told us to use the same url to return data and to login.
This url, as a POST, and that wait a JSON.
I can't configure the environment for do that, is possible? or always we need have a different url to login?
Thank you!!
This is the JSON on JAVA
#Getter
#Setter
public class CheckCloudUsersJSON implements Serializable {
private String tvAdmin;
private String ip;
}
#PostMapping(value = "/check-cloudusers", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity checkCloudUsers(#RequestBody CheckCloudUsersJSON checkCloudUsersJSON) {
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
JWTAuthenticationFilter authenticationFilter = new JWTAuthenticationFilter(authenticationManager());
authenticationFilter.setFilterProcessesUrl("/mobile/login");
httpSecurity
.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.GET, VERSION_URL).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
setFilterProcessesUrl(AUTH_LOGIN_URL);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try {
TVUser credenciales = new ObjectMapper().readValue(request.getInputStream(), TVUser.class);
return new UsernamePasswordAuthenticationToken(
credenciales.getTvUserId(), null);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) throws IOException, ServletException {
String userName = auth.getPrincipal().toString();
byte[] signingKey = SECRET_KEY.getBytes();
String token = Jwts.builder()
.signWith(Keys.hmacShaKeyFor(signingKey), SignatureAlgorithm.HS512)
.setHeaderParam("typ", TOKEN_TYPE)
.setIssuer(TOKEN_ISSUER)
.setAudience(TOKEN_AUDIENCE)
.setSubject(userName)
.setExpiration(new Date(System.currentTimeMillis() + 900000))
.compact();
response.addHeader(TOKEN_HEADER, TOKEN_PREFIX + token);
}
}
Where does the user and password go to the authentication? In the JSON checkCloudUsers JSON?
And the endpoint will return a 200 Ok Code and the JWT Token in the authorization header.
Please elaborate from what you are trying to do, but anyways from what i understand ,since you are using spring security we need to authorise the login request and return the JSON response from the login webservice as a part of the response body.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
http
.authorizeRequests()
.antMatchers("/login/**").permitAll()
.anyRequest().authenticated();
}
#PostMapping("/login")
public JsonResponse login() {
// Point to the login page
// Return the json in the response with a 200 OK
}
I have a custom UserDetailsService:
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private AccountRepository accountRepository;
#Autowired
private PasswordEncoder passwordEncoder;
private static Logger logger = LoggerFactory.getLogger(JWTLoginFilter.class);
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
CustomUserDetails account = accountRepository.findByUsername(username);
if (account != null) {
return account;
} else {
throw new UsernameNotFoundException("could not find the user '" + username + "'");
}
}
public void saveUser(String userName, String password) {
CustomUserDetails userDetails = new CustomUserDetails(userName, passwordEncoder.encode(password), true, true, true,true, AuthorityUtils.commaSeparatedStringToAuthorityList("USER_ROLE"));
accountRepository.save(userDetails);
logger.debug("New user with username " + userName + " was created");
}
}
and I have a sign up filter (which handles creating new users) and extends AbstractAuthenticationProcessingFilter:
public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter {
#Autowired
private CustomUserDetailsService userDetailService;
private static Logger logger = LoggerFactory.getLogger(JWTLoginFilter.class);
public JWTSignupFilter(String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url, HttpMethod.POST.toString()));
setAuthenticationManager(authManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
CustomUserDetails creds = new ObjectMapper().readValue(request.getInputStream(), CustomUserDetails.class);
if (userDetailService.loadUserByUsername(creds.getUsername()) != null) {
logger.debug("Duplicate username " + creds.getUsername());
throw new AuthenticationException("Duplicate username") {
private static final long serialVersionUID = 1L;
};
}
userDetailService.saveUser(creds.getUsername(), creds.getPassword());
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(),creds.getPassword()));
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
TokenAuthenticationService.addAuthentication(response, auth.getName());
chain.doFilter(request, response);
}
}
I get null pointer exception when the execution reaches userDetailService.loadUserByUsername, which means autowiring didn't work.
I tried implementing ApplicationContextAware like the following, but it is still Null. I also annotated JWTSignupFilter with #Service but it didn't work either. Any idea how to fix this issue ?
public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
private CustomUserDetailsService userDetailService;
.....
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
userDetailService = applicationContext.getBean(CustomUserDetailsService.class);
}
}
This is the overriden configure method in WebSecurityConfigurerAdapter, where login filter comes in to the play:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout().logoutUrl("/logout").logoutSuccessHandler(logoutHandler).logoutSuccessUrl("/login").invalidateHttpSession(true)
.and()
// We filter the api/signup requests
.addFilterBefore(
new JWTSignupFilter("/signup", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// We filter the api/login requests
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(
new JWTAuthenticationFilter(userDetailsServiceBean()),
UsernamePasswordAuthenticationFilter.class);
}
Try this:
Add below code into your configuration file:
#Bean
public JWTSignupFilter jWTSignupFilter() throws Exception {
return new JWTSignupFilter("/login", authenticationManager());
}
Add below line into your WebSecurityConfigurerAdapter extended class
#Autowired
JWTLoginFilter jWTSignupFilter
and replace
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
with
.addFilterBefore(
jWTSignupFilter,
UsernamePasswordAuthenticationFilter.class)
Updated
Your WebSecurityConfigurerAdapter extended class should look like so:
public Class CustomConfigurationClass extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout().logoutUrl("/logout").logoutSuccessHandler(logoutHandler).logoutSuccessUrl("/login").invalidateHttpSession(true)
.and()
// We filter the api/signup requests
.addFilterBefore(
jWTSignupFilter(),
UsernamePasswordAuthenticationFilter.class)
// We filter the api/login requests
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(
new JWTAuthenticationFilter(userDetailsServiceBean()),
UsernamePasswordAuthenticationFilter.class);
}
#Bean
public JWTSignupFilter jWTSignupFilter() throws Exception {
return new JWTSignupFilter("/signup", authenticationManager());
}
}
I have Token based authorization,
Well thing i faced is that after authentication i gain token and then i try manually to send calls to server without token and i refresh it fast and sometimes it allows me to get the data as somehow proper data of authorization is in SecurityContextHolder and don't know how it appeared there, when token wasn't sent to server, and yeah i use STATELESS Session
Here is my config:
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
#Autowired
private AccessDeniedHandler accessDeniedHandler;
#Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(this.userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception{
return super.authenticationManagerBean();
}
#Bean
public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception{
AuthenticationTokenFilter authenticationTokenFilter = new AuthenticationTokenFilter();
authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationTokenFilter;
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf()
.disable()
.httpBasic().disable()
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/**").permitAll()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated();
}
}
AuthenticationTokenFilter
public class AuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter {
#Autowired
private TokenUtils tokenUtils;
#Autowired
private UserDetailsService userDetailsService;
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
tokenUtils = WebApplicationContextUtils
.getRequiredWebApplicationContext(this.getServletContext())
.getBean(TokenUtils.class);
userDetailsService = WebApplicationContextUtils
.getRequiredWebApplicationContext(this.getServletContext())
.getBean(UserDetailsService.class);
HttpServletResponse resp = (HttpServletResponse) response;
resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
resp.setHeader("Access-Control-Max-Age", "3600");
resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, " + Constants.tokenHeader);
HttpServletRequest httpRequest = (HttpServletRequest) request;
String authToken = httpRequest.getHeader(Constants.tokenHeader);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if(authToken != null){
String username = this.tokenUtils.getUsernameFromToken(authToken);
if (username != null && auth == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (this.tokenUtils.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
Check out this springboot jwt starter.
Security config: https://github.com/bfwg/springboot-jwt-starter/blob/master/src/main/java/com/bfwg/config/WebSecurityConfig.java
AuthenticationTokenFilter: https://github.com/bfwg/springboot-jwt-starter/blob/master/src/main/java/com/bfwg/security/auth/TokenAuthenticationFilter.java
Hope this helps.