简体   繁体   中英

Session lost after redirect SAML: may be different webapps?

I am fairly new to webapps programming, so I thought of asking here.

I am implementing the SAML2 protocol in an open source app (namely OFBiz) but I am encountering a problem related to session loss after the protocol made its course.

I am following these steps to implement the protocol. Suppose ofbizwebsite.com is the URL of the site.

  1. Installed a custom plugin named SAMLIntegration which exposes the ACS page and the logic for login. To my understanding, a plugin (gradle) is like an indipendent java project, which translates to a new set of resources for the application (the plugin enables, for example, to visit ofbizwebsite.com/SAMLIntegration and setup some resources).
  2. Exposed the ACS page to ofbizwebsite.com/SAMLIntegration/control/acs , as well as metadata ofbizwebsite.com/SAMLIntegration/control/metadata.jsp
  3. Created the logic for login. Basically, an entity called UserLogin is saved in the session and recovered by a "checker" to understand if an user is logged in. Suppose that this checker is a HTTP WebEvent handler which can be called by any resource requiring authentication.

Now, the problem. If redirect the user to a resource on SAMLIntegration (for example ofbizwebsite.com/SAMLIntegration/control/aview or any ofbizwebsite.com/SAMLIntegration/control/* by calling response.sendRedirect("aview") ) check works and login is preserved. Visiting any resource (for example ofbizwebsite.com/aplugin/control/anotherview ) by navigating the application does not preserve the session.

OFBiz use internally a mechanism for preserving the userLogin between webapps, by creating an HashMap between and UUID and a UserLogin object. The UUID is passed between two different resources, appending this key to each path (so ofbizwebsite.com/aplugin/control/anotherview?externalKey=THEEFFECTIVEUUID )

To my understanding, changing from ofbizwebsite.com/SAMLIntegration/control/* to ofbizwebsite.com/aplugin/control/* determine a session loss. So, my idea was to replace the UUID mechanism with SAML2. However, I do not know how to solve this problem.

In particular, I would like to execute a SAML request each time the checker function is executed. If I can't find the user in the session, a SAML request is fired. However, my problem is HOW to manage the response. Normally, I would redirect it to the acs ofbizwebsite.com/SAMLIntegration/control/acs . Doing so, however, does not allow me to handle the response in the checker function, as the control is passed to another servlet by an external request (the SAML response fired by the IdP). Should I provide a different acs for each different path? (so one for SAMLIntegration and one for aplugin ?) And, even if this was the case, how can I return the control to the checker function which has invoked the SAML request?

Here you go for installing the Shibboleth HTTPD module: https://pad.nereide.fr/SAMLWithShibboleth

You also need this method somewhere in OFBiz (I recommend LoginWorker.java, but you can put it where you want). It allows to use the externalAuthId of the userLogin for authentication, with the uid returned by the sso:

public static String checkShibbolethRequestRemoteUserLogin(HttpServletRequest request, HttpServletResponse response) {
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
        Delegator delegator = dispatcher.getDelegator();

        // make sure the user isn't already logged in
        if (!LoginWorker.isUserLoggedIn(request)) {
            String remoteUserId = (String) request.getAttribute("uid"); // This is the one which works, uid at Idp, remoteUserId here
            if (UtilValidate.isNotEmpty(remoteUserId)) {
                //we resolve if the user exist with externalAuthId
                String userLoginId = null;
                GenericValue userLogin;
                try {
                    List<GenericValue> userLogins = delegator.findList("UserLogin",
                            EntityCondition.makeConditionMap("externalAuthId", remoteUserId, "enabled", "Y"),
                            null, null, null, true);
                    userLogin = userLogins.size() == 1 ? userLogins.get(0) : null;
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                    return "error";
                }
                if (userLogin != null) {
                    userLoginId = userLogin.getString("userLoginId");
                }
                //now try to log the user found
                return LoginWorker.loginUserWithUserLoginId(request, response, userLoginId);
            }
        }
        return "success";
    }

You also need to have this method as an OFBiz preprocessor in the webapp controllers. I suggest to have a look at common-controller.xml.

Finally you need the configs that redirect to the SSO page if no session. That should do the job, at least it works for them...

Finally I recommend https://www.varonis.com/blog/what-is-saml in case of need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM