Subject: [OAUTH-WG] Rotating RTs and grace periods

From: Neil Madden <[email-masked]>
Date: Tue, 2 Nov 2021 10:28:53 +0000

Hi all,

There was a previous discussion on whether to allow a grace period during refresh token rotation, allowing the client to retry a refresh if the response fails to be received due to some transient network issue/timeout [1]. Vittorio mentioned that Auth0 already implement such a grace period. We (ForgeRock) currently do not, but we do periodically receive requests to support this. The current security BCP draft is silent on whether implementing such a grace period is a good idea, but I think we should add some guidance here one way or another.

My own opinion is that a grace period is not a good idea, and if it is to be supported as an option then it should be kept as short as possible. The reason (as I mentioned in the previous thread) is that it is quite easy for an attacker to observe when a legitimate client performs a refresh flow and so can easily sneak in their own request afterwards within the grace period. There are several reasons why it is easy for an attacker to observe this:

- RT rotation is primarily intended for public clients, such as mobile apps and SPAs. These clients are geographically distributed across the internet, and so there is a good chance that the attacker is able to observe the network traffic of at least some of these client instances.
- The refresh flow is typically the only request that the client makes directly to the AS after initial authorization, so despite the traffic being encrypted it is very easy for an observer to determine that the client is performing a refresh whenever it makes any connection to the AS.
- As well as observing the request itself, an attacker may be able to observe the DNS lookup for the AS hostname instead, which is even more likely to be observable and also in plaintext most of the time.
- An attacker in a position to steal RTs from e.g. localStorage, is probably also in a good position to either observe when the legitimate client refreshes or to actually force it to refresh early (e.g., by deleting the corresponding AT from the same storage).

I know some people argue that a grace period is a reasonable trade-off between security and usability. But I think that this kind of attack would be quite easy to carry out in practice for the reasons I suggest above, so I think the security actually degrades extremely quickly if you allow a grace period of any reasonable length. 

On the other hand, if we discourage this entirely then people may use dubious workarounds instead (e.g., one proposal I’ve seen was to use an ID token with the JWT Bearer grant, effectively turning the ID Token into an ad-hoc RT with much fewer protections).

As a strawman, what would people think of wording like the following:

---
The AS MAY allow the original RT to be replayed for a short grace period to allow the client to recover if the response is not received due to a network problem or other transient issue. However, implementors should be aware that an attacker may be able to easily observe when the legitimate client makes a refresh request to the AS and so time their use of a stolen RT to occur within the grace period. Any grace period MUST be kept as short as possible, and MUST NOT exceed 60 seconds. Clients should prefer sender-constrained refresh tokens if recovery from network issues is a priority.
—

(The 60 seconds limit here is based on Auth0’s grace period).

[1]: https://mailarchive.ietf.org/arch/msg/oauth/WXwKxQM2poW7bqOOGGp4POYolFk/ <https://mailarchive.ietf.org/arch/msg/oauth/WXwKxQM2poW7bqOOGGp4POYolFk/> 

Kind regards,

Neil

---

From: Pieter Kasselman <[email-masked]>
Date: Tue, 2 Nov 2021 14:09:26 +0000

Neil

Is the goal to accommodate network latency or clock drift? It would be helpful to include reasons for why a grace period should be considered if it is allowed.

Without knowing the reasons for the grace period it is not clear why a grace period is a better solution than just extending the expiry time by a set time (60 seconds in your example) and having the client present the token a little earlier.

If grace periods are allowed, it may be worth considering adding additional mitigations against replay. For example, a grace period may be allowed if the refresh token is sender constrained with DPoP so there is at least some assurances that the request is originating from the sender (especially if the nonce option is used with DPoP).

I would worry about adding more complexity and less predictability by adding grace periods though (e.g. by looking at a refresh token, will you be able to tell if it can still be used or not), but your point that implementors may solve for it in other less predictable ways raises a valid point.

