Subject: [OAUTH-WG] [Technical Errata Reported] RFC7009 (6663)

From: RFC Errata System <[email-masked]>
Date: Sun, 22 Aug 2021 02:14:34 -0700 (PDT)

The following errata report has been submitted for RFC7009,
"OAuth 2.0 Token Revocation".

--------------------------------------
You may review the report below and at:
https://www.rfc-editor.org/errata/eid6663

--------------------------------------
Type: Technical
Reported by: Ashvin Narayanan <[email-masked]>

Section: 2.1

Original Text
-------------
The client constructs the request by including the following
   parameters using the "application/x-www-form-urlencoded" format in
   the HTTP request entity-body:

   token   REQUIRED.  The token that the client wants to get revoked.

   token_type_hint  OPTIONAL.  A hint about the type of the token
           submitted for revocation.  Clients MAY pass this parameter in
           order to help the authorization server to optimize the token
           lookup.  If the server is unable to locate the token using
           the given hint, it MUST extend its search across all of its
           supported token types.  An authorization server MAY ignore
           this parameter, particularly if it is able to detect the
           token type automatically.  This specification defines two
           such values:

           * access_token: An access token as defined in [RFC6749],
             Section 1.4

           * refresh_token: A refresh token as defined in [RFC6749],
             Section 1.5

           Specific implementations, profiles, and extensions of this
           specification MAY define other values for this parameter
           using the registry defined in Section 4.1.2.

   The client also includes its authentication credentials as described
   in Section 2.3. of [RFC6749].

   For example, a client may request the revocation of a refresh token
   with the following request:

     POST /revoke HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

     token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token

   The authorization server first validates the client credentials (in
   case of a confidential client) and then verifies whether the token
   was issued to the client making the revocation request.  If this
   validation fails, the request is refused and the client is informed
   of the error by the authorization server as described below.

Corrected Text
--------------
The client calls the revocation endpoint using an HTTP
   POST [RFC7231] request with the following parameters sent as
   "application/x-www-form-urlencoded" data in the request body:

   token   REQUIRED.  The token that the client wants to get revoked.

   token_type_hint  OPTIONAL.  A hint about the type of the token
           submitted for revocation.  Clients MAY pass this parameter in
           order to help the authorization server to optimize the token
           lookup.  If the server is unable to locate the token using
           the given hint, it MUST extend its search across all of its
           supported token types.  An authorization server MAY ignore
           this parameter, particularly if it is able to detect the
           token type automatically.  This specification defines two
           such values:

           * access_token: An access token as defined in [RFC6749],
             Section 1.4

           * refresh_token: A refresh token as defined in [RFC6749],
             Section 1.5

           Specific implementations, profiles, and extensions of this
           specification MAY define other values for this parameter
           using the registry defined in Section 4.1.2.

   The client MUST also include in the request, the access token it received 
   from the authorization server. It must do so in the same way as it  would  
   when accessing a protected resource, as describe in [RFC6749], Section 7.

   The following is a non-normative example request in which the client uses 
   its access token to revoke the associated refresh token:

     POST /revoke HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded
     Authorization: Bearer czZCaGRSa3F0MzpnWDFmQmF0M2JW

     token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token

   The following is a non-normative example request in which the client uses 
   its access token to revoke the same access token:

     POST /revoke HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded
     Authorization: Bearer czZCaGRSa3F0MzpnWDFmQmF0M2JW

     token=czZCaGRSa3F0MzpnWDFmQmF0M2JW&token_type_hint=access_token

   The authorization server MUST validate the access token used by the        
   client to authorize its call to the revocation endpoint, including 
   ensuring that it is not expired or revoked. 
   Additionally, the authorization server MUST also validate whether the
   access token used for authorization is part of the same grant  as the 
   token being revoked. If validation fails, the request is  refused and 
   the client is informed of the error by the authorization server. 
   In the case of a bearer token, the authorization server SHOULD respond  
   with an HTTP 401 code as described in OAuth 2.0 Bearer Token Usage 
   [RFC6750], Section 3. 
   Errors based on other types of tokens are beyond the scope of this 
   specification.

Notes
-----
It appears as though the authors of RFC7009 have failed to consider that requests to revoke are likely to come from non-confidential clients and such, would lack authentication credentials. Regardless of the type of client however, authentication should not be required. The OAuth 2.0 specification (RFC6749) does not specify verifying that the access token belongs to the client accessing protected resources, of which revocation is one. It is the role of the access token alone to signify authorization required to make requests to protected resources. If this is an issue for revocation, then it is an issue for all protected resources and counter measures may be proposed in a separate RFC rather than broadening the scope of this particular RFC. As per the original text itself, "This specification in general does not intend to provide countermeasures against token theft and abuse." Additionally, "If an attacker is able to successfully guess a public client's client_id and one of their tok
 ens, or a private client's credentials and one of their tokens, they could do much worse damage by using the token elsewhere than by revoking it.  If they chose to revoke the token, the legitimate client will lose its authorization grant and will need to prompt the user again.  No further damage is done and the guessed token is now worthless."
