Bug 50803 - ServletException.getRootCause() does not return the LoginException thrown by a JAAS login module
Summary: ServletException.getRootCause() does not return the LoginException thrown by ...
Status: RESOLVED INVALID
Alias: None
Product: Tomcat 7
Classification: Unclassified
Component: Servlet & JSP API (show other bugs)
Version: 7.0.8
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
: 44598 (view as bug list)
Depends on:
Blocks:
 
Reported: 2011-02-17 13:53 UTC by Patrik Varga
Modified: 2011-02-18 12:08 UTC (History)
1 user (show)



Attachments
stack trace and output (8.22 KB, text/plain)
2011-02-17 15:39 UTC, Patrik Varga
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Patrik Varga 2011-02-17 13:53:32 UTC
The javadoc of ServletException.getRootCause() at http://download.oracle.com/javaee/6/api/javax/servlet/ServletException.html#getRootCause%28%29 states that this method should return the exception that caused this servlet exception.

However, when using a JAAS login module, the ServletException thrown after an unsuccessful HttpServletRequest.login(String,String) call does not contain its (root) cause, and its getCause() and getRootCause() methods always return null. This makes it impossible to get a handle to the original LoginException thrown by the login module and to present the user the specific error message contained in the LoginException.
Comment 1 Konstantin Kolinko 2011-02-17 14:55:09 UTC
What is stack trace of that exception? Where is it thrown from?
Comment 2 Patrik Varga 2011-02-17 15:39:03 UTC
Created attachment 26676 [details]
stack trace and output

See attached stack trace and output when called from a JSF backing bean test method pvarga.test.LoginBacking.login() which basically looks like this:

public String login() {
	HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    try {
    	request.login(this.username, this.password);
    }
    catch (ServletException se) {
        System.out.println("getCause: " + se.getCause());
        System.out.println("getRootCause: " + se.getRootCause());
        System.out.println("getMessage: " + se.getMessage());
        System.out.println("getLocalizedMessage: " + se.getLocalizedMessage());
        System.out.println("stack trace:");
        se.printStackTrace();
    }
    return null;
}


As you can see the LoginException is logged in JAASRealm.authenticate() but not propagated into the ServletException.
Comment 3 Konstantin Kolinko 2011-02-17 16:07:16 UTC
stack trace:
javax.servlet.ServletException: Login failed
	at org.apache.catalina.authenticator.AuthenticatorBase.doLogin(AuthenticatorBase.java:796)
	at org.apache.catalina.authenticator.AuthenticatorBase.login(AuthenticatorBase.java:785)
	at org.apache.catalina.connector.Request.login(Request.java:2508)
	at org.apache.catalina.connector.RequestFacade.login(RequestFacade.java:1066)


Looking at AuthenticatorBase.java:796, the authenticator calls
context.getRealm().authenticate(username, password)
and that method reports unsuccessful authentication by returning null and not by throwing some exception.

This cannot be solved unless interface of Realm is changed, e.g. by allowing either null or an exception to be returned.
Comment 4 Mark Thomas 2011-02-17 17:09:25 UTC
The Realm interface will not be changed for security reasons.

The reason for a login failure should not be propagated to the user. If it were, that would be a security vulnerability of a similar nature to CVE-2009-0580.
Comment 5 Mark Thomas 2011-02-18 12:08:38 UTC
*** Bug 44598 has been marked as a duplicate of this bug. ***