Wildfly caches roles after logout in a web application

janor picture janor · Feb 21, 2014 · Viewed 8.2k times · Source

jboss-web.xml

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain flushOnSessionInvalidation="true">my-aktion
</security-domain>
<valve>
    <class-name>utils.MyAuthenticator</class-name>
</valve>
</jboss-web>

standalone.xml

<security-domain name="my-aktion" cache-type="default">
                <authentication>
                    <login-module code="utils.MyAuthenticator" flag="required">
                        <module-option name="dsJndiName" value="java:jboss/datasources/MySQLDS"/>
                        <module-option name="principalsQuery" value="SELECT password FROM user WHERE username=?"/>
                        <module-option name="rolesQuery" value="SELECT r.role, 'Roles' FROM Role r INNER JOIN user u ON u.role_id = r.id WHERE u.username=?"/>
                        <module-option name="hashAlgorithm" value="SHA-256"/>
                        <module-option name="hashEncoding" value="base64"/>
                    </login-module>
                </authentication>
            </security-domain>

web.xml (extract)

<security-constraint>
    <web-resource-collection>
        <web-resource-name></web-resource-name>
        <url-pattern>/Profile/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>User</role-name>
        <role-name>Manager</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>my-aktion</realm-name>
    <form-login-config>
        <form-login-page>/Login/login.xhtml</form-login-page>
        <form-error-page>/Login/error.xhtml</form-error-page>
    </form-login-config>
</login-config>
<security-role>
    <role-name>User</role-name>
</security-role>
<security-role>
    <role-name>Manager</role-name>
</security-role>

LogoutServlet.java (same for doPost(...))

@WebServlet("/Login/logout.xhtml")
public final class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

public LogoutServlet() {
    super();
}

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    response.setHeader("Cache-Control", "no-cache, no-store");

    response.setHeader("Pragma", "no-cache");

    response.setHeader("Expires", new java.util.Date().toString());
    if (request.getSession(false) != null) {

        request.getSession(false).invalidate();// remove session.

    }

//      if (request.getSession() != null) {
//
//          request.getSession().invalidate();// remove session.
//
//      }
    request.logout();
    response.sendRedirect(request.getContextPath());    
}

I have a custom Authenticator that extends the DatabaseServerLoginModule and overwrites the createPasswordHash method for its own security.

My problem is that when I log in with a manager role and change the role of a logged-in user with another browser, it caches the role for this user. Only when I log the user out and back in again does he has no access to manager content. I use the LogoutServlet to log out.

I tried various changes in the servlet but it does not help. When I remove "cache-type=default" from the standalone.xml in wildfly it works, but for every action made on the side the login method in the authentication module is called which is very bad.

In the jboss-web.xml the parameter flushOnSessionInvalidation="true" seems to be the right answer to this problem, but it has no effect. Thank you for any help!

Answer

Jorge Marmolejo picture Jorge Marmolejo · Apr 23, 2014

This is a bug in wildfly 8.0.0 planned to be fixed in 8.1. see https://issues.jboss.org/browse/WFLY-3221

In the meantime you can try this workaround to clear cache for a specific user when the session times out or it's invalidated.

Create a Session listener and call the method from sessionDestroyed.

public void clearCache(String username){
try {

    ObjectName jaasMgr = new ObjectName("jboss.as:subsystem=security,security-domain=<YOUR SECURITY DOMAIN>" );
    Object[] params = {username};
    String[] signature = {"java.lang.String"};
    MBeanServer server = (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0);
    server.invoke(jaasMgr, "flushCache", params, signature);
} catch (Exception ex) {
    logger.warn(ex.getMessage());
}}