Note that the client_id is not meant to be private information to begin with, so relying on an attacker "guessing" it should not be seen as a security countermeasure. This section of RFC7009 will be referenced in a subsequent errata.

Instructions:
-------------
This erratum is currently posted as "Reported". If necessary, please
use "Reply All" to discuss whether it should be verified or
rejected. When a decision is reached, the verifying party  
can log in to change the status and edit the report, if necessary. 

--------------------------------------
RFC7009 (draft-ietf-oauth-revocation-11)
--------------------------------------
Title               : OAuth 2.0 Token Revocation
Publication Date    : August 2013
Author(s)           : T. Lodderstedt, Ed., S. Dronia, M. Scurtescu
Category            : PROPOSED STANDARD
Source              : Web Authorization Protocol
Area                : Security
Stream              : IETF
Verifying Party     : IESG

---

From: Justin Richer <[email-masked]>
Date: Mon, 23 Aug 2021 15:41:18 -0400

I personally don’t agree with this errata. Token Revocation was never meant to act as a protected resource, but rather as a function of the AS. The client is known to the AS and so authentication is expected here.

 — Justin

> On Aug 22, 2021, at 5:14 AM, RFC Errata System <[email-masked]> wrote:
> 
> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth

---

From: Emond Papegaaij <[email-masked]>
Date: Tue, 24 Aug 2021 09:43:23 +0200

On Mon, Aug 23, 2021 at 9:42 PM Justin Richer <[email-masked]> wrote:

> I personally don’t agree with this errata. Token Revocation was never
> meant to act as a protected resource, but rather as a function of the AS.
> The client is known to the AS and so authentication is expected here.
>

We ran into this very issue some time ago. Our client in this case was a
command line tool, which only requests the client credentials on login. It
then fetches an access token and stores this locally. The client
credentials are not stored by default. The current spec required us to
request the client credentials to revoke the access token on logout.
Personally, I see no point in requiring the the client to authenticate, it
already possesses an access token, which it can use for whatever it wants
to and the possession of the token should be enough evidence that the
client previously authenticated. Revoking the token seems to be the least
harmful one can do with a token.

For more information see:
https://mailarchive.ietf.org/arch/msg/oauth/7qxGcptE-uzA5WQaxnzGMdSqb2I/

Best regards,
Emond Papegaaij

> > It appears as though the authors of RFC7009 have failed to consider that
> requests to revoke are likely to come from non-confidential clients and
> such, would lack authentication credentials. Regardless of the type of
> client however, authentication should not be required. The OAuth 2.0
> specification (RFC6749) does not specify verifying that the access token
> belongs to the client accessing protected resources, of which revocation is
> one. It is the role of the access token alone to signify authorization
> required to make requests to protected resources. If this is an issue for
> revocation, then it is an issue for all protected resources and counter
> measures may be proposed in a separate RFC rather than broadening the scope
> of this particular RFC. As per the original text itself, "This
> specification in general does not intend to provide countermeasures against
> token theft and abuse." Additionally, "If an attacker is able to
> successfully guess a public client's client_id and one of their tok
> > ens, or a private client's credentials and one of their tokens, they
> could do much worse damage by using the token elsewhere than by revoking
> it.  If they chose to revoke the token, the legitimate client will lose its
> authorization grant and will need to prompt the user again.  No further
> damage is done and the guessed token is now worthless."
> > Note that the client_id is not meant to be private information to begin
> with, so relying on an attacker "guessing" it should not be seen as a
> security countermeasure. This section of RFC7009 will be referenced in a
> subsequent errata.
> >
> > Instructions:
> > -------------

---

From: Warren Parad <[email-masked]>
Date: Tue, 24 Aug 2021 12:14:17 +0200

I think it is worth pointing out, if we were to agree with the errata, that
this particular use case probably isn't relevant:

Our client in this case was a command line tool, which only requests the
> client credentials on login. It then fetches an access token and stores
> this locally. The client credentials are not stored by default.

Unless I misunderstand, I'll take "client credentials" to mean client Id
and client credentials via a client credentials grant. And therefore, is
not the correct flow to be used in a command line tool. Client credentials
are used in private when there are many user agents that could connect
through it, I would not recommend this as the solution here, and even if it
were, you would indeed have access to the client id and secret, so it would
not be a problem to use them to revoke the token.

