Re: [OAUTH-WG] proposed resolution for PKCE in OAuth 2.1

Nov Matake <matake@gmail.com> Tue, 19 May 2020 02:55 UTC

Return-Path: <matake@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 67DBC3A07D5 for <oauth@ietfa.amsl.com>; Mon, 18 May 2020 19:55:12 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.197
X-Spam-Level:
X-Spam-Status: No, score=-0.197 tagged_above=-999 required=5 tests=[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 oj39Jc900CKT for <oauth@ietfa.amsl.com>; Mon, 18 May 2020 19:55:08 -0700 (PDT)
Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) (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 AC9253A07CA for <oauth@ietf.org>; Mon, 18 May 2020 19:55:08 -0700 (PDT)
Received: by mail-pg1-x52c.google.com with SMTP id s10so3479814pgm.0 for <oauth@ietf.org>; Mon, 18 May 2020 19:55:08 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:message-id:mime-version:subject:date:in-reply-to:cc:to :references; bh=nP/DJmJlnFlogmcZtm+GGCqmRa76b0aSVA/xi6d4jYc=; b=QGnU3B5BpQ+5S4fU3uivG1IuPUsSpbyCySHJKTFmrodxOjqi/5/g24eR2kNXIfoMX3 M0+iZD6XMK6z65XoWDz+CxTHfbBPd1N379EiyypMDLwv2cHyltRpBgk0GHojA7gAtcyJ PpLNXNDSu8+4uzba6mUon6WjB+ox/fYiDffCIx/xJCh0pF05Ln8ELXD33QIDz4B7BQKU BdkthbidwIZXPm7J9EWOfA2FaO7jvpDrfatVHFxWiTmGYuTeeM5vbMK7uk5N7XSvFhJz ofjXxEJR5zCn3zZ74wNkRi2SnTpiI93So58eCP1QSMH8u+K0yoVMKwIvySg1zlRqSBSh EUTA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:mime-version:subject:date :in-reply-to:cc:to:references; bh=nP/DJmJlnFlogmcZtm+GGCqmRa76b0aSVA/xi6d4jYc=; b=oFMnxt1tta3gJ3BUgJyOOwMANISVzdqRQ6qfOhVQBz0XK9XMv0zQ3gDGFcSSEAKIbm CBJ/E8QcPah0S3pk9bjyPcjkWIqjY9OvjnnjSQFyyxO5z2iazsruekkJ0Iyuk+vZDFUO 6fvHYyE/s5MYIp0xNN2/APzDCp/a0/eDkZ+BwfNRmDmG50OgtyxIuPI1IhkiM9pGsCbL XE7sCD89dYiGkd9iKfmHwz9/9gEbDcNcyLN3qIqQhuxIRImcmBh2lZd8B9SV/BrCAsbM xA/5oyX6uJTa0UYFOF11hyiZt+6Ojqv+ZhawuCHUlZnHa3Yu7lRz4NAZR4wxIpDXOTxf 5VfA==
X-Gm-Message-State: AOAM531gGVBojcVc5CAxQlbgtOfCeALOo+8jebofAv5pgvCPNXHaNo7x uYOtsjdMKYXuPVfHVFqq0rwS4dU5ocs=
X-Google-Smtp-Source: ABdhPJzqeluOR7TMOu3VwB1LGthOKUhNpAnqGtRpFiLFhXrJM/+I5Z9ggTr1as3se9MPNe3kn9CnmQ==
X-Received: by 2002:a63:1c4c:: with SMTP id c12mr10827599pgm.26.1589856907773; Mon, 18 May 2020 19:55:07 -0700 (PDT)
Received: from [172.16.80.79] (122x210x153x65.ap122.ftth.ucom.ne.jp. [122.210.153.65]) by smtp.gmail.com with ESMTPSA id n205sm8997pfd.50.2020.05.18.19.55.05 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 May 2020 19:55:06 -0700 (PDT)
From: Nov Matake <matake@gmail.com>
Message-Id: <A9DFCD43-24E5-41B7-9C06-9D2AFACA49EC@gmail.com>
Content-Type: multipart/alternative; boundary="Apple-Mail=_D64D77BB-819B-4806-B411-73BE4DD9A4A7"
Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.80.23.2.2\))
Date: Tue, 19 May 2020 11:55:03 +0900
In-Reply-To: <1bc5387b-d9a1-fa36-83d8-15756e9a1a51@danielfett.de>
Cc: "oauth@ietf.org" <oauth@ietf.org>
To: Daniel Fett <fett@danielfett.de>
References: <MN2PR00MB0686CF5B850104F0BCCC5202F5BC0@MN2PR00MB0686.namprd00.prod.outlook.com> <1bc5387b-d9a1-fa36-83d8-15756e9a1a51@danielfett.de>
X-Mailer: Apple Mail (2.3608.80.23.2.2)
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/qrLAf3nWRt8HAFkO49qGrPRuelo>
Subject: Re: [OAUTH-WG] proposed resolution for PKCE in OAuth 2.1
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, 19 May 2020 02:55:12 -0000

