Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-5975

SecurityToken::isExpired: add clock skew option

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.7.10, 2.7.12
    • Fix Version/s: 2.7.13, 3.0.2
    • Component/s: None
    • Labels:
      None
    • Estimated Complexity:
      Unknown

      Description

      We notice race conditions with some of our clients when CXF verifies if SecurityTokens cached locally are still valid or expired. One reason could be clock desynchronization, another reason is that while the token was still valid at the moment of request construction, it isn't when the SOAP message arrives on the server (1s difference suffices).

      Is it possible to add a clock skew option to org.apache.cxf.ws.security.tokenstore.SecurityToken.isExpired() or org.apache.cxf.ws.security.trust.STSClient to compensate clock differences between client and server.

      Our current workaround is to subclass the STSClient class.

      public class STSClockSkewClient extends STSClient {
      
          private static final int CLOCK_SKEW = 15 * 1000 /* 15s */;
      
          public STSClockSkewClient(Bus b) {
              super(b);
          }
      
          @Override
          protected SecurityToken createSecurityToken(Element el, byte[] requestorEntropy) throws WSSecurityException {
              SecurityToken securityToken = super.createSecurityToken(el, requestorEntropy);
              Date expires = securityToken.getExpires();
              if (expires != null) {
                  securityToken.setExpires(new Date(expires.getTime() - CLOCK_SKEW));
              }
              return securityToken;
          }
      
      }
      

      A possible workaround is to handle this in the STS and set Lifetime>Expires in the RSTR response not equal but some time before the end of the SAML token, but most of the times the STS clients have no control over the STS service and cannot ask the service provider to make this change.

        Activity

        Hide
        coheigea Colm O hEigeartaigh added a comment -

        What race conditions have you seen? I'm not keen on adding this option to SecurityToken. If the token has expired + you are seeing a subsequent race condition, then it is a bug that we should fix.

        Colm.

        Show
        coheigea Colm O hEigeartaigh added a comment - What race conditions have you seen? I'm not keen on adding this option to SecurityToken. If the token has expired + you are seeing a subsequent race condition, then it is a bug that we should fix. Colm.
        Hide
        wsalembi Willem Salembier added a comment - - edited

        Race condition is perhaps bad wording. The situation with some clients is the following.

        token valid from 0:00:00->0:59:59

        0:59:59: CXF verifies token expiration on client side and determines its valid
        – network traffic / wire time –
        1:00:00: token arrives on server and server rejects it because token is expired.

        To handle this situation:
        1) Either the server should be lax and accept tokens that expired in the last x seconds
        2) Either the client should be defensive and don't use a token that will expire within x seconds
        3) Either the client should on receiving a soap fault, automatically renew the token and resubmit the request

        In our situation we cannot change the server (option 1) and option 2 and 3 are not currently not supported in CXF thus the only thing we can do is implement the retry in our client code explicitely.

        I'd prefer a simple configuration feature of the CXF token cache to instruct that tokens expiring within x seconds must be renewed by force (eg like in the example above)

        Show
        wsalembi Willem Salembier added a comment - - edited Race condition is perhaps bad wording. The situation with some clients is the following. token valid from 0:00:00->0:59:59 0:59:59: CXF verifies token expiration on client side and determines its valid – network traffic / wire time – 1:00:00: token arrives on server and server rejects it because token is expired. To handle this situation: 1) Either the server should be lax and accept tokens that expired in the last x seconds 2) Either the client should be defensive and don't use a token that will expire within x seconds 3) Either the client should on receiving a soap fault, automatically renew the token and resubmit the request In our situation we cannot change the server (option 1) and option 2 and 3 are not currently not supported in CXF thus the only thing we can do is implement the retry in our client code explicitely. I'd prefer a simple configuration feature of the CXF token cache to instruct that tokens expiring within x seconds must be renewed by force (eg like in the example above)
        Hide
        coheigea Colm O hEigeartaigh added a comment -

        I've added a new JAX-WS configuration tag to SecurityConstants:

        /**

        • This is the value in seconds within which a token is considered to be expired by the
        • client. When a cached token (from a STS) is retrieved by the client, it is considered
        • to be expired if it will expire in a time less than the value specified by this tag.
        • This prevents token expiry when the message is en route / being processed by the
        • service. When the token is found to be expired then it will be renewed via the STS.
        • The default value is 10 (seconds). Specify 0 to avoid this check.
          */
          public static final String STS_TOKEN_IMMINENT_EXPIRY_VALUE =
          "ws-security.sts.token.imminent-expiry-value";

        So for CXF 3.0.2 it will renew the token if it is about to expire within 10 seconds. For CXF 2.7.13 this is not enabled by default in case it breaks previous deployments. In this case you will have to set the configuration tag explicitly to "10" (or however many seconds you want).

        Colm.

        Show
        coheigea Colm O hEigeartaigh added a comment - I've added a new JAX-WS configuration tag to SecurityConstants: /** This is the value in seconds within which a token is considered to be expired by the client. When a cached token (from a STS) is retrieved by the client, it is considered to be expired if it will expire in a time less than the value specified by this tag. This prevents token expiry when the message is en route / being processed by the service. When the token is found to be expired then it will be renewed via the STS. The default value is 10 (seconds). Specify 0 to avoid this check. */ public static final String STS_TOKEN_IMMINENT_EXPIRY_VALUE = "ws-security.sts.token.imminent-expiry-value"; So for CXF 3.0.2 it will renew the token if it is about to expire within 10 seconds. For CXF 2.7.13 this is not enabled by default in case it breaks previous deployments. In this case you will have to set the configuration tag explicitly to "10" (or however many seconds you want). Colm.

          People

          • Assignee:
            coheigea Colm O hEigeartaigh
            Reporter:
            wsalembi Willem Salembier
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development