Search code examples
javaspringspring-bootspring-security

How to addFilter for custom jwt header authorization


For some reason I cannot add a filter that will take over the authorization phase of the filter chain. The defaultChain is reading out on start: "Will not secure any request", but it seems like my request are secured when I test, however It will not trigger my filter. If I could get some help on this matter it would be greatly appreciated!

WEBCONFIG

package com.legacybanking.legacyBankingAPI.security.securityConfig;

import com.legacybanking.legacyBankingAPI.security.jwt.JwtPasswordValidator;
import com.legacybanking.legacyBankingAPI.services.CustomerService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


import java.util.List;

@Configuration
@AllArgsConstructor
@EnableWebSecurity
@Slf4j
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final CustomerService customerService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customerService).passwordEncoder(bCryptPasswordEncoder);
    }
    
    @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        return super.userDetailsService();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.info("ITS NOT WORKING");
        http
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .addFilter(new JwtPasswordValidator(authenticationManager()))
                .authorizeRequests()
//                ANT MACHERS = WHITELISTING
                .antMatchers("/api/**")
                .permitAll()
                .anyRequest()
                .authenticated();
    }
}

JWTCONFIG

package com.legacybanking.legacyBankingAPI.security.jwt;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.legacybanking.legacyBankingAPI.models.Customer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.stream.Collectors;

@Slf4j
public class JwtPasswordValidator extends UsernamePasswordAuthenticationFilter {

    @Autowired
    private final AuthenticationManager authenticationManager;

    public JwtPasswordValidator(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }


    @Override
    public Authentication attemptAuthentication( HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        System.out.println("request = " + request.getParameter("email"));
        System.out.println("request = " + request.getParameter("password"));
        String email =  request.getParameter("email");
        String password = request.getParameter("password");
        log.info("Test Loging -> {}, {}",email,password);
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(email,password);
        return authenticationManager.authenticate(authenticationToken);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        System.out.println(authResult);
        User user = (User) authResult.getPrincipal();
        String key = "secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret";
        Algorithm algorithm = Algorithm.HMAC256(key.getBytes());
        String access_token = JWT.create()
                .withSubject(user.getUsername())
                .withIssuedAt(new Date())
                .withExpiresAt(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
                .withIssuer(request.getRequestURI())
                .withClaim("roles", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
                .sign(algorithm);
        String refresh_token = JWT.create()
                .withSubject(user.getUsername())
                .withExpiresAt(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
                .withIssuer(request.getRequestURI())
                .sign(algorithm);
        System.out.println(access_token);
        log.info("This is the access token: {}", access_token);
        response.addHeader("Authorization", "Bearer " + access_token);
        response.setHeader("access_token", "token" + access_token);

    }
}


Solution

  • You have to register the JwtPasswordValidator class inside the AppSecurityConfig cofig() method as follows:

    http.addFilter(JwtPasswordValidator);
    

    also you may need to create a CustomAuthorizationFilter which extends OncePerRequestFilter class and register it inside the config method as follows:

    http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
    

    if need more help do not hesitate to ask.