I think S1 is the best bet for a standard solution to mention in OAuth 2.1.
State could be deprecated as a solution for CSRF protection, but it is
still useful for other things.

An AS could individually recommend variations on S2 if they do not plan to
implement PKCE.

I still think that a more general cancellation/revocation mechanism as
mentioned by Max would be useful (also for other grant types such as
auth_req_ids from CIBA), but I understand that introducing this is probably
off-topic for this thread.

Cheers,
Frederik

On Thu, 6 Nov 2025 at 17:43, Aaron Parecki <aaron=
[email protected]> wrote:

> I think that's covered as part of the discussion of how a client and AS
> know that each other are speaking OAuth 2.1 vs 2.0.
>
>
> On Thu, Nov 6, 2025 at 11:40 AM Neil Madden <[email protected]>
> wrote:
>
>> The only issue I have with deprecating state for CSRF protection is that
>> the client has no way in general to know if the AS supports (in fact
>> enforces) PKCE. If it doesn’t, then we may end up with no CSRF protection
>> at all, and clients being vulnerable to Login CSRF/session fixation-like
>> attacks.
>>
>> — Neil
>>
>> On 6 Nov 2025, at 16:12, Aaron Parecki <[email protected]> wrote:
>>
>> 
>>
>> S1 seems like the cleanest solution to me. I think this should also come
>> with language officially deprecating "state" for CSRF protection like
>> Philippe said.
>>
>>
>> On Thu, Nov 6, 2025 at 10:59 AM Primbs, Jonas <
>> [email protected]> wrote:
>>
>>> Let’s collect auth code revocation solutions:
>>>
>>> S1: Enforce PKCE + normal token request but without code_verifier.
>>> + No additional endpoints
>>> + Works for many existing implementations
>>> - AS must implement PKCE and enforce it for all clients (bad for testing)
>>>
>>> S2: Use specific client_id at the token endpoint.
>>> + No additional endpoints
>>> -  A bit hacky
>>>
>>> S3: Specify a dedicated token endpoint
>>> + One official way
>>> - Huge changes required
>>>
>>> S4: Use token revocation endpoint
>>> + Just an extension of existing endpoints
>>> - Client cannot know if the AS implements this
>>>
>>>
>>>
>>> Am 06.11.2025 um 08:24 schrieb Neil Madden <[email protected]>:
>>>
>>> This makes me wonder if we could in fact have a special client_id value
>>> that indicates that the AS should revoke the code (and any tokens if
>>> issues)? It's a bit hacky but has the advantage of likely doing the right
>>> thing for most ASes, as Tim mentions. Something like
>>> client_id=csrf_detected_revoke_please.
>>>
>>> On 6 Nov 2025, at 13:04, Tim Würtele <[email protected]>
>>> wrote:
>>>
>>> Hi Jonas,
>>>
>>> a minor (but imho relevant to this discussion) nitpicking inline.
>>>
>>> Best,
>>>
>>> Tim
>>> On 05.11.25 16:25, Primbs, Jonas wrote:
>>>
>>> Hi Frederik,
>>>
>>> yes, calling the token request validly, thereby invalidating the
>>> authorization code for future usage by the attacker, and throwing away the
>>> token response could also be a solution.
>>> However, I am not sure what the implications could be with respect to
>>> how authorization servers handle this (e.g., starting a session, which
>>> confuses users when they look at the list of active sessions) or how
>>> clients handle this (e.g., logging tokens in a potential crash dump).
>>> If authorization servers implement token revocation correctly, when
>>> authorization codes are used twice, sending a second valid token request
>>> with the same authorization code afterwards might ensure that the issued
>>> tokens cannot be used anymore.
>>>
>>> Again, this might fail if the client faces any issues. So I prefer a
>>> standardized authorization code invalidation mechanism.
>>> One opportunity here, which is already standardized, is enforcing PKCE
>>> and sending no code_verifier in the token request intentionally.
>>>
>>> The issue with that is the (historically grown) lack of precision in the
>>> specs as to when exactly an authZ code is to be invalidated by the AS. Let
>>> me elaborate a bit:
>>>
>>> RFC 6749 says (in 4.x) the client MUST only use the code once and the AS
>>> MUST deny all but the first request with a given code (and SHOULD revoke
>>> associated tokens). In 10.5, we have "Authorization codes MUST be [...]
>>> single-use." - without being explicit about whether this statement applies
>>> to the "user" of the code (the client), the AS, or both; although I'd argue
>>> that interpreting this as "the client may only use it once" is a
>>> justifiable interpretation (especially because the subsequent sentences in
>>> 10.5 also just repeat the SHOULD statement from 4.x).
>>>
>>> RFC 6819, 4.4.1.1 does say "The authorization server should enforce a
>>> one-time usage restriction (see Section 5.1.5.4)."; but the language there
>>> is not normative ("may", "may want", ...); the same is true for 5.2.1.1.
>>>
>>> OIDC is even more vague (3.1.3.2): The AS MUST ... "If possible, verify
>>> that the Authorization Code has not been previously used."
>>>
>>> ... just a few examples.
>>>
>>> Using PKCE does not change this ambiguity; RFC 7636 does not talk about
>>> code invalidation at all.
>>>
>>>
>>> In other words: An error response from the AS's token EP, e.g., due to a
>>> wrong/missing code_verifier does not guarantee that the code has been
>>> invalidated. And as others have pointed out in this thread, there are AS
>>> implementations out there that do accept a code multiple times (be it "on
>>> purpose", or due to CAP). Of course, one might argue that these are not
>>> standards-compliant, but I don't think there's a very strong case for that
>>> claim, given the (historically) inaccurate wording...
>>>
>>> That being said: If I were to implement a client today, I would make
>>> such a "wrong" token request to at least give the AS a chance of detecting
>>> the attack - and if the AS follows the SHOULD-advise from 6749, any tokens
>>> issued for that code would then immediately be invalidated, which of course
>>> does not prevent an attack, but may help to limit the damage.
>>>
>>> Side note: This "best effort" damage control strategy does not even need
>>> PKCE, just sending the code with a wrong client_id should lead to the same
>>> result (from a "did the AS implement 6749's SHOULD" perspective).
>>>
>>>
>>> If there already is a spec for that in CIBA, we should include or at
>>> least reference this in the OAuth 2.1 spec.
>>>
>>> Greetings,
>>> Jonas
>>>
>>>
>>> Am 05.11.2025 um 04:02 schrieb Frederik Krogsdal Jacobsen
>>> <[email protected]> <[email protected]>:
>>>
>>> Hi Jonas,
>>>
>>> Thanks for the detailed explanation of the attack and possible
>>> mitigations.
>>>
>>> It seems to me that your suggestion 3 could be implemented by the client
>>> by simply exchanging the code and throwing away the token response when the
>>> initial CSRF is detected.
>>> This would of course only work with an AS that correctly implements the
>>> security guidance in section 10.5 of RFC 6749: "Authorization codes
>>> MUST be short lived and single-use."
>>> The main problem with this approach is that it is a bit confusing to
>>> explain.
>>>
>>> I also know that in practice, some AS implementers allow multiple uses
>>> of the code, so it may be interesting to look into defining a specific
>>> "cancel request" that uses up a code without returning a token.
>>> Defining such a request might also make the approach easier to explain.
>>> In fact, many OIDC providers already define custom "cancel" requests to
>>> mitigate phishing. A "cancel" request might also be useful for OpenID CIBA
>>> [1].
>>>
>>> Do you see any problems with this approach?
>>>
>>> Cheers,
>>> Frederik
>>>
>>> [1]:
>>> https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html
>>>
>>> On Tue, 4 Nov 2025 at 05:10, Primbs, Jonas <
>>> [email protected]> wrote:
>>>
>>>> Hi all,
>>>>
>>>> according to Aaron’s recommendation, I have created a PR for OAuth 2.1:
>>>> https://github.com/oauth-wg/oauth-v2-1/pull/230
>>>>
>>>> It references OpenID Connect’s response modes (fragment and form_post)
>>>> as solutions for Browser-Swapping attacks, which I have presented in
>>>> today’s OAuth WG meeting.
>>>> If you have missed my presentation, but are still interested, here are
>>>> my slides:
>>>> https://datatracker.ietf.org/meeting/124/materials/slides-124-oauth-sessa-browser-swapping-01
>>>>
>>>> I’m interested in your feedback on this first draft, which currently
>>>> covers only recommendation #2 from my slides, because this is probably the
>>>> least controversial change.
>>>> If you are attending onsite, also feel free to speak to me in the
>>>> hallway. My company gave me enough of the „No, PKCE…“ t-shirts for the rest
>>>> of the week, so that it’s easier for you to find me. @Brian & Mike: I have
>>>> learned from the best ;-)
>>>>
>>>> Greetings,
>>>> Jonas
>>>>
>>>>
>>>> Jonas Primbs M.Sc.
>>>> University of Tübingen
>>>> Faculty of Science
>>>> Department of Computer Science
>>>> Sand 13, 72076 Tübingen, Germany
>>>> <https://www.google.com/maps/search/Sand+13,+72076+T%C3%BCbingen,+Germany?entry=gmail&source=g>
>>>> Tel.: (+49) 7071 / 29-70512
>>>> Mail: [email protected]
>>>> Web: https://kn.inf.uni-tuebingen.de
>>>>
>>>> _______________________________________________
>>>> OAuth mailing list -- [email protected]
>>>> To unsubscribe send an email to [email protected]
>>>>
>>>
>>>
>>> _______________________________________________
>>> OAuth mailing list -- [email protected]
>>> To unsubscribe send an email to [email protected]
>>>
>>> --
>>> Tim Würtele, M.Sc.
>>> Room V38 2.434
>>> Institute of Information Security - SEC
>>> Universität StuttgartUniversitätsstraße 38 
>>> <https://www.google.com/maps/search/Universit%C3%A4tsstra%C3%9Fe+38?entry=gmail&source=g>
>>> D-70569 Stuttgart
>>> Germany
>>> Phone: +49 (0) 711 685-88468https://sec.uni-stuttgart.de
>>>
>>> _______________________________________________
>>> OAuth mailing list -- [email protected]
>>> To unsubscribe send an email to [email protected]
>>>
>>>
>>> _______________________________________________
>>> OAuth mailing list -- [email protected]
>>> To unsubscribe send an email to [email protected]
>>>
>>>
>>> _______________________________________________
>>> OAuth mailing list -- [email protected]
>>> To unsubscribe send an email to [email protected]
>>>
>> _______________________________________________
> OAuth mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
>
_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to