I disagree with the language below. It’s perfectly legal to switch, as the
same client may do both OpenID Connect and pure OAuth interactions, depending
upon whether the “openid” scope is included. Both can be secure.
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.
I’d rather that the onus be put on new code, than existing code. For instance
new code wanting to require PKCE on all interactions could use something like a
“require_pkce” dynamic client registration parameter (or corresponding static
registration). Otherwise, it should be up to the client which of the
mechanisms to use.
-- Mike
From: Aaron Parecki <[email protected]>
Sent: Wednesday, May 20, 2020 3:48 PM
To: Nov Matake <[email protected]>
Cc: Mike Jones <[email protected]>; [email protected]
Subject: [EXTERNAL] Re: [OAUTH-WG] proposed resolution for PKCE in OAuth 2.1
So if I'm understanding this correctly, it sounds like the AS needs to reject a
token request with code_verifier if the authorization code was issued in
response to a request that did not contain a code_challenge. This to me sounds
like it would be simpler to just say the code_challenge and code_verifier are
always required.
That said, I do understand the previously discussed concerns around existing
OpenID Connect clients.
I believe the text that Daniel proposed is the best of both worlds, and I
support making this change in both OAuth 2.1 and the Security BCP.
Aaron Parecki
On Tue, May 19, 2020 at 9:29 AM Nov Matake
<[email protected]<mailto:[email protected]>> wrote:
Yes.
The root problem isn’t the mix-use of PKCE and nonce, it’s PKCE implementation
bug.
Yeah, all PKCE implementation MUST reject such requests, regardless it’s OAuth
2.1 or 2.0.
(and it’s probably because of PKCE spec’s ambiguity..)
2020/05/20 1:13、Mike Jones
<[email protected]<mailto:[email protected]>>のメール:
So it sounds me like the fix is to have servers reject PKCE requests with
incomplete parameter sets: requests that only contains one of code_challenge
and code_verified. Will that eliminate the attack, Nov?
-- Mike
From: OAuth <[email protected]<mailto:[email protected]>> On Behalf
Of Nov Matake
Sent: Monday, May 18, 2020 11:50 PM
To: Daniel Fett <[email protected]<mailto:[email protected]>>
Cc: [email protected]<mailto:[email protected]>
Subject: Re: [OAUTH-WG] proposed resolution for PKCE in OAuth 2.1
Sure, feel free to add the senario to your post.
FYI:
my OAuth2 server ruby gem rejects such token requests,
https://github.com/nov/rack-oauth2/blob/master/lib/rack/oauth2/server/extension/pkce.rb#L28
and Google also does the same.
https://gist.github.com/nov/9feba86685bd3b18b4bf7bfb88022046
So I'm guessing such behavior is relatively rare-case, hopefully.
iPadから送信
2020/05/19 15:43、Daniel Fett
<[email protected]<mailto:[email protected]>>のメール:
Hi,
Am 19.05.20 um 04:55 schrieb Nov Matake:
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
If the behavior is acceptable by RFC7636, "Nonce/PKCE Sidestep Attack” would be
possible.
I *think* that there is nothing preventing servers from sometimes using PKCE
and sometimes using Nonce. I assume that this is out of the scope of the
existing specifications.
I would be interested to hear how actual implementations handle this in
practice.
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..
Excellent point!
Would it be okay if I add that attack to the original post (with credits, of
course)?
-Daniel
nov
2020/05/19 1:54、Daniel Fett <[email protected]<mailto:[email protected]>>のメール:
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/
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:
1. In terms of protection against CSRF and code misuse, PKCE and Nonce
provide similar levels of security, with a slight advantage for PKCE.
2. 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.
3. 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 <[email protected]><mailto:[email protected]>
Sent: Thursday, May 14, 2020 3:18 AM
To: Torsten Lodderstedt
<[email protected]><mailto:[email protected]>
Cc: OAuth WG <[email protected]><mailto:[email protected]>; Mike Jones
<[email protected]><mailto:[email protected]>
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
<[email protected]><mailto:[email protected]> 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
<[email protected]><mailto:[email protected]> 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
<[email protected]><mailto:[email protected]>のメール:
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
<[email protected]><mailto:[email protected]>
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 <[email protected]><mailto:[email protected]>
Sent: Monday, May 11, 2020 4:55 PM
To: OAuth WG <[email protected]><mailto:[email protected]>
Cc: Neil Madden <[email protected]><mailto:[email protected]>;
Mike Jones
<[email protected]><mailto:[email protected]>
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
<[email protected]><mailto:[email protected]> wrote:
I am happy with this proposed wording. Thanks for updating it.
— Neil
On 11 May 2020, at 19:52, Aaron Parecki
<[email protected]><mailto:[email protected]> 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) 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
[email protected]<mailto:[email protected]>
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
[email protected]<mailto:[email protected]>
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
[email protected]<mailto:[email protected]>
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
[email protected]<mailto:[email protected]>
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
[email protected]<mailto:[email protected]>
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
[email protected]<mailto:[email protected]>
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/oauth