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

Ash Narayanan <ashvinnarayanan@gmail.com> Tue, 31 August 2021 00:42 UTC

Return-Path: <ashvinnarayanan@gmail.com>
X-Original-To: oauth@ietfa.amsl.com
Delivered-To: oauth@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 8AF843A2917 for <oauth@ietfa.amsl.com>; Mon, 30 Aug 2021 17:42:32 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.097
X-Spam-Level:
X-Spam-Status: No, score=-2.097 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 52F81Cmx_9a8 for <oauth@ietfa.amsl.com>; Mon, 30 Aug 2021 17:42:26 -0700 (PDT)
Received: from mail-ot1-x335.google.com (mail-ot1-x335.google.com [IPv6:2607:f8b0:4864:20::335]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id D5E013A2913 for <oauth@ietf.org>; Mon, 30 Aug 2021 17:42:25 -0700 (PDT)
Received: by mail-ot1-x335.google.com with SMTP id c42-20020a05683034aa00b0051f4b99c40cso10459570otu.0 for <oauth@ietf.org>; Mon, 30 Aug 2021 17:42:25 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to:cc; bh=qZ4cAcfr0izUZDqxP5BmK9+g60Y9mPI/ZflgneQEWVk=; b=b/mbWNcoMOB64zhw4kCMruO21y1sYTpUN9kwnz2SI7NedOF/FjQDcz/3lC8POSavTQ Mn9wO6S7797ETM7Jyh+kjRhwS41n0oAWt2TnKVEcqlco5L5N5M+BPuG1yTi1CMfDdWdt XQzUtms7An0dq+fnssAePwpCs4yP+y+u79+3rDlPtwLTDjRVFUkCk6Mr7hPbbmf0GEMl RXdwyG3P+YN01XizWKXTnLQAsb5G//5DOOJ8AZBncDveMxiaEmgAapoIDONQG/nHoUEI 6xiZ/iPzCoh8uk4ZBX9XgPp7chxlV30IIzJ9uhnUUG07l9lR/nAmZ1bZO5/qGH91IAva iXjQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=qZ4cAcfr0izUZDqxP5BmK9+g60Y9mPI/ZflgneQEWVk=; b=teyibSrtFhULSd1L7b4iALld9fOuL75Bhp7GKzMLjncCR/54W4NTvcUF88Gj46OI2H eT7XV4E1uxXCgFDA2rmUpxdZvNulfalFnKILoUgKKahzkYMe6nq8eOHZe6rwin5/kFYI M2+Mhc1oD2PppJY76UX9zbWdPfOnmp22asIc9+wpRqunXLtNV8AkLRCkrZoTMaVDG6m+ ZQVHgp4cpLYB0vSGMRS/c+e/QXhuPa32EkzzmU44C7qA4CgygE7uuzOfsEEAghipvyMM CqPU8AvyTjgc/5ygb8rnksKDAJA7pbA5kS+YZSplyCKvHfyUmzTveOWm6YGnOkcgH0dp 5TLg==
X-Gm-Message-State: AOAM533cUIKo+QefkVjEaiiF520bd6rXSPKw3yy0pMDntrtWUERNbIhq cuchXbxtkVn1Ndca+wirReFZ3U1siuFptlqdKUY=
X-Google-Smtp-Source: ABdhPJy2X57WNtQ26LoETXEmYP3oUouYUxtWkXx/wsPhN7YLpqDDPfukW7j1P8NMDsQXzIGXXASTR7968LrVqBZJdMA=
X-Received: by 2002:a9d:7396:: with SMTP id j22mr22889428otk.206.1630370543652; Mon, 30 Aug 2021 17:42:23 -0700 (PDT)
MIME-Version: 1.0
From: Ash Narayanan <ashvinnarayanan@gmail.com>
Date: Tue, 31 Aug 2021 10:42:12 +1000
Message-ID: <CAFvbn=aD4y9SgzigPbQK6EuPgt+YYT6rBkHfQvXDk_4jRhA_iQ@mail.gmail.com>
To: dick.hardt@gmail.com
Cc: IETF oauth WG <oauth@ietf.org>
Content-Type: multipart/alternative; boundary="0000000000001b51ad05cad0398f"
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/JGc8MKMkhJG3aVzSAJwk3HKwBPo>
Subject: Re: [OAUTH-WG] [Technical Errata Reported] RFC7009 (6663)
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/oauth/>
List-Post: <mailto:oauth@ietf.org>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 31 Aug 2021 00:42:33 -0000

Hi Dick,

>The access token represents the authorization to access the resource(s) --
>it does not represent the authorization to manipulate tokens.

Anything for which the client must have an access token to access is a
protected resource. In order to revoke a token, the client must have the
associated access token to begin with, hence a protected resource. If not a
protected resource, it is implied anyone can access it, and the OAuth spec
makes no assertions about where a protected resource must be located so
there's no reason it can't be on the AS as well.

Emond describes it quite neatly:
>> 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.

So you shouldn't be returning a key you never had.

Anything for which you *may* use a client_secret if you have one or not if
you don't is generally a red flag. In RFC 7009 as I've pointed out, the
client_id is being used as a security measure as it's part of the
authentication header. Furthermore, it also mentions an attacker *guessing*
it (in addition to the token). The client_id is by no means a secure item
on a non-confidential client such as an SPA.

Also you say:
> Changing the spec would change the security assumptions that existing
deployments have made.

Isn't that the nature of the business? Or are you implying that no
deployment should ever change even if improvements are found?

Ash


>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 <emond.papegaaij@gmail.com>
>wrote:
>
>> On Tue, Aug 24, 2021 at 12:14 PM Warren Parad <wparad@rhosys.ch> 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:
>>>
>>> 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.
>>>
>>
>> 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.
>>
>>
>>> 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.
>>>
>>
>> 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
>>
>>
>>
>>> On Tue, Aug 24, 2021 at 9:44 AM Emond Papegaaij <
>>> emond.papegaaij@gmail.com> wrote:
>>>
>>>> On Mon, Aug 23, 2021 at 9:42 PM Justin Richer <jricher@mit.edu> 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
>>>>
>>>>
>>>>
>>>>> > On Aug 22, 2021, at 5:14 AM, RFC Errata System <
>>>>> rfc-editor@rfc-editor.org> wrote:
>>>>> >
>>>>> > 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 <ashvinnarayanan@gmail.com>
>>>>> >
>>>>> > 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
>>>>> >
>>>>> > _______________________________________________
>>>>> > OAuth mailing list
>>>>> > OAuth@ietf.org
>>>>> > https://www.ietf.org/mailman/listinfo/oauth
>>>>>
>>>>> _______________________________________________
>>>>> OAuth mailing list
>>>>> OAuth@ietf.org
>>>>> https://www.ietf.org/mailman/listinfo/oauth
>>>>>
>>>> _______________________________________________
>>>> OAuth mailing list
>>>> OAuth@ietf.org
>>>> https://www.ietf.org/mailman/listinfo/oauth
>>>>
>>> _______________________________________________
>> OAuth mailing list
>> OAuth@ietf.org
>> https://www.ietf.org/mailman/listinfo/oauth
>>