why spring returns 401 html page instead of my custom json api response with error? and what is the best way to fix it (override spring config)
security:
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.cors().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/v2/api-docs").permitAll()
.antMatchers("/configuration/ui").permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/configuration/security").permitAll()
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/swagger-ui/*").permitAll()
.antMatchers("/webjars/**").permitAll()
.antMatchers("/v2/**").permitAll()
.antMatchers(LOGIN_ENDPOINT, REGISTER_ENDPOINT, "/v2/api-docs", "/swagger-ui.html",
"/v2/swagger-ui.html").permitAll()
.antMatchers(ADMIN_ENDPOINT).hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.apply(new JwtConfigurer(jwtTokenProvider));
}
Filter:
public class JwtTokenFilter extends GenericFilterBean {
private final JwtTokenProvider jwtTokenProvider;
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
throws IOException, ServletException {
String token = jwtTokenProvider.resolveToken((HttpServletRequest) req);
try {
if (token != null && jwtTokenProvider.isTokenValid(token)) {
var authentication = jwtTokenProvider.getAuthentication(token);
if (authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
} catch (JwtAuthenticationException e) {
SecurityContextHolder.clearContext();
((HttpServletResponse) res).sendError(e.getHttpStatus().value());
((HttpServletResponse) res).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
filterChain.doFilter(req, res);
throw new JwtAuthenticationException("JWT token is expired or invalid",
HttpStatus.UNAUTHORIZED);
}
filterChain.doFilter(req, res);
}
}
so i implemented custom exception handler and filter, and what i need is this type of error
{
"errorMessage": "Invalid username or password",
"validationErrors": null
}
that what i get when login fo example, success case to get token is also working
{
"username": "vovaflex",
"token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ2b3ZhZmxleCIsInJvbGVzIjpbIlJPTEVfVVNFUiJdLCJpYXQiOjE2MTk4NjQ2MDksImV4cCI6MTYxOTg2ODIwOX0.Oc7AG5ZncfAT3QB8l0mkYDkBr5ZjBfJ2MxLe3M12DF8",
"roles": [
{
"id": 1,
"created": "2021-04-03T18:14:51.891+00:00",
"updated": "2021-04-03T18:14:51.891+00:00",
"status": "ACTIVE",
"name": "ROLE_USER",
"users": null
}
]
}
but whey for example token is not correct or expired or so, i get 401 unauthorized (correct) but instead of json with message that i set up i get full html page with error
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 401 – Unauthorized</title>
</head>
<body>
<h1>HTTP Status 401 – Unauthorized</h1>
</body>
</html>
Advertisement
Answer
For custom JSON error block, you need to do two things
Implement the AuthenticationEntryPoint
public class AuthExceptionEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2) throws IOException, ServletException {
JavaScript}
}
and add that reference in the websecurity settings configure(HttpSecurity http)
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
{
@Override
public void configure(HttpSecurity http) throws Exception
{
http.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint()) ;
}
}
check these two resources for more details