FusionAuth
    • Home
    • Categories
    • Recent
    • Popular
    • Pricing
    • Contact us
    • Docs
    • Login

    Refresh Token Clarity

    Scheduled Pinned Locked Moved Unsolved
    Q&A
    2
    4
    919
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A
      alan.wood
      last edited by

      We are trying to utilize refresh tokens in a SPA web site. To do so we had to reduce our security settings by not requiring client authentication so that it was able to exchange the refresh token for an access token.

      We are okay with this since we also have "require PKCE" if no client secret is passed in, but wanted to verify that the refresh token itself was not a source of risk.

      I can't prove that the refresh token (essentially a bearer token now) is either:

      1. Sender Constrained
      2. Refresh Token Rotation Implemented

      We did a test for #2 with "one time use" on, expecting the refresh chain to be rejected in the detection of an "attack".

      Issue a /authorize and get a code
      Exchange code for tokens (includes refresh token)
      Use refresh token to get a new (access token, refresh token) pair
      Use OLD refresh token again to attempt to get a new pair, this fails [so far so good]
      Use NEW refresh token from step above to get a pair

      The expectation is that the NEW refresh token is revoked due to the "attack" detected with the use of the OLD refresh token. Essentially we should assume that the credentials were stolen and used maliciously.

      However, that doesn't happen with FA. Instead, the refresh token is allowed to get a new access token.

      This allows the following attack:

      1. Attacker/Malicious code gains access to refresh token
      2. Attacker immediately uses refresh token to gain new access token
      3. Real code attempts to get a new access token and is refused due to one-time
      4. Attacker continues to use refresh chain to access application

      I'm trying to prove that refresh tokens are "safe" to use in a public client and would like some guidance since I can't find any information about how the above attack is mitigated in Fusion Auth. Does anything else mitigate this attack?

      Thanks!

      PingIdentity Blog Post on Refresh Token Rotation

      Auth0 Blog Post on Refresh Token Rotation

      danD 1 Reply Last reply Reply Quote 0
      • danD
        dan @alan.wood
        last edited by

        @alan-wood That is the current behavior.

        If you'd like to keep an eye on whether old refresh tokens are used, you might look at this webhook, which fires every time a JWT is refreshed and this one, which is fired every time a refresh token is revoked. Both of these have the userId and refreshToken.

        You could watch for collisions (storing them in your database or redis or wherever) and manually revoke any refresh token in such a case.

        Please file an issue in our github issues repo outlining your concern if you think this should be handled by FusionAuth. Feel free to reference this forum post.

        --
        FusionAuth - Auth for devs, built by devs.
        https://fusionauth.io

        A 1 Reply Last reply Reply Quote 0
        • A
          alan.wood @dan
          last edited by

          @dan I've raised a new feature request to add this functionality to Fusion Auth. The webhook idea was interesting, but there is no call when the one-time JWT refresh token is "re-used". Therefore, I can't detect the scenario and revoke the chain. The alternative is to open the JWT refresh token to be re-usable. That's another set of security issues that I don't want to have in the system.

          I've raised the issue here: Issue #1619

          danD 1 Reply Last reply Reply Quote 0
          • danD
            dan @alan.wood
            last edited by

            @alan-wood Hmmm.

            First, thanks for filing the issue. I appreciate it.

            but there is no call when the one-time JWT refresh token is "re-used".

            Second, I'm pretty sure the webhook idea will work. Here's my thoughts:

            • User 123 logs in, gets refresh token A
            • Use refresh token to get a new (access token, refresh token) pair
            • System catches jwt refresh event and records token A for this user (so the userId 123, token A pair). It generates token B.
            • Use refresh token A again to attempt to get a new pair, this fails [so far so good]
            • The webhook should fire again and records that token A was used again (by looking up the refresh token value in the pair). Uh-oh!
            • Fire off an event to revoke all refresh tokens for the user 123: https://fusionauth.io/docs/v1/tech/apis/jwt#revoke-refresh-tokens
            • Using refresh token B will fail, because all refresh tokens are revoked.

            Have you tried this approach? What am I missing?

            --
            FusionAuth - Auth for devs, built by devs.
            https://fusionauth.io

            1 Reply Last reply Reply Quote 0
            • First post
              Last post