Re: [Ace] AD review of draft-ietf-ace-oauth-authz-24

Ludwig Seitz <> Wed, 20 November 2019 06:44 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id D68D8120125; Tue, 19 Nov 2019 22:44:41 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.901
X-Spam-Status: No, score=-1.901 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (1024-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id Wg9fIoombNhI; Tue, 19 Nov 2019 22:44:38 -0800 (PST)
Received: from ( []) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 9107412004C; Tue, 19 Nov 2019 22:44:37 -0800 (PST)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901;; cv=none; b=cAC5Qk1dSfQWINjrbrNpnh5LrHUn75Gq+LKdl1rZ9ryGZLyfyCufWCCj+3Y3l1b7Wqsl8AmPtgUFjIVZR/8CJR+OVDQO5odi9/MLipEmEpbKsuz/5+7rUjxW+3eSCk7rhfN7O35Z33cxkzimyZCgqnU3eqwYm2OeGhjRw5T6PdHMyhXWHyMXQwqA3oTLtgDVebpepidOtHPzPY2Ade3fNYvR753k4zaDbdXzsQC1YbA8m0IAKkzPr4BpGWseF5bGYdyAPcq0eHqW3CYri32gDWMOPPMzsN2NWf8GBqOz7Qg0YdQe9i0E4HKxTiyTAqwV0MCwHNCDv5bKkMiUOtvLSA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=hAuk4TjGKK0gC+65cfP9uXYYZO0Eq6CbpWOyCLh3gb0=; b=Y3ZOjO3xNv3ugwP1biHXvXL8gz+4IAVsAx9qIHyeZhjEKjNPHeV8P04Fj745uk7wVAPrVKrFaEspvvuow9HLv+HxKSQQi1nr0qS9V2yXnOKvX6OmPDrYbtWfz7BE2dtxRoc9/aVeMAoBlaAct42TzD1+JZx6Cr51Ud/e2NorcDOEBE9fbBN048oxFRgq0RW+m+R+rdFSrjHnKk+sVnpfNEIcJlGrVzPN0zRaCA0S5c7Nx7uLCjal0Lc3KUQjxYdj599OpxSkQTcd2r8iNyx0lk1u8DimEBXLGNaDxNQ750TAAHraZLj6jKoZrdDKL4j9ujOXq5e0HEM6j/eEH7iJXw==
ARC-Authentication-Results: i=1; 1; spf=pass (sender ip is; dmarc=pass (p=none sp=none pct=100) action=none; dkim=none (message not signed); arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=selector1-RISEcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=hAuk4TjGKK0gC+65cfP9uXYYZO0Eq6CbpWOyCLh3gb0=; b=nyXjkqArQ9pRIvacwaGmxkdV6ouqygZ4AdGVEQXTConm4y8+QVUCNEoz7R0Ga/HqBZ3/jY1dV3KUsjKpLRRekcKg+eM0ce9L+xdexCZLejcxciMmWd14VELAWaguzgh3LK6IHYG5tiD/gqx06GS9p9i6Y14B/FFDZltR88T3vDc=
Received: from HE1P189CA0031.EURP189.PROD.OUTLOOK.COM (2603:10a6:7:53::44) by DB6P18901MB0071.EURP189.PROD.OUTLOOK.COM (2603:10a6:4:26::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2451.23; Wed, 20 Nov 2019 06:44:34 +0000
Received: from (2a01:111:f400:7e06::200) by (2603:10a6:7:53::44) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2474.16 via Frontend Transport; Wed, 20 Nov 2019 06:44:34 +0000
Authentication-Results: spf=pass (sender IP is;; dkim=none (message not signed) header.d=none;; dmarc=pass action=none;
Received-SPF: Pass ( domain of designates as permitted sender); client-ip=;;
Received: from ( by ( with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2474.17 via Frontend Transport; Wed, 20 Nov 2019 06:44:34 +0000
Received: from [] ( by ( with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 20 Nov 2019 07:44:31 +0100
To: Benjamin Kaduk <>
CC: <>, <>
References: <> <> <> <> <>
From: Ludwig Seitz <>
Message-ID: <>
Date: Wed, 20 Nov 2019 07:44:03 +0100
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0
MIME-Version: 1.0
In-Reply-To: <>
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="------------ms050208010005070001060909"
X-Originating-IP: []
X-ClientProxiedBy: ( To (
X-EOPAttributedMessage: 0
X-Forefront-Antispam-Report: CIP:; IPV:NLI; CTRY:SE; EFV:NLI; SFV:NSPM; SFS:(10009020)(4636009)(136003)(376002)(346002)(39860400002)(396003)(199004)(189003)(22746008)(76176011)(53546011)(6116002)(3846002)(30864003)(65956001)(229853002)(2906002)(65806001)(70206006)(106002)(316002)(54906003)(16576012)(40036005)(58126008)(16586007)(22756006)(2171002)(31696002)(86362001)(5660300002)(235185007)(568964002)(31686004)(6246003)(336012)(44832011)(14444005)(5024004)(476003)(33964004)(70586007)(2616005)(6706004)(126002)(6916009)(486006)(956004)(11346002)(71190400001)(186003)(81156014)(81166006)(7736002)(8936002)(6666004)(26005)(305945005)(356004)(8676002)(16526019)(386003)(4326008)(36756003)(446003)(478600001); DIR:OUT; SFP:1101; SCL:1; SRVR:DB6P18901MB0071;; FPR:; SPF:Pass; LANG:en; PTR:InfoDomainNonexistent; A:1; MX:1;
X-MS-PublicTrafficType: Email
X-MS-Office365-Filtering-Correlation-Id: 89757317-a702-4468-e835-08d76d851ad6
X-MS-TrafficTypeDiagnostic: DB6P18901MB0071:
X-Microsoft-Antispam-PRVS: <DB6P18901MB0071ADF78892DC8C4CFE3D6C824F0@DB6P18901MB0071.EURP189.PROD.OUTLOOK.COM>
X-MS-Oob-TLC-OOBClassifiers: OLM:10000;
X-Forefront-PRVS: 02272225C5
X-MS-Exchange-SenderADCheck: 1
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: 70kH2rT7Add8qVpuiEZKEPd9pKNyDErv9yMTtcQvdSxq5NYnxij32bPiyxlzpxKR/nO2ZfljbtEkVLhKNhtoFGK+wA/AmB2mQtd9fF86r+fLfv1U1zFJ+RQ56vpb8Wh79dJh5o3j0jutfvBL7oixCdM/uz9NQd2xnsjqk9ySy2fYkkz6XEg44TNoR1FIJ+dHyyo6o7OCEkeSVvsocihtfNryu2vYv5gJ7XUnoexmQe6uWKOJHa3jFDOdEuQZy+91lp4p52ioDT/Ke8USkNsBAMp3uVpitaoL1LdqVtoQU5fE+/HelhzN8PnOhkLueThC/1TtvWXbQVEl3Up1fdGM06ZyxBvQec4OxXpbnAQJQGDqVfqVjjYLbH5qU3TmWHtKkB0kJeDIE+rqb6sO3SD12sOllIf1VAOR9beK+HLDbnfYyqxcPGhiT3cYOMkJUmKb
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Nov 2019 06:44:34.3743 (UTC)
X-MS-Exchange-CrossTenant-Network-Message-Id: 89757317-a702-4468-e835-08d76d851ad6
X-MS-Exchange-CrossTenant-Id: 5a9809cf-0bcb-413a-838a-09ecc40cc9e8
X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5a9809cf-0bcb-413a-838a-09ecc40cc9e8; Ip=[]; Helo=[]
X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6P18901MB0071
Archived-At: <>
Subject: Re: [Ace] AD review of draft-ietf-ace-oauth-authz-24
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "Authentication and Authorization for Constrained Environments \(ace\)" <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Wed, 20 Nov 2019 06:44:42 -0000

Hello ACE,

I've had a side-meeting with Ben at IETF 106 and we clarified the 
outstanding issues as follows. I have submitted -26 implementing the 
resolutions resulting from these clarifications. See below for detailed 


On 17/11/2019 07:25, Benjamin Kaduk wrote:
> On Wed, Nov 13, 2019 at 01:55:44PM +0100, Ludwig Seitz wrote:
>> On 10/11/2019 04:28, Benjamin Kaduk wrote:

>>>>> 16.)
>>>>> Section 3.2
>>>>>      One application of COSE is OSCORE [I-D.ietf-core-object-security],
>>>>>      which provides end-to-end confidentiality, integrity and replay
>>>>>      protection, and a secure binding between CoAP request and response
>>>>>      messages.  In OSCORE, the CoAP messages are wrapped in COSE objects
>>>>>      and sent using CoAP.
>>>>>      This framework RECOMMENDS the use of CoAP as replacement for HTTP for
>>>>>      use in constrained environments.
>>>>> Do we have a reason to mention OSCORE if we're not going to make a
>>>>> recommendation about its use?
>>>> [LS] We also mention DTLS and TLS without making any recommendation about
>>>> which to use. I would suggest to either remove all of it or to add a
>>>> sentence
>>>> noting that this is an enumeration of some security options, and the choice
>>>> depends on the specific application scenario.
>>> Adding a sentence feels like a slightly better option to me, though it
>>> could easily go either way.
>> Fixed

Note: I thought I had fixed this in -25, but it turned out to only be in 
my head. It's now also fixed in the document (i.e. -26).

>>>>> 39.)
>>>>>      Refresh tokens are typically not stored as securely as proof-of-
>>>>>      possession keys in requesting clients.  Proof-of-possession based
>>>>>      refresh token requests MUST NOT request different proof-of-possession
>>>>>      keys or different audiences in token requests.  Refresh token
>>>>>      requests can only use to request access tokens bound to the same
>>>>>      proof-of-possession key and the same audience as access tokens issued
>>>>>      in the initial token request.
>>>>> This is perhaps something of a philosophical question, but if a refresh
>>>>> token is only usable at the token endpoint, in some sense its audience
>>>>> is definitionally the AS.  So there's a little bit of a mismatch in
>>>>> treating it as having the audience value that the access tokens issued
>>>>> from it will have.  I don't know the background for audience-restriced
>>>>> refresh tokens in regular OAuth 2.0, though, so hopefully someone can
>>>>> educate me.
>>>> [LS] I'm equally confused. I suggest that Hannes or one of the other OAuth
>>>> experts give us a hint on that one.
>>> [We had some stab at this in the other thread, but additional input might
>>> still be in order]
>> Let's hear with OAuth people in Singapore.

We discussed that now, the text refers to the audience of the access 
token, not the refresh token which is just an opaque reference. -> No 
textual change.

>>>>> 58.)
>>>>>      Profiles MUST specify whether the authz-info endpoint is protected,
>>>>>      including whether error responses from this endpoint are protected.
>>>>>      Note that since the token contains information that allow the client
>>>>>      and the RS to establish a security context in the first place, mutual
>>>>>      authentication may not be possible at this point.
>>>>> We'll need some careful reasoning about this for the security
>>>>> considerations, since the authz-info transaction can impact what profile
>>>>> the RS thinks is in use.  E.g., whether a network attacker could
>>>>> cause the client to think that a different (vulnerable) profile is in
>>>>> use than the one the RS expects to use.
>>>> [LS] Noted. Do you think the reasoning in section 6.5 needs to be extended?
>>> I think we should add some more text, yes.
>>> Specifically, we should mention that the authz-info interaction can affect
>>> what profile RS will use (e.g., via "ace_profile"), and that profile
>>> developers should be conscious of the risk of downgrade attacks that
>>> involve other profile types.  (Am I reading this right that the client will
>>> know what profile to use by the time it is ready to post to the authz-info
>>> endpoint and that the response will not change what profile the client
>>> uses?  Specifically, even if a client supports multiple profiles that use
>>> different methods for token transport, a client is not going to try one
>>> method/profile and then fall back to a different one if the first one
>>> (transiently) fails?)
>> I'm not sure how you would mount such a downgrade attack. The client
>> receives the profile to use either by implicit configuration or
>> explicitly through the "profile" parameter from the AS.
>> If the client does not receive a "profile" parameter and has no implicit
>> profile configured this is an error.
>> The RS either has the profile pre-configured or receives it via an
>> authenticated "profile" claim in the access token (again if the claim is
>> missing and no pre-configured profile exists this is an error). Even
>> though the token is sent to authz-info over an insecure channel and the
>> client is not yet authenticated, the access token itself is, and
>> therefore I find it hard to see how an attacker would trick the RS to
>> use a different profile.
> The general idea I have in mind is that the attacker can send a different
> token to authz-info than would be used in normal operation.  Maybe it's an
> old one, or supposed to be for a different client, or something else, but
> the risk is that the attacker confuses the RS about what token (and thus
> which profile) to use with a given client.  I think we have enough
> flexibility in how these things are done that the core framework does not
> provide a solid guarantee that such a mixup can never happen.

I've added some clarifying text in section 6.8 providing a description 
of the attack and what the RO can do to mitigate it.

>>>>> 65.)
>>>>>         specification defines the following approach: The claim "exi"
>>>>>         ("expires in") can be used, to provide the RS with the lifetime of
>>>>>         the token in seconds from the time the RS first receives the
>>>>>         token.  This approach is of course vulnerable to malicious clients
>>>>>         holding back tokens they do not want to expire.  Such an attack
>>>>> It also has suboptimal behavior if the RS loses state (e.g., by
>>>>> rebooting), and possibly requires the RS to store indefinitely all
>>>>> tokens with an "exi" value.  I have mixed feelings about specifying it
>>>>> at all, though I concede it probably does have some value.  Regardless,
>>>>> I think a dedicated subsection in the security considerations is in
>>>>> order.
>>>> [LS] We wanted to provide some solution for expiring tokens for RSes
>>>> that have
>>>> no connectivity and no synchronized clocks. Using the "exp" claim in
>>>> such cases
>>>> would have pretty unpredictable results.
>>>> I have extended section 6.3 in the security considerations to go into
>>>> the detail
>>>> of "exi", please have a look if this covers the necessary issues.
>>> I think we should also say something about the amount of such persistent
>>> storage potentially growing without bound, as those counters (or some
>>> similar indication) are the only thing that will cause the RS to reject
>>> tokens that have been used the requisite number of times.  So, RS state
>>> requirements grows with the number of 'exi'-bearing tokens that are issued
>>> for them.  I suppose a bloom filter might be a way out, though...
>> I don't see why storage requirements would grow more compared to regular
>> tokens with the "exp" claim. The way exi is intended to be implemented
>> is as follows:
>> 1. C ---Token(exi=100)---> RS  (internal_clock=54645)
>> 2. RS generates a new 'exp' for the token, sets it to 54745 and discards
>> the exi claim.
>> 3. RS expires token according to internal clock (i.e. at 54745)
>> If you send the RS a lot of tokens it will eventually exhaust its
>> memory, but that would happen with regular exp claims as well if the
>> attacker can craft/obtain enough tokens with sufficiently long lifetime.
>> Note that these would have to be tokens for different clients, since the
>> framework currently recommends to only store one token per client.
>> The advantage for the attacker with exi is that it could hold back any
>> tokens without having to worry about the expiration, but it would still
>> have to hoard enough tokens for different clients, all applicable to the
>> RS in order to exhaust the RS's storage.
> My point is that a token with "exi" is potentially valid "forever".
> Suppose I use that token once, and the RS does as you describe above,
> computing an "exp" for that token.  If I post a new token to that RS so it
> discards the "exi"-ful token, or the expiration timer fires and the RS
> forgets about that token, then there is nothing to stop me (or an attacker)
> from replaying that same original "exi"-bearing token.  The RS would then
> see "exi", compute a new derived "exp", and give the token a whole nother
> validity period.
> Only if the RS retains some state that it has seen that specific token and
> used up the "exi" period is this token replay prevented.  I don't see a way
> to reliably retain that state without having some permanent storage
> dedicated to the state for each "exi" token that has evern been received,
> over the lifetime of the RS.  (A bloom filter or similar solution uses less
> state, but reduces reliability to some extent.)

I've added text in sections 6.6. and 5.8.3 to address this.

>>>>> 68.)
>>>>>      o  The client performs an introspection of the token.  Although this
>>>>>         is not explicitly forbidden, how exactly a client does
>>>>>         introspection is not currently specified for OAuth.
>>>>> I'm pretty sure this is overtaken by events (sorry for my part in
>>>>> that!).  E.g., draft-ietf-oauth-jwt-introspection-response discusses
>>>>> clients doing introspection, and even RFC 7662 itself discusses using a
>>>>> client secret to authenticate to the introspection endpoint.  I think
>>>>> there's another document between those two that's also relevant, but
>>>>> can't find it right now
>>>> [LS] I am not so sure. When reading the fine print in both RFC 7662 and
>>>> draft-ietf-oauth-jwt-introspection-response, I find that when they mention
>>>> the term "client", they refer to the protected resource / RS as being a
>>>> client of
>>>> the AS introspection endpoint.  A client holding an access token and
>>>> performing introspection is never explicitly mentioned in both
>>>> documents, to my best
>>>> knowledge.
>>> It seems like we should try to check on this in Singapore, while the usual
>>> suspects are easily at hand.
>> Yes together with the other OAuth questions.

We discussed this, OAuth experts disagree whether introspection by 
clients is implicitly forbidden. It is not explicitly forbidden at 
least, so the text is still correct. -> No change

Background: The OAuth experts arguing for "implicitly forbidden" point 
to the text saying: "In OAuth 2.0 [RFC6749], the contents of tokens are 
opaque to clients." (from RFC 7662) and read this as "the client 
should/must not know the contents of the token and therefore not be 
allowed to do introspection".

Ludwig Seitz, PhD
Security Lab, RISE
Phone +46(0)70-349 92 51