Cheers

Pieter

From: OAuth <[email-masked]> On Behalf Of Neil Madden
Sent: Tuesday 2 November 2021 10:29
To: oauth <[email-masked]>
Subject: [EXTERNAL] [OAUTH-WG] Rotating RTs and grace periods

Hi all,

On the other hand, if we discourage this entirely then people may use dubious workarounds instead (e.g., one proposal I've seen was to use an ID token with the JWT Bearer grant, effectively turning the ID Token into an ad-hoc RT with much fewer protections).

---
-

(The 60 seconds limit here is based on Auth0's grace period).

[1]: https://mailarchive.ietf.org/arch/msg/oauth/WXwKxQM2poW7bqOOGGp4POYolFk/<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmailarchive.ietf.org%2Farch%2Fmsg%2Foauth%2FWXwKxQM2poW7bqOOGGp4POYolFk%2F&data=04%7C01%7Cpieter.kasselman%40microsoft.com%7Cbdb0969234774ba6f87608d99deba06c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637714457664531224%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=CDskCHwXxJxGdmudTW33gUT5f3%2B835uZDxyNEmKkiFc%3D&reserved=0>

Kind regards,

Neil

---

From: Neil Madden <[email-masked]>
Date: Tue, 2 Nov 2021 21:20:13 +0000

The grace period is to allow the client to retry if it fails to receive the new RT for any reason. For example, the client performs a successful refresh flow but loses mobile network signal before receiving the response. The grace period allows the client to simply retry the request, whereas without a grace period the first request would have invalidated the old RT leaving the client with no option but to perform a full authorization flow again to get a new one. 

I’m generally against allowing a grace period at all, but given that it’s a common request and some implementations are already allowing this, I’m hoping we can find some wording we can all agree on. 

I agree that a grace period is more acceptable if the RT is sender-constrained by something like DPoP, but then in that case does RT rotation add anything anyway? The current BCP lists these two as either/or rather than defence in depth. 

— Neil

> On 2 Nov 2021, at 14:09, Pieter Kasselman <[email-masked]> wrote:
> 
> 
> Neil
>  
> [1]: https://mailarchive.ietf.org/arch/msg/oauth/WXwKxQM2poW7bqOOGGp4POYolFk/ 
>  
> Kind regards,
>  
> Neil

---

From: Aaron Parecki <[email-masked]>
Date: Tue, 2 Nov 2021 14:34:58 -0700

The grace period is not about the refresh token lifetime, it's specifically
about whether what would be a single-use refresh token can be used more
than one time within a short window of the first use.

Okta supports a configurable grace period per application that the customer
can set, anywhere from 0 to 60 seconds.

Personally I also agree with Neil that a grace period is not a good idea
from the security aspect, but I do also see that we have a lot of customers
who ask for this feature due to things like flaky mobile networks.

I like the suggested text from Neil. I assume this would go into the
Security BCP as well as OAuth 2.1?

Aaron

On Tue, Nov 2, 2021 at 7:09 AM Pieter Kasselman <pieter.kasselman=
[email-masked]> wrote:

> Neil
>
>
>
> Is the goal to accommodate network latency or clock drift? It would be
> helpful to include reasons for why a grace period should be considered if
> it is allowed.
>
>
>
> Without knowing the reasons for the grace period it is not clear why a
> grace period is a better solution than just extending the expiry time by a
> set time (60 seconds in your example) and having the client present the
> token a little earlier.
>
>
>
> If grace periods are allowed, it may be worth considering adding
> additional mitigations against replay. For example, a grace period may be
> allowed if the refresh token is sender constrained with DPoP so there is at
> least some assurances that the request is originating from the sender
> (especially if the nonce option is used with DPoP).
>
>
>
> I would worry about adding more complexity and less predictability by
> adding grace periods though (e.g. by looking at a refresh token, will you
> be able to tell if it can still be used or not), but your point that
> implementors may solve for it in other less predictable ways raises a valid
> point.
>
>
>
> Cheers
>
>
>
> Pieter
>
>
>
> *From:* OAuth <[email-masked]> *On Behalf Of *Neil Madden
> *Sent:* Tuesday 2 November 2021 10:29
> *To:* oauth <[email-masked]>
> *Subject:* [EXTERNAL] [OAUTH-WG] Rotating RTs and grace periods
>
>
>
> Hi all,
>
>
>
> There was a previous discussion on whether to allow a grace period during
> refresh token rotation, allowing the client to retry a refresh if the
> response fails to be received due to some transient network issue/timeout
> [1]. Vittorio mentioned that Auth0 already implement such a grace period.
> We (ForgeRock) currently do not, but we do periodically receive requests to
> support this. The current security BCP draft is silent on whether
> implementing such a grace period is a good idea, but I think we should add
> some guidance here one way or another.
>
>
>
> My own opinion is that a grace period is not a good idea, and if it is to
> be supported as an option then it should be kept as short as possible. The
> reason (as I mentioned in the previous thread) is that it is quite easy for
> an attacker to observe when a legitimate client performs a refresh flow and
> so can easily sneak in their own request afterwards within the grace
> period. There are several reasons why it is easy for an attacker to observe
> this:
>
>
>
> - RT rotation is primarily intended for public clients, such as mobile
> apps and SPAs. These clients are geographically distributed across the
> internet, and so there is a good chance that the attacker is able to
> observe the network traffic of at least some of these client instances.
>
> - The refresh flow is typically the only request that the client makes
> directly to the AS after initial authorization, so despite the traffic
> being encrypted it is very easy for an observer to determine that the
> client is performing a refresh whenever it makes any connection to the AS.
>
> - As well as observing the request itself, an attacker may be able to
> observe the DNS lookup for the AS hostname instead, which is even more
> likely to be observable and also in plaintext most of the time.
>
> - An attacker in a position to steal RTs from e.g. localStorage, is
> probably also in a good position to either observe when the legitimate
> client refreshes or to actually force it to refresh early (e.g., by
> deleting the corresponding AT from the same storage).
>
>
>
> I know some people argue that a grace period is a reasonable trade-off
> between security and usability. But I think that this kind of attack would
> be quite easy to carry out in practice for the reasons I suggest above, so
> I think the security actually degrades extremely quickly if you allow a
> grace period of any reasonable length.
>
>
>
> On the other hand, if we discourage this entirely then people may use
> dubious workarounds instead (e.g., one proposal I’ve seen was to use an ID
> token with the JWT Bearer grant, effectively turning the ID Token into an
> ad-hoc RT with much fewer protections).
>
>
>
> The AS MAY allow the original RT to be replayed for a short grace period
> to allow the client to recover if the response is not received due to a
> network problem or other transient issue. However, implementors should be
> aware that an attacker may be able to easily observe when the legitimate
> client makes a refresh request to the AS and so time their use of a stolen
> RT to occur within the grace period. Any grace period MUST be kept as short
> as possible, and MUST NOT exceed 60 seconds. Clients should prefer
> sender-constrained refresh tokens if recovery from network issues is a
> priority.
>
> —
>
>
>
> [1]:
> https://mailarchive.ietf.org/arch/msg/oauth/WXwKxQM2poW7bqOOGGp4POYolFk/
> <https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmailarchive.ietf.org%2Farch%2Fmsg%2Foauth%2FWXwKxQM2poW7bqOOGGp4POYolFk%2F&data=04%7C01%7Cpieter.kasselman%40microsoft.com%7Cbdb0969234774ba6f87608d99deba06c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637714457664531224%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=CDskCHwXxJxGdmudTW33gUT5f3%2B835uZDxyNEmKkiFc%3D&reserved=0>
>
>
>
>
> Kind regards,
>
>
>
> Neil
> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth
>

---

From: David Waite <[email-masked]>
Date: Tue, 2 Nov 2021 16:21:14 -0600

My perspective is that the rotation of refresh tokens is an AS mechanism to push for one-time-usage and break idempotency. This is specifically employed to reduce the impact in scenarios where the refresh token can be leaked and used by a third party attacker. A leaked refresh token can only be used in environments where the client credentials required for a refresh grant can also be leaked.

So,

1. Refresh token rotation is just one mechanism an AS could use to attempt to make reuse of leaked refresh tokens harder. Therefore it is entirely acceptable for an AS to have a policy around a grace period, as well as other policies - the goal is to try to make attacker’s jobs harder while letting through as many legitimate requests as possible

2. In scenarios where the client is expected to have non-exfiltratable credentials, the need for these sorts of protections goes down possibly to zero. Of course, this has a component of the AS trust of the client, e.g. to not be leveraging exportable keys.

-DW

> On Nov 2, 2021, at 3:20 PM, Neil Madden <[email-masked]> wrote:
> 
>> [1]: https://mailarchive.ietf.org/arch/msg/oauth/WXwKxQM2poW7bqOOGGp4POYolFk/ <https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmailarchive.ietf.org%2Farch%2Fmsg%2Foauth%2FWXwKxQM2poW7bqOOGGp4POYolFk%2F&data=04%7C01%7Cpieter.kasselman%40microsoft.com%7Cbdb0969234774ba6f87608d99deba06c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637714457664531224%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=CDskCHwXxJxGdmudTW33gUT5f3%2B835uZDxyNEmKkiFc%3D&reserved=0> 
>>  
>> Kind regards,
>>  
>> Neil
>>

---

From: Karsten Meyer zu Selhausen <[email-masked]>
Date: Thu, 4 Nov 2021 10:47:57 +0100

I share Neil's opinion about grace periods and agree that there is a 
need of guidance on this matter.

I like the proposed text and think it should be included in the security 
BCP, as well as, OAuth 2.1.

The old thread [1] slightly covered an interesting aspect:

> Aaron: if RT "R1" is used twice, resulting in new ATs "A1.1", "A1.2" and new RTs "R1.1" and "R1.2", what happens if "R1.2" is then later used? Would you invalidate "R1.1" at that point?
Vittorio pointed out that Auth0 would consider "RT1.1 and RT1.2 as 
equivalent".

@Aaron: Does Okta's implementation handle this the same way?

Should we include guidance for handling this aspect, as well?

Best regards,
Karsten

[1]: 

On 02.11.2021 22:34, Aaron Parecki wrote:
> The grace period is not about the refresh token lifetime, it's 
> specifically about whether what would be a single-use refresh token 
> can be used more than one time within a short window of the first use.
>
> Okta supports a configurable grace period per application that the 
> customer can set, anywhere from 0 to 60 seconds.
>
> Personally I also agree with Neil that a grace period is not a good 
> idea from the security aspect, but I do also see that we have a lot of 
> customers who ask for this feature due to things like flaky mobile 
> networks.
>
> On Tue, Nov 2, 2021 at 7:09 AM Pieter Kasselman 
> <pieter.kasselman=[email-masked]> wrote:
>
>     Neil
>
>     Is the goal to accommodate network latency or clock drift? It
>     would be helpful to include reasons for why a grace period should
>     be considered if it is allowed.
>
>     Without knowing the reasons for the grace period it is not clear
>     why a grace period is a better solution than just extending the
>     expiry time by a set time (60 seconds in your example) and having
>     the client present the token a little earlier.
>
>     additional mitigations against replay. For example, a grace period
>     may be allowed if the refresh token is sender constrained with
>     DPoP so there is at least some assurances that the request is
>     originating from the sender (especially if the nonce option is
>     used with DPoP).
>
>     I would worry about adding more complexity and less predictability
>     by adding grace periods though (e.g. by looking at a refresh
>     token, will you be able to tell if it can still be used or not),
>     but your point that implementors may solve for it in other less
>     predictable ways raises a valid point.
>
>     Cheers
>
>     Pieter
>
>     *From:*OAuth <[email-masked]> *On Behalf Of *Neil Madden
>     There was a previous discussion on whether to allow a grace period
>     during refresh token rotation, allowing the client to retry a
>     refresh if the response fails to be received due to some transient
>     network issue/timeout [1]. Vittorio mentioned that Auth0 already
>     implement such a grace period. We (ForgeRock) currently do not,
>     but we do periodically receive requests to support this. The
>     current security BCP draft is silent on whether implementing such
>     a grace period is a good idea, but I think we should add some
>     guidance here one way or another.
>
>     My own opinion is that a grace period is not a good idea, and if
>     it is to be supported as an option then it should be kept as short
>     as possible. The reason (as I mentioned in the previous thread) is
>     that it is quite easy for an attacker to observe when a legitimate
>     client performs a refresh flow and so can easily sneak in their
>     own request afterwards within the grace period. There are several
>     reasons why it is easy for an attacker to observe this:
>
>     - RT rotation is primarily intended for public clients, such as
>     mobile apps and SPAs. These clients are geographically distributed
>     across the internet, and so there is a good chance that the
>     attacker is able to observe the network traffic of at least some
>     of these client instances.
>
>     - The refresh flow is typically the only request that the client
>     makes directly to the AS after initial authorization, so despite
>     the traffic being encrypted it is very easy for an observer to
>     determine that the client is performing a refresh whenever it
>     makes any connection to the AS.
>
>     - As well as observing the request itself, an attacker may be able
>     to observe the DNS lookup for the AS hostname instead, which is
>     even more likely to be observable and also in plaintext most of
>     the time.
>
>     - An attacker in a position to steal RTs from e.g. localStorage,
>     is probably also in a good position to either observe when the
>     legitimate client refreshes or to actually force it to refresh
>     early (e.g., by deleting the corresponding AT from the same storage).
>
>     I know some people argue that a grace period is a reasonable
>     trade-off between security and usability. But I think that this
>     kind of attack would be quite easy to carry out in practice for
>     the reasons I suggest above, so I think the security actually
>     degrades extremely quickly if you allow a grace period of any
>     reasonable length.
>
>     On the other hand, if we discourage this entirely then people may
>     use dubious workarounds instead (e.g., one proposal I’ve seen was
>     to use an ID token with the JWT Bearer grant, effectively turning
>     the ID Token into an ad-hoc RT with much fewer protections).
>
>     The AS MAY allow the original RT to be replayed for a short grace
>     period to allow the client to recover if the response is not
>     received due to a network problem or other transient issue.
>     However, implementors should be aware that an attacker may be able
>     to easily observe when the legitimate client makes a refresh
>     request to the AS and so time their use of a stolen RT to occur
>     within the grace period. Any grace period MUST be kept as short as
>     possible, and MUST NOT exceed 60 seconds. Clients should prefer
>     sender-constrained refresh tokens if recovery from network issues
>     is a priority.
>
>     —
>

-- 
Karsten Meyer zu Selhausen
Senior IT Security Consultant
Phone:	+49 (0)234 / 54456499
Web:	https://hackmanit.de  | IT Security Consulting, Penetration Testing, Security Training

Is your OAuth or OpenID Connect application vulnerable to mix-up attacks? Find out more on our blog:
https://www.hackmanit.de/en/blog-en/132-how-to-protect-your-oauth-client-against-mix-up-attacks

Hackmanit GmbH
Universitätsstraße 60 (Exzenterhaus)
44789 Bochum

Registergericht: Amtsgericht Bochum, HRB 14896
Geschäftsführer: Prof. Dr. Jörg Schwenk, Prof. Dr. Juraj Somorovsky, Dr. Christian Mainka, Prof. Dr. Marcus Niemietz