1

I am working on a Spring Boot Service, which is receiving JWT Token generated in another service in the request header. My goal is to verify the validity of the JWT Token in my Spring Boot Application.

After researching a while I've decided to use WebSecurityConfig from Spring Security and to have some kind of a middleware which is actually a filter.

I have configured the filter to be applied not on all request that are defined in my application. But regardless of this the filter is applied on requests that are configured as permitAll().

I am totally confused by this all and can't figure out what I am missing. Finally I have decided to ask for help. Please help.

Here is my code.

Security config:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
JWTAuthenticationFilter jwtAuthenticationFilter;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/req").permitAll()
            .and()
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        // And filter other requests to check the presence of JWT in header
        .addFilterBefore(jwtAuthenticationFilter,
                BasicAuthenticationFilter.class);
}

@Override
public void configure(WebSecurity webSecurity) {
    webSecurity
        .ignoring()
            .antMatchers("/req");
    }
}

Filter:

@Component
public class JWTAuthenticationFilter extends GenericFilterBean {
@Autowired
TokenAuthenticationService tokenAuthenticationService = new TokenAuthenticationService();
@Override
public void doFilter(ServletRequest request,
        ServletResponse response,
        FilterChain filterChain)
                throws IOException, ServletException {
    boolean authentication = tokenAuthenticationService
            .getAuthentication((HttpServletRequest)request);

    if (!authentication) {
        ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        return;
    }

    filterChain.doFilter(request,response);
    }
}

Authentication Service:

@Component
class TokenAuthenticationService {
@Value("${security.authentication.token.secret}")
private String SECRET;
@Value("${security.authentication.token.token_prefix}")
private String TOKEN_PREFIX;
@Value("${security.authentication.token.header_string}")
private String HEADER_STRING;

boolean getAuthentication(HttpServletRequest request) throws UnsupportedEncodingException {
    String token = request.getHeader(HEADER_STRING);

    if (token != null) {
        // parse the token.
        DecodedJWT jwt;
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                .build(); //Reusable verifier instance
            jwt = verifier.verify(token);

            return true;
        } catch (UnsupportedEncodingException exception){
            //UTF-8 encoding not supported
            UnsupportedEncodingException ex = exception;
            return false;
        } catch (JWTVerificationException exception){
            //Invalid signature/claims
            JWTVerificationException ex = exception;
            return false;
        }
    }
    return false;
    }
}
Evgeni Atanasov
  • 372
  • 4
  • 10
  • You wrote *I have configured the filter to be applied not on all request* but I can't see such code in your filter. You always authenticate the request. – dur Oct 03 '17 at 17:39
  • Well don't the antMatchers().permitAll() and the ignoring().antMatchers() mean the filter to be skipped on these paths? Can you show me an example of how this configuration is applied in the filter class? – Evgeni Atanasov Oct 04 '17 at 05:19
  • `ignoring().antMatchers()` should work, because it excludes the whole filter chain, but Spring Boot adds automatically all servlet filters to the application. Did you exclude your filter in your Spring Boot configuration? – dur Oct 04 '17 at 09:03
  • Possible duplicate of [Filter invoke twice when register as Spring bean](https://stackoverflow.com/questions/39314176/filter-invoke-twice-when-register-as-spring-bean) – dur Oct 04 '17 at 09:09
  • @dur _Did you exclude your filter in your Spring Boot configuration?_ I didn't do this. But do I need it because inside my filter class I want to inject values from application.properties and if I understand correctly it excludes it from being in the component scan chain? – Evgeni Atanasov Oct 04 '17 at 10:56
  • I registered my filter with [this](https://stackoverflow.com/a/43744163/2897455) approach and protected only my private paths. – Evgeni Atanasov Oct 04 '17 at 16:55
  • Dependency injection has nothing to do with adding/excluding servlet filter. You have to disable the servlet filter or it will applied twice for not ignored paths and once for ignored paths. – dur Oct 04 '17 at 20:52
  • I think I understand you but in my case, the filter is hit once for protected paths and not hit for public paths. In the WebSecurity configure http I dont have the filter in the chain anymore so I believe it only gets hit because of registering it in the bean factory. – Evgeni Atanasov Oct 05 '17 at 07:15

1 Answers1

0

You need to use the ResourceServiceConfiguration class instead of WebSecurityConfig for JWT validation. Please check this link - https://github.com/manishsingh27/TokenBasedAuth/tree/main/stdedu/src/main/java/com/adms/stdedu/config

import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

@Configuration
//@Order(-21)
@EnableResourceServer
public class ResourceServiceConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().antMatchers("/**").hasAnyAuthority ("READ_PRIVILEGE","WRITE_PRIVILEGE");
    }

}
ManishSingh
  • 1,339
  • 9
  • 10