We have a web application built using spring boot and we are using spring security to manage authentication. Authentication is right now happening using basic mode.
We are using UserDetailsService to handle authentication. When we are running the application directly from STS using the embedded tomcat, when the user is not enabled, we receive the following error with status code 401.
{"timestamp":1485512173312,"status":401,"error":"Unauthorized","message":"User is disabled","path":"/trex/user"}
But, when I package the application into a war and deploy it to Tomcat we no longer receive the json error. Instead, we receive a html error similar to the following.
<html><head><title>Apache Tomcat/7.0.75 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 401 - User is disabled</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>User is disabled</u></p><p><b>description</b> <u>This request requires HTTP authentication.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.75</h3></body></html>
Is it possible to stop handling the standard error codes and let the json data pass back as it is?
Edited: Spring security config
/**
* Security configuration. Defines configuration methods and security
* constraints. Autowired bean definitions can be found in {@link AuthAppConfig}
*
*
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
Logger logger = LoggerFactory.getLogger(getClass());
/*userDetailsService
* @Autowired TRexUserDetailsService customAuthenticationEntryPoint;
*
*/
@Autowired
TRexUserDetailsService userDetailsService;
@Autowired
private AmazonProperties amazonProperties;
/**
* Configuration related to authentication and authorization
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
AuthenticationEntryPoint entryPoint = new CustomAuthenticationEntryPoint();
LogoutHandler myLogoutHandler = new MyLogoutSuccessHandler();
logger.info("Configuring the security of the application");
http
// Basic Authentication
.httpBasic().authenticationEntryPoint(entryPoint)
.and().authorizeRequests()
// Allowing index.html, login.html and / and
// resetforgotpassword.html and all forgot user mappings since
// we are using 2 way handshake for this purpose
.antMatchers("/activate/user","/activate/token/**"
,"/validate","/validateEmail","/user/resetpassword/**","/user/forgotpassword"
,"/admin/masters/*.js","/admin/modeller/*.js", "/login.html", "/index.html","/activateuser.html","/savepassword.html","/forgotpassword.html","/","/lib/**"
,"/directives/paginated-control.js"
, "/expense/js/summary.js"
,"/travel/js/directive/uploadDirecetive.js"
,"/travel/js/travelData.js"
,"/travel/js/summary.js"
,"/directives/paginated-control.js"
,"/loginform.html"
,"/infoDirective.html"
)
.permitAll()
// Admin ADMIN,
.antMatchers("/admin/**").access("hasRole('ADMIN')")
// Allow SA
.antMatchers("/SA/**").access("hasRole('SUPER')")
//Allow REPORTS
.antMatchers("/reports/**").access("hasRole('REPORT')")
// All other requests are to be authenticated.
.anyRequest().authenticated().and()
// Filter to prevent CSRF attacks.
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class).csrf()
// Used to check which requests are to be checked for csrf
// protection
.requireCsrfProtectionMatcher(new CsrfRequestMatcher())
// Add the renamed CSRF token header repository
.csrfTokenRepository(csrfTokenRepository())
.and()
// Configuration for /logout
.logout()
// Logout requires form submit. Bypassing the same.
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/#/login")
.addLogoutHandler(myLogoutHandler)
//Session management to store session registry
.and().sessionManagement()
.maximumSessions(100)
.maxSessionsPreventsLogin(false)
.expiredUrl("/#/login")
.sessionRegistry(sessionRegistry());
}
/**
* Session Registry to store sessions
* @return
*/
@Bean
SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
/**
* Session event publisher.
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
/**
* This method specifies that the header name to be used is XSRF token
* instead of the default CSRF cause Angular names the token as XSRF instead
* of CSRF
*
* @return
*/
private CsrfTokenRepository csrfTokenRepository() {
logger.info("Configuring the CSRF token name as XSRF-TOKEN");
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
/**
* Configuration for Custom Authentication
*
* @param auth
* @throws Exception
*/
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth, BCryptPasswordEncoder passwordEncoder)
throws Exception {
logger.info("Configuring the authentication to custom User Details Service");
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
logger.info("Configuring the authentication to custom User Details Service");
}
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
// TODO Auto-generated method stub
return super.authenticationManagerBean();
}
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() throws Exception {
BasicAuthenticationEntryPoint entryPoint = new CustomAuthenticationEntryPoint();
entryPoint.setRealmName("Spring");
return entryPoint;
}
}