Subject: Re: [OAUTH-WG] Review of Token Revocation draft

From: Justin Richer <[email-masked]>
Date: Mon, 3 Dec 2012 10:29:17 -0500

An early draft of the revocation spec had this token type field, for 
this purpose. From an early conversation on the list with Torsten, we 
decided that most of the time it didn't matter, as different classes of 
token would be recognizable as different by the AS. In some 
implementations (like ours), this means checking different token stores 
in parallel for a given token value. In other implementations, they can 
key on something in the token to make the search more simple.

But one of the reasons behind not having a "token type" parameter any 
more is that OAuth core defines two token classes: access and refresh. 
OpenID Connect adds another type, the id token. UMA adds a whole range 
of other types, from host access tokens and onward. Even dynamic 
registration adds a new class, the registration access token. So the 
problem is how do we manage all of these classes? Right now, the answer 
is "punt" by not having the field and putting the weight on the AS. But 
maybe we can revisit this decision with a bit more deployment experience.

The way I see it, we've got a few options:

1) Leave it as-is, with no field. Client/RS/whoever just sends the token 
over and it's the AS's problem.
2) Define a required field with "access" and "refresh" value semantics, 
and state that other values MAY be accepted by a given AS, or defined by 
extension protocols. These extension values MUST be fully qualified URIs.
3) Same as #2, but with IANA registry to allow for non-collision of 
short names.
4) Define an optional field that the client MAY send as a hint to the 
AS, and it's up to the AS to figure out if it makes any sense in the 
context of the request. All bets are off as to the content of this 
field, other than "it's a string".

There may be other approaches as well.

  -- Justin

On 11/30/2012 04:28 PM, Anganes, Amanda L wrote:
> Here is my review of the Toke Revocation draft 
> (http://datatracker.ietf.org/doc/draft-ietf-oauth-revocation/):
>
> Section 1. Introduction
> First paragraph has the following definition in it: "A token is the 
> external representation of an access grant issued by a resource owner 
> to a particular client." This seems a bit odd to me. The OAuth2 spec 
> [1] defines "access token" as "An access token is a string 
> representing an authorization issued to the client." (section 1.4) and 
> "refresh token" as "credentials used to obtain access tokens (section 
> 1.5). Should this spec borrow similar language to be more consistent?
>
> Paragraph 2 "From an end-user's perception" should be "From an 
> end-user's perspective".
>
> Section 2. Token Revocation
> What is the reason for requiring the service provider to detect the 
> token type automatically? For our implementation, Access Tokens, 
> Refresh Tokens, and ID Tokens are all structured tokens (with unique 
> structures across the three types), and as such are stored in 3 
> separate database tables. In order to "detect" the token type, we 
> would need to run a get-by-value query across all three tables, check 
> if any of those queries returned anything, and then proceed to revoke 
> the token (if one was found). This does not seem ideal to me.
>
> The spec says that "The authorization server first validates the 
> client credentials (in case of a confidential client) and verifies 
> whether the client is authorized to revoke the particular token." What 
> does this verification entail? Does it just mean that 1) the client 
> credentials must validate and 2) the token must belong to the client 
> requesting the revocation? If so I think the text should be clarified 
> to reflect that. Or are you thinking of a case where a client might 
> not be allowed to revoke its own tokens, via some kind of scoping?
>
> 2.1 Cross Origin Support
> Formatting looks a little off here, otherwise this section looks fine.
>
> 5. Security Considerations
> Paragraph 3 (Malicious clients...): "Appropriate countermeasures, 
> which should be in place for the token endpoint as well, MUST be 
> applied to the revocation endpoint." These countermeasures should be 
> referenced to the proper section(s) of the OAuth core spec or Threat 
> Model document.
>
> Paragraph 4 reads a bit oddly. Suggest following rewording:
> "A malicious client may attempt to guess valid tokens on this endpoint 
> by making revocation requests against potential token strings. 
> According to this specification, a client's request must contain a 
> valid client_id, in the case of a public client, or valid client 
> credentials, in the case of a confidential client. The token being 
> revoked must also belong to the requesting client. If an attacker is 
> able to successfully guess a public client's client_id and one of 
> their tokens, 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 and will need to prompt the user 
> again. No further damage is done and the guessed token is now worthless."
>
> References:
> [1] http://tools.ietf.org/html/draft-ietf-oauth-v2-31
>
> -- 
> Amanda Anganes
> Info Sys Engineer, G061
> The MITRE Corporation
> 781-271-3103
> [email-masked]
>
>
> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth

