0

At a glance, I have API Back-end App written in Spring Boot which uses JWT for secured data transmission. I want to add 3rd parameter for authorization, so I should have login, password and storeID parameters. I am inspired by this answer How implement Spring security when login page having more field apart from user name and password? but when I followed proposed solution my 3rd parameter in not used. My impression is that I am missing something important in Security Config. Could you please point to my mistake?

SecurityConfig

@SuppressWarnings("SpringJavaAutowiringInspection")
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AuthenticationDetailsSource<HttpServletRequest, ?> webAuthenticationDetailsSourceImpl;

    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
        .authenticationProvider(myAuthProvider());
    }

    @Bean
    public CustomUserDetailsAuthenticationProvider myAuthProvider() throws Exception {
        CustomUserDetailsAuthenticationProvider provider = new CustomUserDetailsAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder());
        provider.setUserDetailsService(userDetailsService);

        return provider; 
    }

    @Bean
    public UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception {
        UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter  = new UsernamePasswordAuthenticationFilter();
usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
        usernamePasswordAuthenticationFilter.setAuthenticationDetailsSource(webAuthenticationDetailsSourceImpl);

        return usernamePasswordAuthenticationFilter;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        JwtAuthenticationTokenFilter authenticationTokenFilter = new JwtAuthenticationTokenFilter();
    authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean());

        return authenticationTokenFilter;
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // we don't need CSRF because our token is invulnerable
                .csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()

                // don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                // allow anonymous resource requests
                .antMatchers(
                        HttpMethod.GET,
                        "/",
                        "/*.html",
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js"
                ).permitAll()
                .antMatchers("/auth/**").permitAll()
                .anyRequest().authenticated();

        // Custom JWT based security filter
        httpSecurity
                .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        // disable page caching
        httpSecurity.headers().cacheControl();
    }
}

I was under impression I can check against storeID field in WebAuthenticationDetailsSourceImpl, but looks like it has never been executed because I don't see anything related in log.

WebAuthenticationDetailsSourceImpl:

@Component
public class WebAuthenticationDetailsSourceImpl implements AuthenticationDetailsSource<HttpServletRequest, JwtAuthenticationRequest> {

    @Override
    public JwtAuthenticationRequest buildDetails(HttpServletRequest context) {
        System.out.println("___#####_____");
        System.out.println(context);
        System.out.println("___#####_____");
        return new JwtAuthenticationRequest();
    }
}
Community
  • 1
  • 1
Evgeny M
  • 417
  • 7
  • 15

1 Answers1

0

cuz you don't insert "your" usernamePasswordAuthenticationFilter that set webAuthenticationDetailsSourceImpl to Spring Security's authentication filter chain.

perhaps current your authentication filter chain is

~
JwtAuthenticationTokenFilter
(Spring Security's original)UsernamePasswordAuthenticationFilter
~

hence,if you want to retrieve your additional parameter in "your" usernamePasswordAuthenticationFilter add this filter too like a JwtAuthenticationTokenFilter

but , if you want to simply retrieve parameter at JwtAuthenticationTokenFilter use setAuthenticationDetailsSource at there

@Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
    JwtAuthenticationTokenFilter authenticationTokenFilter = new JwtAuthenticationTokenFilter();
    authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean());
    authenticationTokenFilter.setAuthenticationDetailsSource(webAuthenticationDetailsSourceImpl);
    return authenticationTokenFilter;
}
Javvano
  • 969
  • 8
  • 16
  • In JwtAuthenticationTokenFilter I validate token and if it is not valid/exist I do `chain.doFilter(request, response)` So like you said I am probably have to add "my usernamePasswordAuthenticationFilter". – Evgeny M Jun 26 '16 at 01:15
  • `@Bean public UsernamePasswordStoreAuthenticationFilter authenticationTokenFilterBean2() throws Exception { UsernamePasswordStoreAuthenticationFilter authenticationTokenFilter = new UsernamePasswordStoreAuthenticationFilter(); authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean()); authenticationTokenFilter.setAuthenticationDetailsSource(webAuthenticationDetailsSourceImpl); return authenticationTokenFilter; }` – Evgeny M Jun 26 '16 at 01:18
  • And also modified configure() method ` // Custom JWT based security filter httpSecurity .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(authenticationTokenFilterBean2(), UsernamePasswordAuthenticationFilter.class);` But WebAuthenticationDetailsSourceImpl has neve been called. – Evgeny M Jun 26 '16 at 01:21