Hi,

I thought the server MUST reject such token requests, but I couldn’t find such definition in RFC7636...

> The client will send the code, along with a (now not matching) code_verifier to the server. The server will ignore the code_verifier (as it was not expected) and send back an access token and ID token to the client.
https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/#noncepkce-sidestep-attack <https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/#noncepkce-sidestep-attack>

If the behavior is acceptable by RFC7636, "Nonce/PKCE Sidestep Attack” would be possible.

Plus, with such AS behavior, CSRF protection using PKCE can also be bypassed as below.
1. The attacker removes code_challenge from his/her own AuthZ Req, receives a non-code_challenge-bound code, and sends it to the victim.
2. The client receives the attacker’s code from the victim, and sends it to the AS w/ the valid code_verifier bound to the victim’s browser session.
3. The AS ignores the code_verifier and returns tokens.

If that’s the case, current OAuth 2.0 PKCE implementation can be weaker than expected..

nov

> 2020/05/19 1:54、Daniel Fett <fett@danielfett.de>のメールt;のメール:
> 
> Hi all,
> 
> Talking to Torsten, we realized that providing a generic extension point here is probably not a good idea. It is really hard to tell what protects you from code injection and what does not, and people might come up with all sorts of non-standard and potentially insecure solutions. 
> 
> Even just for PKCE vs. Nonce, it is not obvious if they provide the same level of protection. In an attempt to answer this question, I tried to come up with a more systematic analysis of "PKCE vs Nonce". I wrote up my results here: 
> https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/ <https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/>
> 
> Although this is not a formal analysis, I hope that I have covered all interesting cases. Please review the text and let me know if I have missed something or if there are any mistakes.
> 
> The main results are:
> In terms of protection against CSRF and code misuse, PKCE and Nonce provide similar levels of security, with a slight advantage for PKCE.
> In practice, a circumvention of both mechanisms, however, is possible if an AS allows a client to choose between PKCE and Nonce and the client makes use of this freedom. I propose to call this attack the Nonce/PKCE Sidestep Attack. → Please review the attack description in the analysis.
> To avoid the Nonce/PKCE Sidestep Attack, clients must not switch between using only PKCE and only Nonce (but may use both in parallel, or switch between using only PKCE and PKCE+Nonce). Authorization servers must enforce PKCE unless they know that the client uses Nonce for all of its flows (and checks the Nonce value). The presence of a nonce parameter in the authorization request is not sufficient to determine if a client actually checks the nonce claim in the ID token.
> As you can see, already having two more-or-less well-understood mechanisms is hard enough to wrap your head around from a security standpoint. We should therefore make PKCE the default and Nonce an option for backwards compatibility.
> 
> To this end, I would like to propose the follwing strawman, based on Torsten's and Aaron's suggestions:
> 
> An AS MUST reject requests without a code_challenge from public
> clients, and MUST reject such requests from other clients unless there
> is reasonable assurance that the client mitigates authorization code
> injection using the OpenID Connect Nonce mechanism and that this
> mitigation is used for all interactions with the client. See section
> 9.7 for details.
> 
> Section 9.7:
> 
> Clients MUST prevent injection (replay) of authorization codes into
> the authorization response by attackers. The use of the
> `code_challenge` parameter is RECOMMENDED to this end. For
> confidential clients, the OpenID Connect `nonce` parameter and ID
> Token Claim {{OpenID}} MAY be used instead of or in addition to the
> `code_challenge` parameter for this purpose. The `code_challenge` or
> OpenID Connect `nonce` value MUST be transaction-specific and securely
> bound to the client and the user agent in which the transaction was
> started.
> 
> If the OpenID Connect `nonce` is used to mitigate authorization code
> injection instead of `code_challenge`, client and authorization server
> MUST ensure that the mitigation is applied to every interaction with
> the client and that the client cannot switch between `code_challenge`
> and `nonce`. For example, the presence of a `nonce` parameter in the
> authorization request is not sufficient to determine that the
> `code_verifier` check can be skipped.
> 
> 
> Of course, we need to adapt the wording in the Security BCP accordingly.
> 
> -Daniel
> 
> 
> 
> 
> Am 15.05.20 um 01:01 schrieb Mike Jones:
>> I agree with Nov that obscuring the language in 9.7 would be a disservice to developers.
>> 
>> The Security BCP, which has already going the WGLC, explicitly calls out the use of nonce as part of the best practices.  OAuth 2.1 should do no less.
>> 
>> The 9.7 language that Aaron proposed was the result of many people's contributions and a vigorous discussion.  Let's publish the next version of 2.1 with that language intact, as I believe it represents at least a local point of hard-won consensus.  Let's get that language into the record of drafts.
>> 
>> There's always time to debate it and change it later in subsequent drafts, but let's not now lose what it took a lot of effort to achieve.
>> 
>> 				Thanks,
>> 				-- Mike
>> 
>> -----Original Message-----
>> From: Nov Matake <matake@gmail.com> <mailto:matake@gmail.com> 
>> Sent: Thursday, May 14, 2020 3:18 AM
>> To: Torsten Lodderstedt <torsten@lodderstedt.net> <mailto:torsten@lodderstedt.net>
>> Cc: OAuth WG <oauth@ietf.org> <mailto:oauth@ietf.org>; Mike Jones <Michael.Jones@microsoft.com> <mailto:Michael.Jones@microsoft.com>
>> Subject: Re: [OAUTH-WG] proposed resolution for PKCE in OAuth 2.1
>> 
>> There is no specific mechanism right now.
>> But future developers won’t be able to read the reason why the extension point is given only for confidential clients.
>> 
>>> On May 14, 2020, at 18:32, Torsten Lodderstedt <torsten@lodderstedt.net> <mailto:torsten@lodderstedt.net> wrote:
>>> 
>>> Are you aware of any suitable mechanism? I’m asking since from my perspective this clause is mainly intended to allow existing OpenID Connect deployments to use nonce instead of PKCE in combination with OAuth 2.1. It’s a compromise. I think we should not encourage others to invent their own OAuth security mechanisms. 
>>> 
>>>> On 14. May 2020, at 09:37, Nov Matake <matake@gmail.com> <mailto:matake@gmail.com> wrote:
>>>> 
>>>> Hi,
>>>> 
>>>> Why not allowing public clients use "other suitable mechanisms” then?
>>>> OAuth WG can allow both type of clients do so, then OIDF will define nonce as the alternative only for confidential clients.
>>>> 
>>>>> 2020/05/14 15:56、Torsten Lodderstedt <torsten=40lodderstedt.net@dmarc.ietf.org> <mailto:torsten=40lodderstedt.net@dmarc.ietf.org>のメール:
>>>>> 
>>>>> Hi all,
>>>>> 
>>>>> I would also like to thank everybody for the substantial discussion.  
>>>>> 
>>>>> The proposed change for Section 4.1.2.1 works for me (as already stated). I’m not fully comfortable with the proposed change for Section 9.7 for the following reasons:
>>>>> 
>>>>> - The text is weaker than Section 4.1.2.1 since it RECOMMENDS use of PKCE instead of requiring it (with a well-defined exception).
>>>>> - Given the latest findings re nonce I don’t feel comfortable with recommending any mechanism that this WG is not responsible for and thus did not conduct the security threat analysis for. I think the better way for us as WG is to define the extension point for other mechanisms. The OpenID Foundation (or any other body) can then fill in and issue a statement that nonce (or another suitable mechanism) fulfils the requirements of the extension point. 
>>>>> 
>>>>> Based on this considerations, I propose the following text for Section 9.7:
>>>>> 
>>>>> Clients MUST prevent injection (replay) of authorization codes into 
>>>>> the authorization response by attackers. Public clients MUST use the 
>>>>> "code_challenge” with a transaction-specific value that is securely 
>>>>> bound to the client and the user agent in which the transaction was 
>>>>> started. Confidential clients MUST use the “code_challenge” in the 
>>>>> same way or other suitable mechanisms to mitigate authorization code 
>>>>> injection.
>>>>> 
>>>>> This text follows the logic in Section 4.1.2.1 and allows use of the nonce for confidential clients.
>>>>> 
>>>>> best regards,
>>>>> Torsten. 
>>>>> 
>>>>>> On 12. May 2020, at 02:21, Mike Jones <Michael.Jones=40microsoft.com@dmarc.ietf.org> <mailto:Michael.Jones=40microsoft.com@dmarc.ietf.org> wrote:
>>>>>> 
>>>>>> That works for me.  Thanks all for the useful back-and-forth that got us to this point of clarity.  I suspect many of us learned things along the way; I know that I did!
>>>>>> 
>>>>>>                                                     Cheers,
>>>>>>                                                     -- Mike
>>>>>> 
>>>>>> From: Aaron Parecki <aaron@parecki.com> <mailto:aaron@parecki.com>
>>>>>> Sent: Monday, May 11, 2020 4:55 PM
>>>>>> To: OAuth WG <oauth@ietf.org> <mailto:oauth@ietf.org>
>>>>>> Cc: Neil Madden <neil.madden@forgerock.com> <mailto:neil.madden@forgerock.com>; Mike Jones 
>>>>>> <Michael.Jones@microsoft.com> <mailto:Michael.Jones@microsoft.com>
>>>>>> Subject: Re: [OAUTH-WG] proposed resolution for PKCE in OAuth 2.1
>>>>>> 
>>>>>> Thank you Neil.
>>>>>> 
>>>>>> To address Mike's concerns in the previous threads, I would like to also update section 9.7 with the following text:
>>>>>> 
>>>>>> Clients MUST prevent injection (replay) of authorization codes into 
>>>>>> the authorization response by attackers. The use of the 
>>>>>> `code_challenge` parameter is RECOMMENDED to this end. For 
>>>>>> confidential clients, the OpenID Connect `nonce` parameter and ID 
>>>>>> Token Claim {{OpenID}} MAY be used instead of or in addition to the 
>>>>>> `code_challenge` parameter for this purpose. The `code_challenge` 
>>>>>> or OpenID Connect `nonce` value MUST be transaction-specific and 
>>>>>> securely bound to the client and the user agent in which the transaction was started.
>>>>>> 
>>>>>> This change better clarifies the specific circumstances under which the "nonce" parameter is sufficient to protect against authorization code injection.
>>>>>> 
>>>>>> Aaron Parecki
>>>>>> 
>>>>>> On Mon, May 11, 2020 at 11:55 AM Neil Madden <neil.madden@forgerock.com> <mailto:neil.madden@forgerock.com> wrote:
>>>>>> I am happy with this proposed wording. Thanks for updating it.
>>>>>> 
>>>>>> — Neil
>>>>>> 
>>>>>> 
>>>>>> On 11 May 2020, at 19:52, Aaron Parecki <aaron@parecki.com> <mailto:aaron@parecki.com> wrote:
>>>>>> 
>>>>>> Thanks for the lively discussion around PKCE in OAuth 2.1 everyone! 
>>>>>> 
>>>>>> We would like to propose the following text, which is a slight variation from the text Neil proposed. This would replace the paragraph in 4.1.2.1 (https://tools.ietf.org/html/draft-parecki-oauth-v2-1-02#section-4.1.2.1 <https://tools.ietf.org/html/draft-parecki-oauth-v2-1-02#section-4.1.2.1>) that begins with "If the client does not send the "code_challenge" in the request..."
>>>>>> 
>>>>>> "An AS MUST reject requests without a code_challenge from public clients, and MUST reject such requests from other clients unless there is reasonable assurance that the client mitigates authorization code injection in other ways. See section 9.7 for details."
>>>>>> 
>>>>>> Section 9.7 is where the nuances of PKCE vs nonce are described.
>>>>>> 
>>>>>> As Neil described, we believe this will allow ASs to support both OAuth 2.0 and 2.1 clients simultaneously. The change from Neil's text is the clarification of which threats, and changing to MUST instead of SHOULD. The "MUST...unless" is more specific than "SHOULD", and since we are already describing the explicit exception to the rule, it's more clear as a MUST here.
>>>>>> 
>>>>>> Aaron Parecki
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> _______________________________________________
>>>>>> OAuth mailing list
>>>>>> OAuth@ietf.org <mailto:OAuth@ietf.org>
>>>>>> https://www.ietf.org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>
>>>>>> 
>>>>>> _______________________________________________
>>>>>> OAuth mailing list
>>>>>> OAuth@ietf.org <mailto:OAuth@ietf.org>
>>>>>> https://www.ietf.org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>
>>>>> _______________________________________________
>>>>> OAuth mailing list
>>>>> OAuth@ietf.org <mailto:OAuth@ietf.org>
>>>>> https://www.ietf.org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>
>> _______________________________________________
>> OAuth mailing list
>> OAuth@ietf.org <mailto:OAuth@ietf.org>
>> https://www.ietf.org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>
> 
> _______________________________________________
> OAuth mailing list
> OAuth@ietf.org
> https://www.ietf.org/mailman/listinfo/oauth