---

From: Torsten Lodderstedt <[email-masked]>
Date: Tue, 25 Dec 2012 13:41:28 +0100

Hi all,

any other opinion regarding having or not having a token type parameter?

I would like to go with #1 as it is rather late in the process to 
(re-)introduce a mandatory parameter. And making it an optional 
parameter (#4) seems not really useful to me.

regards,
Torsten.
> 1) Leave it as-is, with no field. Client/RS/whoever just sends the 
> token over and it's the AS's problem.
> 2) Define a required field with "access" and "refresh" value 
> semantics, and state that other values MAY be accepted by a given AS, 
> or defined by extension protocols. These extension values MUST be 
> fully qualified URIs.
>> representing an authorization issued to the client." (section 1.4) 
>> and "refresh token" as "credentials used to obtain access tokens 
>> (section 1.5). Should this spec borrow similar language to be more 
>> consistent?
>>
>> whether the client is authorized to revoke the particular token." 
>> What does this verification entail? Does it just mean that 1) the 
>> client credentials must validate and 2) the token must belong to the 
>> client requesting the revocation? If so I think the text should be 
>> clarified to reflect that. Or are you thinking of a case where a 
>> client might not be allowed to revoke its own tokens, via some kind 
>> of scoping?
>>
>> 2.1 Cross Origin Support
>> "A malicious client may attempt to guess valid tokens on this 
>> endpoint by making revocation requests against potential token 
>> strings. According to this specification, a client's request must 
>> contain a valid client_id, in the case of a public client, or valid 
>> client credentials, in the case of a confidential client. The token 
>> being revoked must also belong to the requesting client. If an 
>> attacker is able to successfully guess a public client's client_id 
>> and one of their tokens, 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 and will need to prompt 
>> the user again. No further damage is done and the guessed token is 
>> now worthless."
>>
>> References:

---

From: John Bradley <[email-masked]>
Date: Wed, 26 Dec 2012 11:17:51 -0300

I agree that #1 is currently the best option.    Tokens are supposed to be opaque to the client in principal.  The AS is in the best position to sort it out of required.   Nothing stops the token from being structured if it is an issue for the AS.

John B.

On 2012-12-25, at 9:41 AM, Torsten Lodderstedt <[email-masked]> wrote:

