Details

    Description

      This is a new bundle that provides an implementation of forms based authentication for sling.

      The login/logout servlets from the org.apache.sling.commons.auth are used.

      The AuthenticationHandler will use http basic auth credentials if they are on the request, otherwise it will use the user/pwd posted from the login form.

      The login form html is generated by a set of scripts
      1. login.html.esp - full login page (includes login_body.html.esp for the form markup)
      2. login_body.html.esp - just the login form, which may be useful for drawing the login form for an ajax context
      3. loginError.html.esp - full login-error page
      4. loginError_body.html.esp - just the login-error form, for login error in ajax context

      The above scripts are included as bundle-resources @ /libs/sling/servlet/default

      The bundle also has a couple of test scripts to show some examples of usage:
      1. loginTest.html.esp - shows who is logged in and links to login or logout
      2. loginTest2.html.esp - shows how a script can check permissions and show a login page if the anonymous user doesn't have permission to see the page,

      Some examples of usage are:
      1. http://host:port/path/to/node.login.html - show the login page and then goto http://host:port/path/to/node after authenticated
      2. http://host:port/path/to/node.login.html?s=.edit.html - show the login page and then goto http://host:port/path/to/node.edit.html after authenticated
      3. http://host:port/system/sling/logout - invalidate the session and switch back to anonymous user

      Attachments

        Activity

          enorman Eric Norman added a comment - - edited

          forms auth bundle. Unpack to sling/contrib/extensions

          enorman Eric Norman added a comment - - edited forms auth bundle. Unpack to sling/contrib/extensions

          I'd rather name it session-based authentication, because it should be clear that it requires an HttpSession to work, which is IMHO not very Sling-ish. It's ok if you (really) want to use it, but people should be warned. Once you start using a session, you are not only preventing scalability, you also make it much harder to "go back" because people quickly see the short-term benefit of coding with a session and will put things into it until you have too much code depending on it.

          alexander.klimetschek Alexander Klimetschek added a comment - I'd rather name it session-based authentication, because it should be clear that it requires an HttpSession to work, which is IMHO not very Sling-ish. It's ok if you (really) want to use it, but people should be warned. Once you start using a session, you are not only preventing scalability, you also make it much harder to "go back" because people quickly see the short-term benefit of coding with a session and will put things into it until you have too much code depending on it.

          I agree that using an HTTP session to store credentials opens the door for abusing sessions.

          IIUC, using a cookie instead of a session doesn't make any difference in terms of XSS vulnerability?
          Session key is stored in a cookie or in the URL, so accessible from javascript anyway.

          If that's the case, I would much prefer a cookie-based solution, if we are going to add such a module to Sling. That probably doesn't make much difference in terms of implementation (I have not looked at Eric's code yet).

          bdelacretaz Bertrand Delacretaz added a comment - I agree that using an HTTP session to store credentials opens the door for abusing sessions. IIUC, using a cookie instead of a session doesn't make any difference in terms of XSS vulnerability? Session key is stored in a cookie or in the URL, so accessible from javascript anyway. If that's the case, I would much prefer a cookie-based solution, if we are going to add such a module to Sling. That probably doesn't make much difference in terms of implementation (I have not looked at Eric's code yet).

          > IIUC, using a cookie instead of a session doesn't make any difference in terms of XSS vulnerability?
          > Session key is stored in a cookie or in the URL, so accessible from javascript anyway.

          Correct, both are XSS vulnerable. Only plain basic auth is not XSS vulnerable. Although the session key might be restricted to a shorter time span, so that the timeframe for attacks is limited.

          But in any case, where you don't want to send the username/password in the cookie (ie. an Authorization cookie like the HTTP basic auth header) you need to store something on the server side, ie. introduce a session.

          alexander.klimetschek Alexander Klimetschek added a comment - > IIUC, using a cookie instead of a session doesn't make any difference in terms of XSS vulnerability? > Session key is stored in a cookie or in the URL, so accessible from javascript anyway. Correct, both are XSS vulnerable. Only plain basic auth is not XSS vulnerable. Although the session key might be restricted to a shorter time span, so that the timeframe for attacks is limited. But in any case, where you don't want to send the username/password in the cookie (ie. an Authorization cookie like the HTTP basic auth header) you need to store something on the server side, ie. introduce a session.

          What I meant was to use a cookie that's only an ID that points to server-side stored credentials.

          I agree that it sounds like a session...and thinking about it this also means that server-side data needs to be purged after some expiration time, etc...which servlet containers do just fine for sessions.

          So a cookie ID is probably not much better than a session. It would just prevent people from falling into the session trap just because that module of Sling is using sessions.

          bdelacretaz Bertrand Delacretaz added a comment - What I meant was to use a cookie that's only an ID that points to server-side stored credentials. I agree that it sounds like a session...and thinking about it this also means that server-side data needs to be purged after some expiration time, etc...which servlet containers do just fine for sessions. So a cookie ID is probably not much better than a session. It would just prevent people from falling into the session trap just because that module of Sling is using sessions.

          OTOH using a cookie instead of the standard session mechanism the server-side data could be persisted in the repository (with suitable access control), which solves the clustering scenario as well - and purging that is easy with a background cleanup thread.

          So maybe cookie ID is good...or maybe I should stop thinking aloud in JIRA

          bdelacretaz Bertrand Delacretaz added a comment - OTOH using a cookie instead of the standard session mechanism the server-side data could be persisted in the repository (with suitable access control), which solves the clustering scenario as well - and purging that is easy with a background cleanup thread. So maybe cookie ID is good...or maybe I should stop thinking aloud in JIRA
          mmoulton Mike Moulton added a comment -

          I like the idea of using the repository since it frees you from relying on app server clustering of http sessions. Not to mention, it seems a bit more 'slingish' than using the http session.

          mmoulton Mike Moulton added a comment - I like the idea of using the repository since it frees you from relying on app server clustering of http sessions. Not to mention, it seems a bit more 'slingish' than using the http session.
          enorman Eric Norman added a comment - - edited

          I'm not opposed to storing the credential cache in the repository. I will try that out and provide a new patch.

          enorman Eric Norman added a comment - - edited I'm not opposed to storing the credential cache in the repository. I will try that out and provide a new patch.
          ianeboston Ian Boston added a comment -

          A data point for you on respository clustering of cookies.

          Sakai 2 (the version not based on Sling) uses a database table to store custom session cookies, and has been in production for reasonably large clusters for about 4 years (16 node clusters) the result is not entirely happy.

          Here are some of the issues.

          1. "Ghost busting" where a server goes away from the cluster a reasonably complex background thread performs ghost session busting. This generates both database contention and network traffic.

          2. Cookies have to have affinity to app servers unless sub ms propagation of sessions can be guaranteed. With a single Oracle/MySQL DB back end we found that we could not guarantee no race conditions without affinity. AFAIK, the current open source cluster for Jackrabbit does not have sub ms propagation of events between Cluster nodes.

          3. There are a number of good quality cluster wide replication frameworks available [A][B][C] that do a good job here, to start with HttpSession is not a problem if its not abused, ie only very small amounts of recreatable data should be stored to keep true to REST and session usage should be actively policed. Abandoning HttpSession makes it harder for deployers to configure cluster sync.

          4. Concurrency: In a very highly loaded system anything that causes concurrency issues will be a nightmare. We have already proved [D] that a high number of concurrent writes to even a deeply hierachical area of the content tree carries the risk of non mergable concurrent modifications (about 1%) which need to be handled. Server persisted storage, with a last access time are likely to create just this type of issue.

          All of this is based on the DB persistence managers or direct JDBC avalable in Jackrabbit and may not be true of other custom proprietary persistance managers

          IMVHO, I would not make the same mistakes as were made in Sakai2 and invent a new mechanism of cluster wide cookie management. Those mistakes ( and not policing session usage) were one of the driving reasons for abandoning our current code base and adopting Sling.

          A. Standard container session replication (Jetty & Tomcat)
          B. Terracotta and others
          C. Cluster wide caches (EhCache, Memcache etc)

          BTW, I have a bundle for EhCache which we use.

          ianeboston Ian Boston added a comment - A data point for you on respository clustering of cookies. Sakai 2 (the version not based on Sling) uses a database table to store custom session cookies, and has been in production for reasonably large clusters for about 4 years (16 node clusters) the result is not entirely happy. Here are some of the issues. 1. "Ghost busting" where a server goes away from the cluster a reasonably complex background thread performs ghost session busting. This generates both database contention and network traffic. 2. Cookies have to have affinity to app servers unless sub ms propagation of sessions can be guaranteed. With a single Oracle/MySQL DB back end we found that we could not guarantee no race conditions without affinity. AFAIK, the current open source cluster for Jackrabbit does not have sub ms propagation of events between Cluster nodes. 3. There are a number of good quality cluster wide replication frameworks available [A] [B] [C] that do a good job here, to start with HttpSession is not a problem if its not abused, ie only very small amounts of recreatable data should be stored to keep true to REST and session usage should be actively policed. Abandoning HttpSession makes it harder for deployers to configure cluster sync. 4. Concurrency: In a very highly loaded system anything that causes concurrency issues will be a nightmare. We have already proved [D] that a high number of concurrent writes to even a deeply hierachical area of the content tree carries the risk of non mergable concurrent modifications (about 1%) which need to be handled. Server persisted storage, with a last access time are likely to create just this type of issue. All of this is based on the DB persistence managers or direct JDBC avalable in Jackrabbit and may not be true of other custom proprietary persistance managers IMVHO, I would not make the same mistakes as were made in Sakai2 and invent a new mechanism of cluster wide cookie management. Those mistakes ( and not policing session usage) were one of the driving reasons for abandoning our current code base and adopting Sling. A. Standard container session replication (Jetty & Tomcat) B. Terracotta and others C. Cluster wide caches (EhCache, Memcache etc) BTW, I have a bundle for EhCache which we use.
          enorman Eric Norman added a comment - - edited

          org.apache.sling.cookieauth.zip is the source for a bundle that stores the encrypted auth credentials in a cookie.

          orig.apache.sling.sessionauth.zip is the source for a bundle that stores the encrypted auth credentials in a session attribute.

          enorman Eric Norman added a comment - - edited org.apache.sling.cookieauth.zip is the source for a bundle that stores the encrypted auth credentials in a cookie. orig.apache.sling.sessionauth.zip is the source for a bundle that stores the encrypted auth credentials in a session attribute.
          enorman Eric Norman added a comment - - edited

          Ian makes some good points. I experimented a little with storing the credentials in the repository, but ran into many concurrency issues trying to keep track of when the stored credentials are stale.

          As an alternative, I refactored my previous patch to provide two ways to do form based authentication:
          1. org.apache.sling.sessionauth - this bundle uses http sessions where the auth credentials are cached on the server-side as a session attribute
          2. org.apache.sling.cookieauth - this bundle gets/sets the auth credentials from the value of a cookie (password is encrypted in the cookie value).

          The above satisfies my needs for now. I would like to hear the thoughts of the community regarding if there are better ways to harden the value of the cookieauth so the user/password stored in the cookie value are not open to attack.

          enorman Eric Norman added a comment - - edited Ian makes some good points. I experimented a little with storing the credentials in the repository, but ran into many concurrency issues trying to keep track of when the stored credentials are stale. As an alternative, I refactored my previous patch to provide two ways to do form based authentication: 1. org.apache.sling.sessionauth - this bundle uses http sessions where the auth credentials are cached on the server-side as a session attribute 2. org.apache.sling.cookieauth - this bundle gets/sets the auth credentials from the value of a cookie (password is encrypted in the cookie value). The above satisfies my needs for now. I would like to hear the thoughts of the community regarding if there are better ways to harden the value of the cookieauth so the user/password stored in the cookie value are not open to attack.
          enorman Eric Norman added a comment - - edited

          Updated the bundles to utilize org.apache.sling.commons.auth

          enorman Eric Norman added a comment - - edited Updated the bundles to utilize org.apache.sling.commons.auth
          enorman Eric Norman added a comment - - edited

          Updated again. If http basic auth info is in the request, let the auth challenge fall through to the httpauth handler.

          enorman Eric Norman added a comment - - edited Updated again. If http basic auth info is in the request, let the auth challenge fall through to the httpauth handler.
          enorman Eric Norman added a comment - - edited

          Updated the description to reflect the changes in the implementation after the integration with org.apache.sling.commons.auth

          enorman Eric Norman added a comment - - edited Updated the description to reflect the changes in the implementation after the integration with org.apache.sling.commons.auth

          Thanks for the patches. I have been taking a look at it and they basically look fine.

          Just a few comments for discussions:

          • Except for the concrete cookie handling, both are actually the same. How about merging them and making the
            actual handling of the data – session or cookie – configurable ?
          • Currently the cookie/session data is set in the extractRequestParameterAuthentication method before it is
            known whether the credentials are valid or not. I would assume this can be enhanced with the functionality
            proposed by SLING-1314. Thus the cookie/session data setting could be delayed until after receiving
            the success notification.
          • SessionAuth: dropping credentials and requesting credentials invalidates the session. This is probably not
            good if the session is used for other things. Maybe it would be better to just remove the credentials attribute
            (and only invalidate the session if it becomes empty after removing the credentials) ?
          • I have concerns about sending the password back and forth in the cookie handler or keeping the password
            in the session – even though it is hashed, but it looks like it is used as is for authentication and thus is as
            susceptible to snooping as would be a plain text transmission. How about implementing a LoginModulePlugin
            and special credentials we can use in case we deem the cookie/session info valid. This would probably require
            more state to be kept in the authentication handler.
          fmeschbe Felix Meschberger added a comment - Thanks for the patches. I have been taking a look at it and they basically look fine. Just a few comments for discussions: Except for the concrete cookie handling, both are actually the same. How about merging them and making the actual handling of the data – session or cookie – configurable ? Currently the cookie/session data is set in the extractRequestParameterAuthentication method before it is known whether the credentials are valid or not. I would assume this can be enhanced with the functionality proposed by SLING-1314 . Thus the cookie/session data setting could be delayed until after receiving the success notification. SessionAuth: dropping credentials and requesting credentials invalidates the session. This is probably not good if the session is used for other things. Maybe it would be better to just remove the credentials attribute (and only invalidate the session if it becomes empty after removing the credentials) ? I have concerns about sending the password back and forth in the cookie handler or keeping the password in the session – even though it is hashed, but it looks like it is used as is for authentication and thus is as susceptible to snooping as would be a plain text transmission. How about implementing a LoginModulePlugin and special credentials we can use in case we deem the cookie/session info valid. This would probably require more state to be kept in the authentication handler.
          enorman Eric Norman added a comment - - edited

          updated patch to incorporate the suggested changes

          enorman Eric Norman added a comment - - edited updated patch to incorporate the suggested changes
          enorman Eric Norman added a comment - - edited

          Thanks Felix. Your comments seem reasonable. I have attached an updated patch for review.

          • One bundle now handles both cookie (default) and session storage for the auth hash. Configurable from the web console.
          • You are correct that the changes in SLING-1314 is helpful to delay the setting of the cookie. The attached patch uses this technique so it requires the patch from SLING-1314 to be applied first.
          • SessionAuth: I removed the session.invalidate() and just remove the credentials attribute when dropping credentials.
          • The implementation now generates a more complex hash [1]. A custom LoginModulePlugin implementation is used to verify the supplied hash value matches what was expected. The changes in SLING_1116_jackrabbit_server_patch.txt (attached) were required to get the login process to accept the custom credentials object.

          [1] Auth hash pseudo-code:
          HA1 = MD5(username : realm : cryptedPassword)
          HA2 = MD5(HttpServletRequest.getRemoteAddress() : AuthenticationHandler.PATH_PROPERTY)
          authHash = MD5(HA1 : HA2)

          Thoughts?

          enorman Eric Norman added a comment - - edited Thanks Felix. Your comments seem reasonable. I have attached an updated patch for review. One bundle now handles both cookie (default) and session storage for the auth hash. Configurable from the web console. You are correct that the changes in SLING-1314 is helpful to delay the setting of the cookie. The attached patch uses this technique so it requires the patch from SLING-1314 to be applied first. SessionAuth: I removed the session.invalidate() and just remove the credentials attribute when dropping credentials. The implementation now generates a more complex hash [1] . A custom LoginModulePlugin implementation is used to verify the supplied hash value matches what was expected. The changes in SLING_1116_jackrabbit_server_patch.txt (attached) were required to get the login process to accept the custom credentials object. [1] Auth hash pseudo-code: HA1 = MD5(username : realm : cryptedPassword) HA2 = MD5(HttpServletRequest.getRemoteAddress() : AuthenticationHandler.PATH_PROPERTY) authHash = MD5(HA1 : HA2) Thoughts?

          > HttpServletRequest.getRemoteAddress()

          this method returns the address of the client or the last proxy that sent the request. if there is indeed a proxy in between, then this may hide that a request is possibly sent from a different client.

          mreutegg Marcel Reutegger added a comment - > HttpServletRequest.getRemoteAddress() this method returns the address of the client or the last proxy that sent the request. if there is indeed a proxy in between, then this may hide that a request is possibly sent from a different client.

          Thanks, Marcel.

          Good point.

          In this case we may want to the remove the getRemoteAddress check from the verification game because the client generally has little to no way of controlling this situation. On the other hand, we might still keep it (knowing the issues and make it configurable to switch off)

          fmeschbe Felix Meschberger added a comment - Thanks, Marcel. Good point. In this case we may want to the remove the getRemoteAddress check from the verification game because the client generally has little to no way of controlling this situation. On the other hand, we might still keep it (knowing the issues and make it configurable to switch off)
          ianeboston Ian Boston added a comment -

          One comment that might be relevant:

          I notice that the hash in the cookie is of the form md5(remoteAddress:path):md5(userId:authRealmsha1(

          {sha1}

          userPassword))

          which makes the cookie static for a user from an address which might be a proxy address, I which case the cookie is susceptible to capture and reuse.,
          remove the remote_address and it effectively becomes a clear text password in http headers with every request.

          I also assumes that Jackrabbit has access to the password, which in the case of a LoginModulePlugin is not the case.

          In a slightly different senario, were we are using a SSO system to authenticate users we need to have secure cookies to track user identity against each request and we have used sha1(expirytime:securetoken:userID)@securetokennumber,expirytime@userID as the cookie, where expiry time is the epoch when the cookie becomes invalid, securetoken number comes for a circular buffer to securetokens, identified by securetokennumber, that buffer completely refreshing after 2.5 times the TTL on the cookie. Documented in more detail at [1], implemented at [2].

          The approach isn't totally secure (nothing is), and still needs to have the whole server operating over ssl, but the tokens do expire. The downside is that the circular buffer of secure tokens needs to be distributed in a cluster, and persisted, however 5x20 bytes changing every 10 minutes shouldn't be too hard to distribute.

          Also if you want to avoid having to manage special Credentials you might consider using SimpleCredentials with a special attribute class as this wont require JAAS style callbacks to get round the strong JR->SimpleCredentials bindings.

          1 http://confluence.sakaiproject.org/display/KERNDOC/KERN-579+Trusted+Authentication (scroll to the bit on Cookies)
          2 http://github.com/ieb/open-experiments/tree/master/slingtests/osgikernel/bundles/trustedauth/

          ianeboston Ian Boston added a comment - One comment that might be relevant: I notice that the hash in the cookie is of the form md5(remoteAddress:path):md5(userId:authRealmsha1( {sha1} userPassword)) which makes the cookie static for a user from an address which might be a proxy address, I which case the cookie is susceptible to capture and reuse., remove the remote_address and it effectively becomes a clear text password in http headers with every request. I also assumes that Jackrabbit has access to the password, which in the case of a LoginModulePlugin is not the case. In a slightly different senario, were we are using a SSO system to authenticate users we need to have secure cookies to track user identity against each request and we have used sha1(expirytime:securetoken:userID)@securetokennumber,expirytime@userID as the cookie, where expiry time is the epoch when the cookie becomes invalid, securetoken number comes for a circular buffer to securetokens, identified by securetokennumber, that buffer completely refreshing after 2.5 times the TTL on the cookie. Documented in more detail at [1] , implemented at [2] . The approach isn't totally secure (nothing is), and still needs to have the whole server operating over ssl, but the tokens do expire. The downside is that the circular buffer of secure tokens needs to be distributed in a cluster, and persisted, however 5x20 bytes changing every 10 minutes shouldn't be too hard to distribute. Also if you want to avoid having to manage special Credentials you might consider using SimpleCredentials with a special attribute class as this wont require JAAS style callbacks to get round the strong JR->SimpleCredentials bindings. 1 http://confluence.sakaiproject.org/display/KERNDOC/KERN-579+Trusted+Authentication (scroll to the bit on Cookies) 2 http://github.com/ieb/open-experiments/tree/master/slingtests/osgikernel/bundles/trustedauth/
          mmoulton Mike Moulton added a comment -

          For security reasons, I personally would like to see the cookie value be an HMAC [1] as opposed to a plain MD5 / SHA1 hash. I found an article [2] over at benlog.com that summarized this issue pretty well.

          Here is an example taking what you outlined above, running it through an HMAC algorithm.

          KEY = // a secret key either generated at startup (cookie is only good for that execution of the JVM) or stored across executions
          MESSAGE = username : realm : cryptedPassword : HttpServletRequest.getRemoteAddress() : AuthenticationHandler.PATH_PROPERTY
          authHash = HMAC(KEY, MESSAGE) // where HMAC could use MD5 or SHA1 underneath.

          For an example of the above in Java, see [3].

          [1] http://en.wikipedia.org/wiki/HMAC
          [2] http://benlog.com/articles/2008/06/19/dont-hash-secrets/
          [3] http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#HmacEx

          mmoulton Mike Moulton added a comment - For security reasons, I personally would like to see the cookie value be an HMAC [1] as opposed to a plain MD5 / SHA1 hash. I found an article [2] over at benlog.com that summarized this issue pretty well. Here is an example taking what you outlined above, running it through an HMAC algorithm. KEY = // a secret key either generated at startup (cookie is only good for that execution of the JVM) or stored across executions MESSAGE = username : realm : cryptedPassword : HttpServletRequest.getRemoteAddress() : AuthenticationHandler.PATH_PROPERTY authHash = HMAC(KEY, MESSAGE) // where HMAC could use MD5 or SHA1 underneath. For an example of the above in Java, see [3] . [1] http://en.wikipedia.org/wiki/HMAC [2] http://benlog.com/articles/2008/06/19/dont-hash-secrets/ [3] http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#HmacEx
          ianeboston Ian Boston added a comment -

          Your right I should be using HMAC, but I am finding it very slow ~ 100ms compared to 67ns for a SHA1 hash. Every request needs to be decoded.

          This is on JDK 16. on OSX using hmacSHA1 with pre generated key, any ideas ?

          ianeboston Ian Boston added a comment - Your right I should be using HMAC, but I am finding it very slow ~ 100ms compared to 67ns for a SHA1 hash. Every request needs to be decoded. This is on JDK 16. on OSX using hmacSHA1 with pre generated key, any ideas ?
          ianeboston Ian Boston added a comment -

          sorry for the noise, looks like the the crypto api needs warming up before using, problems goes away is a dummy hmac is done in construction.

          ianeboston Ian Boston added a comment - sorry for the noise, looks like the the crypto api needs warming up before using, problems goes away is a dummy hmac is done in construction.
          enorman Eric Norman added a comment - - edited

          It looks like the dust has settled so I am going to try to summarize the suggestions below. Please correct me if I missed anything:

          1. HttpServletRequest.getRemoteAddress() is not reliable, so it should not be included in the hash

          2. Include cookie expiration time in the cookie and hash

          3. Include a securetoken in the hash. The CookieAuthenticationHandler must maintain the mapping from securetokennumber to securetoken to be able to recompute the hash on each request for comparison.

          4. Since the expirytime is included in the cookie, each request that sucessfully authenticates should update the cookie value to push the expiretime further out (currentTime + sessionTimeoutDuration).

          5. Use SimpleCredentials with custom attributes instead of a new Credentials class to avoid having to patch the jackrabbit-server bundle

          6. Use HMAC to hash the secure part of the cookie value.

          Ian's cookie value pattern looks ok to me, so if nobody objects, the cookie value calculation could look something like this

          CookieValue = HmacSHA1(expirytime : securetoken : userId)@securetokennumber,expirytime@userID

          I can take a shot at implementing the above suggestions later today if somebody else doensn't beat me to it.

          enorman Eric Norman added a comment - - edited It looks like the dust has settled so I am going to try to summarize the suggestions below. Please correct me if I missed anything: 1. HttpServletRequest.getRemoteAddress() is not reliable, so it should not be included in the hash 2. Include cookie expiration time in the cookie and hash 3. Include a securetoken in the hash. The CookieAuthenticationHandler must maintain the mapping from securetokennumber to securetoken to be able to recompute the hash on each request for comparison. 4. Since the expirytime is included in the cookie, each request that sucessfully authenticates should update the cookie value to push the expiretime further out (currentTime + sessionTimeoutDuration). 5. Use SimpleCredentials with custom attributes instead of a new Credentials class to avoid having to patch the jackrabbit-server bundle 6. Use HMAC to hash the secure part of the cookie value. Ian's cookie value pattern looks ok to me, so if nobody objects, the cookie value calculation could look something like this CookieValue = HmacSHA1(expirytime : securetoken : userId)@securetokennumber,expirytime@userID I can take a shot at implementing the above suggestions later today if somebody else doensn't beat me to it.
          ianeboston Ian Boston added a comment -

          I'd be happy to donate bits or all of the bundle from Sakai if appropriate and helpful, or feel free to grab anything you want.

          ianeboston Ian Boston added a comment - I'd be happy to donate bits or all of the bundle from Sakai if appropriate and helpful, or feel free to grab anything you want.

          Cool. Looking forward for something to commit

          Re 2: If we set an expiration time on the cookie, it is not a session cookie any more. Maybe the expiration time in the hash is enough ?

          Re 3: would it make sense to store the tokens in the repository ? This would "fix" the cluster issue - would it create others ?

          Re 5: would that be a single custom attribute ? with a customizable name ?

          Re 6: perfect.

          Again, thanks

          fmeschbe Felix Meschberger added a comment - Cool. Looking forward for something to commit Re 2: If we set an expiration time on the cookie, it is not a session cookie any more. Maybe the expiration time in the hash is enough ? Re 3: would it make sense to store the tokens in the repository ? This would "fix" the cluster issue - would it create others ? Re 5: would that be a single custom attribute ? with a customizable name ? Re 6: perfect. Again, thanks
          enorman Eric Norman added a comment - - edited

          Updated the proposed bundle to integrate the suggestions. I borrowed the TokenStore class from Ian's sample code. Thanks Ian!

          The TokenStore storage is still in the local filesystem, so it needs some more thought on how this will work in a cluster.

          enorman Eric Norman added a comment - - edited Updated the proposed bundle to integrate the suggestions. I borrowed the TokenStore class from Ian's sample code. Thanks Ian! The TokenStore storage is still in the local filesystem, so it needs some more thought on how this will work in a cluster.

          Excellent. I will integrate this into Sling tonight or tomorrow morning. Thanks a lot.

          fmeschbe Felix Meschberger added a comment - Excellent. I will integrate this into Sling tonight or tomorrow morning. Thanks a lot.

          Eric/Felix,

          Hello, I am trying to implement your session authentication solution for deployment within our Day CQ 5 CMS custom solution. I downloaded the source code, ran a maven package and deployed it into our Apache Felix OSGI container. Unfortuantely I am getting two "Cannot be resolved" import issues:

          !! org.apache.sling.commons.auth.spi,version=1.0.0 – Cannot be resolved
          !! org.apache.sling.jcr.jackrabbit.server.security,version=2.0.0 from – Cannot be resolved

          I downloaded the source code for "auth.spi" from Apache, created a bundle and deployed that into Felix; however, I am still having trouble producing a bundle for the jackrabbit dependency. There's a POM file located at org\apache\sling\jcr\jackrabbit-server however when I deploy that bundle I get another 15 cannot resolve imports from this bundle.

          Instead of going down the long path for trying to resolve all of the dependencies, is there any smaller bundle or alternate suggestion for trying to get the bundle to resolve correctly? We're using Day's CQ5 product which includes an instance of Apache Felix.

          mtorre Matt Torrenzano added a comment - Eric/Felix, Hello, I am trying to implement your session authentication solution for deployment within our Day CQ 5 CMS custom solution. I downloaded the source code, ran a maven package and deployed it into our Apache Felix OSGI container. Unfortuantely I am getting two "Cannot be resolved" import issues: !! org.apache.sling.commons.auth.spi,version=1.0.0 – Cannot be resolved !! org.apache.sling.jcr.jackrabbit.server.security,version=2.0.0 from – Cannot be resolved I downloaded the source code for "auth.spi" from Apache, created a bundle and deployed that into Felix; however, I am still having trouble producing a bundle for the jackrabbit dependency. There's a POM file located at org\apache\sling\jcr\jackrabbit-server however when I deploy that bundle I get another 15 cannot resolve imports from this bundle. Instead of going down the long path for trying to resolve all of the dependencies, is there any smaller bundle or alternate suggestion for trying to get the bundle to resolve correctly? We're using Day's CQ5 product which includes an instance of Apache Felix.

          Thanks for taking your time to try this out !

          What follows is related to the commercial Day CQ5 product...

          I assume you are using CQ 5.2.1 so your are still based on the previous Sling authentication infrastructure, where everything was contained in the Sling Engine bundle. In the meantime the authentication infrastructure has spun off into a separate bundle and new API has been defined (while the old API is still present and supported for backwards compatibility).

          Attached patch is written against the new API and also includes functionality which is specific to the Sling Embedded Jackrabbit Repository bundle, which is not present in CQ 5.

          While integrating this patch, I will try to find a way to loosen the Sling Embedded Jackrabbit Repository dependency to be able to use the bundle with CQ5, but of course dependency on the new API will remain.

          As a workaroud, you might try to upgrade the Sling Engine bundle of your CQ 5 instance to the latest trunk build and install the Sling Commons Auth bundle, too.

          fmeschbe Felix Meschberger added a comment - Thanks for taking your time to try this out ! What follows is related to the commercial Day CQ5 product... I assume you are using CQ 5.2.1 so your are still based on the previous Sling authentication infrastructure, where everything was contained in the Sling Engine bundle. In the meantime the authentication infrastructure has spun off into a separate bundle and new API has been defined (while the old API is still present and supported for backwards compatibility). Attached patch is written against the new API and also includes functionality which is specific to the Sling Embedded Jackrabbit Repository bundle, which is not present in CQ 5. While integrating this patch, I will try to find a way to loosen the Sling Embedded Jackrabbit Repository dependency to be able to use the bundle with CQ5, but of course dependency on the new API will remain. As a workaroud, you might try to upgrade the Sling Engine bundle of your CQ 5 instance to the latest trunk build and install the Sling Commons Auth bundle, too.

          To update, I was able to resolve all of my dependencies . Day just produced a product upgrade to CQ 5.3 that has an updated instance of Felix.

          For anyone that is try to implment with Day with the update2_org.apache.sling.cookieauth.zip , here are the details:

          org.apache.sling.commons.auth was taken care of in the Apache CQ 5.3 upgrade.

          I downloaded the source of org.apache.sling.jcr.jackrabbit-server and generated that bundle. There were only two packages that I couldn't resolve: org.apache.sling.jcr.base and org.apache.jackrabbit.api.jsr283.*

          I downloaded the org.apache.sling.jcr.base code, bundled it, and deployed ito Felix. Base needed the jsr283.security file.

          I downloaded the org.apache.jackrabbit.api v1.6.0 jar and "bundlized" it via bnd and installed that into Felix.

          All my dependencies have now been resolved. So to recap, to get all of the dependencies resolved, you need to include the following bundles/jars

          org.apache.jackrabbit.api (1.6.0)
          org.apache.sling.jcr.base (2.0.5.SNAPSHOT)
          org.apache.sling.jcr.jackrabbit.server (2.0.5.SNAPSHOT)
          org.apache.sling.commons.auth.spi,version=1.0.0 from org.apache.sling.commons.auth (100) <- Missing from Day CQ 5.2.1 but taken care of in Day CQ 5.3

          My next few steps will be to try and test your functionality out while integrated with Day CMS.

          mtorre Matt Torrenzano added a comment - To update, I was able to resolve all of my dependencies . Day just produced a product upgrade to CQ 5.3 that has an updated instance of Felix. For anyone that is try to implment with Day with the update2_org.apache.sling.cookieauth.zip , here are the details: org.apache.sling.commons.auth was taken care of in the Apache CQ 5.3 upgrade. I downloaded the source of org.apache.sling.jcr.jackrabbit-server and generated that bundle. There were only two packages that I couldn't resolve: org.apache.sling.jcr.base and org.apache.jackrabbit.api.jsr283.* I downloaded the org.apache.sling.jcr.base code, bundled it, and deployed ito Felix. Base needed the jsr283.security file. I downloaded the org.apache.jackrabbit.api v1.6.0 jar and "bundlized" it via bnd and installed that into Felix. All my dependencies have now been resolved. So to recap, to get all of the dependencies resolved, you need to include the following bundles/jars org.apache.jackrabbit.api (1.6.0) org.apache.sling.jcr.base (2.0.5.SNAPSHOT) org.apache.sling.jcr.jackrabbit.server (2.0.5.SNAPSHOT) org.apache.sling.commons.auth.spi,version=1.0.0 from org.apache.sling.commons.auth (100) <- Missing from Day CQ 5.2.1 but taken care of in Day CQ 5.3 My next few steps will be to try and test your functionality out while integrated with Day CMS.

          Correct, CQ 5.3 contains the necessairy new API

          But be aware, as I said previsously, I am integrating the patch such, that the Jackrabbit dependencies you listed are not needed (Sling is still based on Jackrabbit 1.6 at the moment).

          fmeschbe Felix Meschberger added a comment - Correct, CQ 5.3 contains the necessairy new API But be aware, as I said previsously, I am integrating the patch such, that the Jackrabbit dependencies you listed are not needed (Sling is still based on Jackrabbit 1.6 at the moment).

          Thanks again for providing the patch.

          I have taken the liberty to simplify it a bit:

          • replaced classes by direct method calls
          • refactored the login page call using a dedicated, configurable login form page instead of using selectors
          • merged some configuration properties
          • aligned the form action to the Servlet API 2.4 specification in SRV.12.5.3.1
          • Placed the token store inside the bundle private data (if the path is relative)

          I have commited it in Rev. 907677 and cleaned up the dependencies in Rev. 907686

          In addition I added documentation of this handler at http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/formauth
          (support for the j_verify parameter as documented is not implemented yet)

          Please review. Thanks.

          fmeschbe Felix Meschberger added a comment - Thanks again for providing the patch. I have taken the liberty to simplify it a bit: replaced classes by direct method calls refactored the login page call using a dedicated, configurable login form page instead of using selectors merged some configuration properties aligned the form action to the Servlet API 2.4 specification in SRV.12.5.3.1 Placed the token store inside the bundle private data (if the path is relative) I have commited it in Rev. 907677 and cleaned up the dependencies in Rev. 907686 In addition I added documentation of this handler at http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/formauth (support for the j_verify parameter as documented is not implemented yet) Please review. Thanks.

          In Rev. 907990 I added support for the j_validate form parameter as documented and added a j_reason request parameter for the handler to convey a reason to the login form why the user is requested to login.

          fmeschbe Felix Meschberger added a comment - In Rev. 907990 I added support for the j_validate form parameter as documented and added a j_reason request parameter for the handler to convey a reason to the login form why the user is requested to login.

          Maybe I make some mistake, but when It's not works for me correctly:

          1. I've downloaded the Sling from trunk
          2. I compiled and intalled it.
          3. I've copied the WAR file to a new tomcat instance
          4. I've tarted tomcat - Sling test OK
          5. http://localhost:8080/system/sling/form/login in browser, the login form OK
          6. After I submitted the form the following mesagge I've got:
          Content created /system/sling/form/j_security_check

          Status
          201
          Message
          Created
          Location /system/sling/form/j_security_check
          Parent Location /system/sling/form
          Path
          /system/sling/form/j_security_check
          Referer http://localhost:8080/system/sling/form/login
          ChangeLog
          created("/system/sling/form/j_security_check");
          modified("/system/sling/form/j_security_check/j_username");
          modified("/system/sling/form/j_security_check/j_password");
          Go Back

          Modified Resource

          Parent of Modified Resource

          So I've tried to debug what happens and I expreienced the extractCredentials have not been called.
          It seems to me the AuthenticanHandlers are not called.

          What was my mistake?

          robson@semmi.se Róbert Csákány added a comment - Maybe I make some mistake, but when It's not works for me correctly: 1. I've downloaded the Sling from trunk 2. I compiled and intalled it. 3. I've copied the WAR file to a new tomcat instance 4. I've tarted tomcat - Sling test OK 5. http://localhost:8080/system/sling/form/login in browser, the login form OK 6. After I submitted the form the following mesagge I've got: Content created /system/sling/form/j_security_check Status 201 Message Created Location /system/sling/form/j_security_check Parent Location /system/sling/form Path /system/sling/form/j_security_check Referer http://localhost:8080/system/sling/form/login ChangeLog created("/system/sling/form/j_security_check"); modified("/system/sling/form/j_security_check/j_username"); modified("/system/sling/form/j_security_check/j_password"); Go Back Modified Resource Parent of Modified Resource So I've tried to debug what happens and I expreienced the extractCredentials have not been called. It seems to me the AuthenticanHandlers are not called. What was my mistake?
          enorman Eric Norman added a comment - - edited

          RĂłbert, thanks for reporting this issue. It looks to me that the login action was posting the form to the wrong path. It should have gone to http://localhost:8080/j_security_check instead of http://localhost:8080/system/sling/form/j_security_check

          I corrected the code in r915677.

          Can you please try it again?

          enorman Eric Norman added a comment - - edited RĂłbert, thanks for reporting this issue. It looks to me that the login action was posting the form to the wrong path. It should have gone to http://localhost:8080/j_security_check instead of http://localhost:8080/system/sling/form/j_security_check I corrected the code in r915677. Can you please try it again?

          Thanks Eric, Now it looks OK. The testcase I described above OK.

          robson@semmi.se Róbert Csákány added a comment - Thanks Eric, Now it looks OK. The testcase I described above OK.

          In Rev. 956797 I have improved the FormReason class to provide the human-readable reason through the toString() method.

          I think for now we can close this issue and improvide the form handler furhter with new issues.

          fmeschbe Felix Meschberger added a comment - In Rev. 956797 I have improved the FormReason class to provide the human-readable reason through the toString() method. I think for now we can close this issue and improvide the form handler furhter with new issues.

          Close after release

          fmeschbe Felix Meschberger added a comment - Close after release

          People

            fmeschbe Felix Meschberger
            enorman Eric Norman
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: