I have a single page app developed with Facebook's React framework, where I use this bit of JSX to determine whether or not the user is logged in:
render: function() {
return <div>
<BrandBar/>
<div className="container">
<TopBar/>
{this.state.sessionState == 'LOADING' ? (<h1>Loading</h1>) : (this.state.sessionState == 'LOGGEDIN' ? this.props.children : <Login/>)}
</div>
</div>
}
The login function which alters the state for this component is a simple REST call (using superagent) that fetches the user info with basic auth credentials attached:
login: function(username, password){
return {
then: function(callback){
request
.get(rootUrl + 'me')
.auth(username, password)
.end((err, res) => {
callback(res);
});
}
}
}
On the backend side, I have a REST api in Spring Boot:
Controller:
@RequestMapping(value = "/me",
produces = {APPLICATION_JSON},
method = RequestMethod.GET)
public User getMe() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal != null && principal instanceof CurrentUser){
return ((CurrentUser) principal).getUser();
}
return null;
}
@RequestMapping("/stop")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void stop(HttpSession session) {
session.invalidate();
}
Security config:
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.httpBasic().and()
.authorizeRequests().anyRequest().authenticated()
.and().anonymous().disable()
.exceptionHandling().authenticationEntryPoint(new BasicAuthenticationEntryPoint(){
@Override
public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
});
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
}
Logging in works fine as long as the info I provide is correct, but when I supply bad credentials, the server bypasses the exception handling that returns a plain 401 (without the WWW-Authenticate header). So the browser shows me the popup despite the overridden BasicAuthenticationEntryPoint.
What's even more weird is, when I provide the correct details in the browser popup, it still returns a 401 status.
This seems like a basic setup though: a simple REST service with Spring Security and a single page app on front-end. Has anyone had a similar issue?