> I would like to go with #1 as it is rather late in the process to (re-)introduce a mandatory parameter. And making it an optional parameter (#4) seems not really useful to me.
> 
> regards,
> Torsten.
>> 1) Leave it as-is, with no field. Client/RS/whoever just sends the token over and it's the AS's problem.
>> 2) Define a required field with "access" and "refresh" value semantics, and state that other values MAY be accepted by a given AS, or defined by extension protocols. These extension values MUST be fully qualified URIs.
>> 3) Same as #2, but with IANA registry to allow for non-collision of short names.
>> 4) Define an optional field that the client MAY send as a hint to the AS, and it's up to the AS to figure out if it makes any sense in the context of the request. All bets are off as to the content of this field, other than "it's a string".
>> 
>>> Here is my review of the Toke Revocation draft (http://datatracker.ietf.org/doc/draft-ietf-oauth-revocation/):
>>> 
>>> Section 1. Introduction
>>> First paragraph has the following definition in it: "A token is the external representation of an access grant issued by a resource owner to a particular client." This seems a bit odd to me. The OAuth2 spec [1] defines "access token" as "An access token is a string
>>>                 representing an authorization issued to the client." (section 1.4) and "refresh
>>>                 token" as "credentials used to obtain access tokens
>>>                 (section 1.5). Should this spec borrow similar language
>>>                 to be more consistent?
>>> 
>>> 
>>>               
>>> Paragraph 2 "From an end-user's
>>>                 perception" should be "From an end-user's perspective".
>>> 
>>> 
>>>               
>>> What is the reason for requiring the
>>>                 service provider to detect the token type automatically?
>>>                 For our implementation, Access Tokens, Refresh Tokens,
>>>                 and ID Tokens are all structured tokens (with unique
>>>                 structures across the three types), and as such are
>>>                 stored in 3 separate database tables. In order to
>>>                 "detect" the token type, we would need to run a
>>>                 get-by-value query across all three tables, check if any
>>>                 of those queries returned anything, and then proceed to
>>>                 revoke the token (if one was found). This does not seem
>>>                 ideal to me. 
>>> 
>>> 
>>>               
>>> The spec says that "The authorization server first
>>>                 validates the client credentials (in case of a
>>>                 confidential client) and verifies whether the client is
>>>                 authorized to revoke the particular token." What does
>>>                 this verification entail? Does it just mean that 1) the
>>>                 client credentials must validate and 2) the token must
>>>                 belong to the client requesting the revocation? If so I
>>>                 think the text should be clarified to reflect that. Or
>>>                 are you thinking of a case where a client might not be
>>>                 allowed to revoke its own tokens, via some kind of
>>>                 scoping? 
>>> 
>>> 
>>>               
>>> 2.1 Cross Origin Support
>>> Paragraph 3 (Malicious clients…): "Appropriate countermeasures, which should be in place for the token endpoint as well, MUST be applied to the revocation endpoint." These countermeasures should be referenced to the proper section(s) of the OAuth core spec or Threat Model document. 
>>> 
>>> "A malicious client may attempt to guess valid tokens on this endpoint by making revocation requests against potential token strings. According to this specification, a client's request must contain a valid client_id, in the case of a public client, or valid client credentials, in the case of a confidential client. The token being revoked must also belong to the requesting client. If an attacker is able to successfully guess a public client's client_id and one of their tokens, 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 and will need to prompt the user again. No further damage is done and the guessed token is now worthless." 
>>> 
>>> References:

---

From: Sergey Beryozkin <[email-masked]>
Date: Thu, 27 Dec 2012 09:57:48 +0000

sHi
> parameter (#4) seems not really useful to me.
ce
+1 to #4 - it might help optimizing the lookups. Example, refresh and 
access token keys may be kept in different tables, so ideally revoking a 
refresh token only would involve a definite lookup to the refresh token 
table/etc only, same for access tokens.

Having said this, the optional parameter can probably be added later.

However, it made me think, should the client be able to say, "I'd like 
to revoke this refresh token and the access token linked to this refresh 
token", in other words, should the client be given an option to optimize 
the revocation process ? Probably can be reviewed later too

thanks, Sergey

>>> Paragraph 3 (Malicious clients…): "Appropriate countermeasures, which
>>> should be in place for the token endpoint as well, MUST be applied to
>>> the revocation endpoint." These countermeasures should be referenced
>>> to the proper section(s) of the OAuth core spec or Threat Model
>>> document.
>>>

---

From: Torsten Lodderstedt <[email-masked]>
Date: Thu, 27 Dec 2012 19:22:32 +0100

Am 27.12.2012 10:57, schrieb Sergey Beryozkin:
> access token keys may be kept in different tables, so ideally revoking 
> a refresh token only would involve a definite lookup to the refresh 
> token table/etc only, same for access tokens.
>
> to revoke this refresh token and the access token linked to this 
> refresh token", in other words, should the client be given an option 
> to optimize the revocation process ? Probably can be reviewed later too

Hi Sergey,

ok, got you. Thanks for the proposal. I agree with your assessment that 
this can be added later. In my opinion, we generally need more 
real-world implementation experience in order to optimize the protocol. 
For the time being, I would like to have basic revocation support.

regards,
Torsten.

---

From: Sergey Beryozkin <[email-masked]>
Date: Fri, 28 Dec 2012 15:56:12 +0000

Hi Torsten
> For the time being, I would like to have basic revocation support.

+1 again :-)

Thanks, Sergey