I think this works.
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
boolean loggedIn = false; //false by default or we wouldn't be in this method
if (isLoginAttempt(request, response)) {
loggedIn = executeLogin(request, response);
}
if (!loggedIn) {
// sendChallenge(request, response);
return true;
}
return loggedIn;
}
i.e. if authorisation details are provided execute login as normal (401 if auth details are invalid), else allow them in anyway (then check if authenticated, authorised later).
There's a caveat to this method though in that while it works with curl tests, using Apache's HttpClient Fluent API seems to send a request without authorisation and then send a second request with the credentials after a challenge response, which we're obviously now not sending. Arguably a bug in HttpClient but seeing as we've presumably deviated from the basic auth spec it's probably asking for it. So YMMV. This can be worked around by using preemptive auth and specifying the header value as suggested here.