However, I believe there is something fundamentally broke here, because
there are two use cases which are in conflict with each other:

   - I as a user, at any time want to revoke one of, access token, refresh
   token, or granted scopes associated with my identity by directly
   communicating with an AS. I never want to make this request through a
   client, and more specifically, I never want a client to determine whether
   or not I'm allowed to revoke these.
   - I as a user, at no time want to allow a client, for whom I did not
   give permission to revoke my refresh token nor revoke granted scopes. It
   should not be the case that one client sharing the token with another
   client (either intentionally or accidentally) would be allowed to change
   the requested scopes nor make decisions about the validity of my current
   access token or delegated refresh token.

Given the latter we see that it must be the case that refresh tokens,
access tokens, and associated grants MUST NOT be allowed to be revoked
without client authentication. This means that the original RFC is indeed
correct, and that the errata is not. But, this does not enable the former
case nor encourage a solution that works in scope of retaining control over
resources that the user agent owns. However, it is worth mentioning that it
doesn't prevent, as it still allows an AS to implement additional
mechanisms for direct user revocation, if desired.

That being said I would be in favor of enumerating a *flow* to safely
instruct the AS to revoke directly by the user, but it cannot be done by
amending the revocation endpoint.

Warren Parad

Founder, CTO
Secure your user data with IAM authorization as a service. Implement
Authress <https://authress.io/>.

On Tue, Aug 24, 2021 at 9:44 AM Emond Papegaaij <[email-masked]>
wrote:

>> > It appears as though the authors of RFC7009 have failed to consider
>> that requests to revoke are likely to come from non-confidential clients
>> and such, would lack authentication credentials. Regardless of the type of

---

From: Emond Papegaaij <[email-masked]>
Date: Tue, 24 Aug 2021 17:09:56 +0200

On Tue, Aug 24, 2021 at 12:14 PM Warren Parad <[email-masked]> wrote:

> I think it is worth pointing out, if we were to agree with the errata,
> that this particular use case probably isn't relevant:
>

The CLI-tool actually supports both a 3-legged (via the device
authorization grant) and a 2-legged flow (via the client credentials
grant). It depends on the use case which one is appropriate. In the case of
a user logging in to access the application via the CLI, it clearly is the
3-legged flow, however when the CLI is used in a script that runs without
user interaction, it's the 2-legged flow. In this later case, the script
often fetches the credentials from some store, uses them to acquire an
access token, does it job, and revokes the token. Naturally, it can fetch
the credentials a second time to revoke the token, but I really don't see
the point in this case. The client merely indicates it is done with the
token and it can now be revoked. It is good practice to discard any
credentials when you are done with them to minimize the chance of abuse.
However, requiring the client authentication to revoke the token, really
complicates this case and will probably lead to scripts not revoking the
token.

>    - I as a user, at any time want to revoke one of, access token,
>    refresh token, or granted scopes associated with my identity by directly

I don't fully understand your statement here. As far as I understand the
token revocation endpoint, it is an endpoint specifically for the client to
be used when it no longer needs the token. The client can simply discard
the tokens, but it is cleaner to inform the AS about this fact and allow
the AS to cleanup its resources as well. It is in no way an endpoint to be
used by the resource owner to revoke access for certain clients. I see it
like returning a key when you no longer need access to a building. The fact
that you hold the key should be enough for you to be able to return it.

I do want to point out that the spec for bearer tokens states: "A security
token with the property that any party in possession of the token (a
"bearer") can use the token in any way that any other party in possession
of it can." Clients should IMHO not be exchanging tokens with another party
unless they really trust this other party, in which case they should also
trust this party not to revoke the tokens when not agreed upon. If any
malicious party would get hold of my tokens, I wish they would only use
them to revoke them. A leaked token should be revoked anyway. One could
even argue that the grant for the original client should also be revoked in
this case as well, because it is clearly broken.

Best regards,
Emond Papegaaij

>>> > Note that the client_id is not meant to be private information to
>>> begin with, so relying on an attacker "guessing" it should not be seen as a

---

From: Dick Hardt <[email-masked]>
Date: Tue, 24 Aug 2021 08:47:26 -0700

Hey Emond

The access token represents the authorization to access the resource(s) --
it does not represent the authorization to manipulate tokens. The client
credentials are used for token management. While your implementation may be
ok with using the access token to revoke itself, it is not the security
model represented by the specification. Changing the spec would change the
security assumptions that existing deployments have made.

As noted in your response, the CLI has access to the client credentials to
revoke. Besides convenience, it is not clear to me why you would not want
to require the client credentials -- but it is your implementation -- you
can make your own decisions where and if you want to be compliant.

Warren: an interesting idea to provide more context on this in OAuth 2.1.

/Dick
ᐧ

On Tue, Aug 24, 2021 at 8:10 AM Emond Papegaaij <[email-masked]>
wrote:

>> On Tue, Aug 24, 2021 at 9:44 AM Emond Papegaaij <
>> [email-masked]> wrote:
>>