Wildfly caches roles after logout in a web application
Asked Answered
A

1

6

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!

Azole answered 21/2, 2014 at 10:25 Comment(5)
On a phone, so typing a well-formed answer would take a bit. Do you track logged-in users in any way in the database? Basically, if you can force the affected user to log out when their user roles are affected, then you'll be golden.Lilly
I don't track logged-in users in the database and it is ok for me if the roles are updated first after the logout and relogin of the user. problem is that the cash/session is not cleared correct.Azole
Also, as an aside, it's spelled "cache", and "caching" data means that you're hanging on to data for a little while. "Cash" is not the right word.Lilly
@ChrisForrence Do you have any other ideas to solve this problem? When the server cache would be cleared correctly after logout, then I think the problem would be solved.Azole
Unfortunately, nothing comes to mind; I'm unfamiliar with Wildfly and JBoss (I'm more of a Tomcat guy).Lilly
T
11

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());
}}
Thersathersites answered 22/4, 2014 at 22:18 Comment(10)
Using HttpServletRequest: request.getRemoteUser(). Using an EJB, inject the EJBContext and use context.getCallerPrincipal().getName(). In my case I implemented the Session Lister interface and called the clearCache method from sessionDestroyed, this way the user is removed from cache either when session times out or session is invalidated.Thersathersites
Thanks! I did something yesterday and forgot to comment again: HttpSession session = (HttpSession)hse.getSession(); clearCache((String)session.getAttribute("username"));Surplusage
That did the trick for me - but in wildfly 8.2 ... so still unresolved!?Ashia
Just wanted to add: I do now evict JAAS-Cache on Logout AND previous to Login(!).... and use a Login-Servlet instead of normal Form based/Basic authentication - just for invoking "clearCache". Because otherwise wildfly would not check the password again and would accept the old one without checking if it has changed ... or the account might be locked (which is possible in my LoginModule)Ashia
I am getting error "JBAS011342: No operation called 'flush-cache'" while running following code in wildfly-8.2.0 in domain mode:Antoninaantonino
@ValsarajViswanathan: Have you found a solution for the domain mode? i got exactly the same errorEndear
Still in wildfly11Puparium
I know this is an old post. But I was wondering where do you find or figure out the value you put into "security-domain=<YOUR SECURITY DOMAIN>"?Meperidine
I've been a while, but it's the security domain you setup in your standalone.xml: <subsystem xmlns="urn:jboss:domain:security:1.2"> <security-domains> <security-domain name="<YOUR SECURITY DOMAIN>" cache-type="default"> <authentication> . . . . </authentication> </security-domain>Thersathersites
@JorgeMarmolejo Thanks for the response. I found it. Are there any strange effects of doing this workaround? Where is the sessionDestroyed do you call this? At the very beginning or at the very end? I have tried out this workaround and it seems to work. But then after some time. I am no longer able to get to my web app, and it generates a 500 error. I get failed certificate initializations issues when trying to access EJB calls. I have to then restart wildfly of the service that my web app is talking to.Meperidine

© 2022 - 2024 — McMap. All rights reserved.