Search code examples
javatomcatform-authenticationj-security-check

request.getUserPrincipal() is null in RequestListener despite that authentication succeeded


we have an issue with later and latest Tomcat versions, that prevent us from upgrading to a version later than something like 7.0.22.

We use FormBasedAuthentication with a custom realm.

This is tested with Tomcat 7.0.57 and JDK 7u76 on Windows.

My setup has a login form calling the j_security servlet. The custom realm is called and authentication is successful, a custom principal is returned.

Tomcat will then forward to the protected resource, and we catch the request in a RequestListener.

The problem is, that request.getUserPrincipal() returns null. The debugger exposes, that the sessionwrapper returned by request.getSession(false) (instance of SessionWrapper, containing StandardSession) has a field “principal”, that contains the principal returned from my realm.

I have seen a discussion on the requirement to return a userprincipal on non protected requests in bugzilla, but the request here is calling for a protected resource.

Any idea on why this can happen would be very helpful. Actually, I see it as a bug, that the request is not authenticated but still served.

The exact same setup works like a charm on Tomcat 7.0.12 and I think up to 7.0.22.

Best regards,

Thomas

Here is the code of the request listener:

@Override
public void requestInitialized(ServletRequestEvent event) {
    if( log.isTraceEnabled() ) {
        log.trace( ">> requestInitialized" );
    }
    HttpServletRequest request = (HttpServletRequest)event.getServletRequest();
    PortalRequest.current.set( request );
    HttpSession httpSession = null;
    GenericPrincipal genericPrincipal = (GenericPrincipal)request.getUserPrincipal();

// genericPrincipal is null, requestURI is pointing to a protected resource.

This is the form authentication config in web.xml

<welcome-file-list>
<welcome-file>jsp/main.jsp</welcome-file>
</welcome-file-list>

<security-constraint>
<display-name>PDiX Portal</display-name>
<web-resource-collection>
  <web-resource-name>PDX Portal Protected</web-resource-name>
  <url-pattern>/jsp/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>servlets</web-resource-name>
  <url-pattern>/servlet/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>GWT Resourcen</web-resource-name>
  <url-pattern>/StandardPortal/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>services</web-resource-name>
  <url-pattern>/delegating/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>ViewerServlet</web-resource-name>
  <url-pattern>/frameset</url-pattern>
  <url-pattern>/run</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>EngineServlet</web-resource-name>
  <url-pattern>/preview</url-pattern>
  <url-pattern>/download</url-pattern>
  <url-pattern>/parameter</url-pattern>
  <url-pattern>/document</url-pattern>
  <url-pattern>/output</url-pattern>
  <url-pattern>/extract</url-pattern>
</web-resource-collection>
<auth-constraint>
  <role-name>authenticatedUser</role-name>
</auth-constraint>

FORM PDXRealm /jsp/login.jsp /logout.jsp?error=true authenticatedUser

[updated question to reflect the connection with the request listener]


Solution

  • The problem was resolved with the help of Konstantin Kolinko on the tomcat users list.

    Starting with Tomcat 7.0.22 the authentication happens after the servlet request listener is triggered. This has the side effect, that the request listener can no longer be used to setup application authentication in the session.

    To quote Konstantin:

    There is the following change for 7.0.22 in the changelog file:

    [quote] Correct a regression with the fix for 51653 that broke custom error pages for 4xx responses from the Authenticators. Error handling and request listeners are now handled in the StandardHostValve to ensure they wrap all Context level activity. (markt) [/quote]

    So, my solution is to find another way to setup my stuff, and this is most likely a filter.

    I have skimmed through the Servlet 3.0 spec to find any hint on the state of the request on the call to requestInitialized(), but there is no specific requirements given (or I have not found them).

    Hope someone else will find this helpful as well.