IBM Security Verify

 View Only
  • 1.  Rotating Refresh Tokens

    Posted Sat May 07, 2022 10:46 PM
    We have a SPA web application authenticating using OIDC + PKCE.

    I am implementing logic where once the `access_token` expires, I am requesting a new one using the `refresh_token`. When Verify returns with a new `access_token` a new `refresh_token` is also issued. I'm noticing, however, that the old `refresh_token` (i.e. the one I used in the request) is still valid.

    Example of an API call requesting a new `access_token`, which at the same time returns a new `refresh_token`:
    fetch("https://example.verify.ibm.com/v1.0/endpoint/default/token", {
      "method": "POST",
      "headers": {
        "Content-Type": "application/x-www-form-urlencoded",
        "Accept": "application/json"
      },
      "body": {
        "grant_type": "refresh_token",
        "refresh_token": "HXXXXXXXXXXXX30c",
        "client_id": "XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"
      }
    })
    .then(response => {
      console.log(response);
    })
    .catch(err => {
      console.error(err);
    });​

    Example of the response received from Verify:
    {
    	"access_token": "XXXXaccess_tokenXXXXXX",
    	"refresh_token": "XXXXresfreshXXXXXX",
    	"scope": "openid profile email",
    	"grant_id": "XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX",
    	"id_token": "XXXXXXXXX",
    	"token_type": "Bearer",
    	"expires_in": 1399
    }


    My question(s)
    My concern is that I now have two `refresh_token`, both of which can be used to request additional `access_token`. My goal is to reduce the blast radius by having only a single active `refresh_token`. Using the latest `refresh_token` returned in the token response feels like the most secure option.

    It is the client application's responsibility to revoke the old `refresh_token`? Or, is there a setting within Verify I should select to make the old `refresh_token` expire as soon as it's used to request a new `access_token`?

    ------------------------------
    Timothy
    ------------------------------


  • 2.  RE: Rotating Refresh Tokens

    InnerCircle
    Posted Mon May 09, 2022 08:44 AM
    I was curious about this as we are working with similar flows and I'll likely get asked the same question.

    I looked up the spec:  https://datatracker.ietf.org/doc/html/rfc6749#section-6

    It reads:
       The authorization server MAY issue a new refresh token, in which case
       the client MUST discard the old refresh token and replace it with the
       new refresh token.  The authorization server MAY revoke the old
       refresh token after issuing a new refresh token to the client.  If a
       new refresh token is issued, the refresh token scope MUST be
       identical to that of the refresh token included by the client in the
       request.​

    I agree with you, it does seem like it should be revoked.  If it were me, I'd probably just do it in the mapping rules if the refresh token being used for the authorization at the time of the refresh request,  Maybe in the post rule, after the new access and refresh tokens are generated and prepared to be returned.

    I'll be curious what anyone else says on this.  This conversation may have generated a new backlog item for me, thanks for bringing it up.

    ------------------------------
    Matt Jenkins
    ------------------------------



  • 3.  RE: Rotating Refresh Tokens

    InnerCircle
    Posted Mon May 09, 2022 08:49 AM
    I meant to say "If it were me, I'd probably just do it in the mapping rules if the refresh token being used for the authorization at the time of the refresh request is available to issue a delete token on from the mapping rule."

    Ok the community keeps crashing when I try to edit my post so hopefully a second reply works.  :)

    ------------------------------
    Matt Jenkins
    ------------------------------



  • 4.  RE: Rotating Refresh Tokens

    IBM Champion
    Posted Mon May 09, 2022 10:14 AM

    Hi

    Does anyone of you reporting the behavior make use of the feature "Enable multiple refresh tokens for fault tolerance" referred here ?

    https://www.ibm.com/docs/en/sva/10.0.1?topic=protection-api-token-management-properties#api_prot_token_mgmt_props

    Specifies how refresh tokens are handled. When this option is enabled, and a refresh request is made, the initially-used refresh token remains active (assuming it was initially active), even after a successful refresh request is made and a new token pair (access token and refresh token) is returned. Only upon the subsequent use of the new access token or new refresh token will the initially presented refresh token be invalidated. If the initially used refresh token is presented again, the tokens issued on the first refresh request (Pair 1) are revoked, and another token pair (access token and refresh token) is issued. This new pair (Pair 2) is valid, and Pair 1 is invalid.

    This option is available only if you enable the Issue refresh token option.

    Default value: disabled

     

    This feature is useful I found in cases where there might be a racing condition inside multi-threaded client apps thus preventing to immediately terminate the previous RT when obtaining a new one. But this feature is disabled by default.



    ------------------------------
    Sylvain Gilbert
    ------------------------------



  • 5.  RE: Rotating Refresh Tokens

    Posted Mon May 09, 2022 10:38 AM
    Hi Sylvain,

    It is funny you would bring this up because in between when I posted on the community thread and today, I observed this behaviour. I don't see the Enable multiple refresh tokens for fault tolerance option in IBM Security Verify SaaS. However, I gathered that this is how the SaaS works by default.

    I'm wondering whether this is a bit of a non-issue because in my code, immediately after receiving the new access_token, I am using it to get User Info, therefore invaliding the original refresh_token.  I will assume most developers will want to do something similar (i.e. use the new access_token as soon as they receive it). Ergo, now that I am thinking about it, this is less of a concern than I initially thought. That said, to help force developers to ensure good security habits, it might be worth providing Verify Administrators with an opportunity to enforce an "expire-immediately" behaviour so that the old tokens expire immediately after the refresh token is used.

    Over the next couple of days I will be doing some more development with this and will provide further details on what I find.

    In the interim, I would be curious to know if there is an option within Verify SaaS to expire old tokens immediately, rather than keeping the old tokens valid until there is a new request using the new tokens.

    ------------------------------
    Timothy
    ------------------------------



  • 6.  RE: Rotating Refresh Tokens

    IBM Champion
    Posted Mon May 09, 2022 10:45 AM

    Hi Timothy

     

    It is only now that I realize that this thread is about the IBM Security Verify SaaS offering. My reply was about the IBM Security Verify Access Appliance offering. Would be interested to find out from the vendor if the Appliance feature "Enable multiple refresh tokens for fault tolerance" was transposed over to and activated by default in the SaaS offering.



    ------------------------------
    Sylvain Gilbert
    ------------------------------



  • 7.  RE: Rotating Refresh Tokens

    InnerCircle
    Posted Mon May 09, 2022 10:44 AM
    @Sylvain Gilbert Thanks!  I didn't even realize that was an option.  In my case, I just tested and the refresh tokens are in fact not any good after it refreshes.  In my lab I do NOT have the option checked (running v10.0.3.1).  It is really good to know about this option, as our developers are currently working to implement refresh tokens so I expect weird stuff like this to arise here over the next few months.  Many thanks for pointing it out.

    Maybe @Timothy didn't realize his tokens were actually being revoked as well.  I didn't realize this until I specifically tested them (all my test cases were setup to use the most recent refresh token, I had never tried to pass the first one before until now when I altered the test case).​

    ------------------------------
    Matt Jenkins
    ------------------------------



  • 8.  RE: Rotating Refresh Tokens

    Posted Tue May 10, 2022 10:44 AM
    Hi @Matt Jenkins,

    Just to colour around this a little...

    What I meant with my initial post is that (with the original `refresh_token`) I ​can run the code below over and over, generating a new `refresh` and `access` token each time. Each `refresh_token` and `access_token` returned is useable:

    fetch("https://example.verify.ibm.com/v1.0/endpoint/default/token", {
      "method": "POST",
      "headers": {
        "Content-Type": "application/x-www-form-urlencoded",
        "Accept": "application/json"
      },
      "body": {
        "grant_type": "refresh_token",
        "refresh_token": "__ORIGINAL_REFRESH_TOKEN__",
        "client_id": "XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"
      }
    })
    .then(response => {
      console.log(response);
    })
    .catch(err => {
      console.error(err);
    });​

    My expectation was that the above request would only work once because the original `refresh_token` would expire immediately after requesting a new token. That doesn't appear to be the case.

    After a bit more testing, I noticed that the Renew refresh token lifetime option appears to invalidate old tokens once the new one has been used. But, that experience isn't consistent. I've found situations where I've requested a new `access_token` and found that the original and newly-issued `access_token` both remain active. Steps to reproduce would be:

    1. Go through Authorization Code + PKCE authorization flow.
    2. Use `refresh_token` from step 1 to generate a new `access_token`/`refresh_token` pair.
    3. Do API call with `access_token` (from step 1) <-- This works.
    4. Do API call with newly-issued `access_token` (from step 2) <-- This works too!
    5. Do API call again with `access_token` (from step 1) <-- This works, still!

    For now, I've gotten around this by using very short expiry times. But, it might be something worth looking into.​​​​

    ------------------------------
    Timothy
    ------------------------------



  • 9.  RE: Rotating Refresh Tokens

    InnerCircle
    Posted Wed May 11, 2022 08:38 AM
    Interesting, I am using the on-prem software version so it seems like, at least in my opinion, you've discovered something that maybe should be addressed in the SaaS offering.  On the on-prem version, there is an option "Enforce single access token per authorization grant" that we have enabled.  The documentation reads "If enabled, all previously granted access tokens are revoked after a new access token is generated presenting the refresh token to the authorization server."

    https://www.ibm.com/docs/en/sva/10.0.3?topic=protection-api-token-management-properties

    I'm surprised the SaaS version doesn't offer this option and the one Sylvain pointed out earlier.

    On a side note, I really need to find time to develop automated test cases around things like this.  You bring up some excellent concerns.  If functionality in the product were ever to change, someone were to update our mapping rules or API configuration and make a mistake, etc. we could end up with security holes we were unaware of dealing with these tokens.  If anyone is aware of anything already out there that would test an authorization server against the RFCs and best security practices it would be much appreciated to hear about.


    ------------------------------
    Matt Jenkins
    ------------------------------