'Separate authentication for Swagger and API

I have the SecurityConfig.java like below

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    AuthenticationEntryPointJwt authenticationEntryPointJwt;

    @Autowired
    TokenProcessor tokenProcessor;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .authorizeRequests()
                .antMatchers("/v2/api-docs").authenticated()
                .antMatchers("/swagger-ui.html").authenticated()
                .antMatchers("/swagger-ui/index.html").authenticated()
                .antMatchers("/swagger-ui/").authenticated()
                .antMatchers("/**/signup", "/**/verify", "/**/login")
                .permitAll()
                .anyRequest().authenticated().and()
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPointJwt).and()
                .addFilterBefore(new JwtAuthFilter(tokenProcessor), UsernamePasswordAuthenticationFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.csrf().disable();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("{noop}password").roles("USER");
    }

}

The JWTAuthFilter.java

public class JwtAuthFilter extends GenericFilterBean {

    private UserIdentityTokenProcessor cognitoIdTokenProcessor;

    public JwtAuthFilter(UserIdentityTokenProcessor cognitoIdTokenProcessor) {
        this.cognitoIdTokenProcessor = cognitoIdTokenProcessor;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        try {
            Authentication authentication = this.cognitoIdTokenProcessor.authenticate((HttpServletRequest) request);
            if (authentication != null) {
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            SecurityContextHolder.clearContext();
        }
        filterChain.doFilter(request, response);
    }

}

And the AuthenticationEntryPointJwt.java

public class AuthenticationEntryPointJwt implements AuthenticationEntryPoint {

    private static final Gson GSON = new GsonBuilder().serializeNulls().create();

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse httpServletResponse, AuthenticationException authException) throws IOException, ServletException {
        log.warn("Unauthorized request {}", request.getRequestURI());
        ResponseDTO<Object> response = new ResponseDTO<Object>(false, "Authentication failed: bad credentials",
                null, "UNAUTHORIZED", null);

        String responseJsonString = GSON.toJson(response);
        PrintWriter out = httpServletResponse.getWriter();
        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        out.print(responseJsonString);
        out.flush();
    }
}

My expectation is that:

  • When the user access to the swagger-ui (ex: http://localhost:8080/user/swagger-ui/index.html), there is the pop-up appear to enter the username/password which has defined in SecurityConfig.java
  • After login successfully, when user try to perform the api, they need to add the Bearer token into the header. (token verification)

The current problem:

  • If I configure like some classes above, when I access to the swagger-ui, it will show the error:

{"status":false, "message":"Authentication failed: bad credentials","messageCode":null,"errorCode":"UNAUTHORIZED","data":null}

It means the token verification already applied for the swagger-ui as well. I have tried some ways but I just achieve one way like you keep the token verification but missing the login pop-up.

How could I reach my expectation? (swagger-ui need to show login pop-up and calling api need to process token verification)



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source