Warren: My understanding is that the interception in the sentences you
quoted happens in the attacker's user agent, while the CSRF detection
happens as a result of interactions with the victim's user agent. So the
attacker cannot generally block AS requests.
And in particular, the CSRF detection happens as a result of a request by
the victim's user agent, which is not controlled by the attacker.

The client server can thus invalidate the code upon detecting the CSRF (by
any mechanism), and there's nothing the attacker can do about that except
obtaining and exchanging the code fast enough that the invalidation has not
happened yet.
For the mentioned information vectors for obtaining the code (such as logs
or asking the user for the URL), I think it is unlikely that the attacker
can obtain the code faster than the client server can invalidate it.
So I think this mitigation (whatever the mechanism for invalidation) is
enough to prevent essentially all practical attacks.

But I'm not that confident that my understanding is correct, or whether we
are even talking about the same thing any longer. I think this thread is on
the verge of becoming too messy for any productive conversation to happen.
The quotes and references (1), S1, etc. are not very easy to follow across
subthreads.

Cheers,
Frederik

On Fri, 7 Nov 2025 at 10:52, Warren Parad <[email protected]>
wrote:

> You know, I had that thought, but I read this statement by Jonas:
>
> The attacker intercepts the authorization URL when being sent to the
>> authorization server. Most of the time, this works by copying the URL
>> displayed on the AS’s login page. Sometimes it’s a bit more complicated
>> because the attacker must intercept URLs called in their browser. However,
>> the attacker has full control over their web browser, so this is easy.
>
>
> Which tells me that it is actually the same vulnerability. (However, I
> read "web browser" as "application" here, so that could be my mistake).
> "Attacker has control over the web browser" means that they will do
> anything in their power to circumvent the controls in place.
>
> If the attacker controls the application in the user agent, I don't think
> it makes sense to secure less useful mechanisms. For instance, if the
> attacker could block AS requests, then it doesn't make sense to introduce a
> "but intentionally using PKCE without a verifier is one way to revoke a
> code without getting a token that you could accidentally use." because that
> would just be blocked. Sure the attacker might not block AS requests, but
> if they could, then we will see this attack vector become the only one that
> gets used. So in practice, we should assume attackers to perform the most
> sophisticated attack possible given any scenario.
>
> On Fri, Nov 7, 2025 at 10:42 AM Frederik Krogsdal Jacobsen
> <[email protected]> wrote:
>
>> Warren, I think you may be mixing this thread up with Andrey's thread on
>> a different, but related topic? Some of the replies to Andrey's thread got
>> scattered across different threads (at least in my email client).
>> In this attack (as I understand it), the attacker does not block any
>> request to the AS.
>> PKCE by itself does not fix this problem, but intentionally using PKCE
>> without a verifier is one way to revoke a code without getting a token that
>> you could accidentally use.
>>
>> Cheers,
>> Frederik
>>
>> On Fri, 7 Nov 2025 at 10:36, Warren Parad <wparad=
>> [email protected]> wrote:
>>
>>> If PKCE fixes a problem, then that's the solution to the problem, it
>>> doesn't make sense to add a "standard alternative" because of that. State,
>>> never existed for CSRF protection, that was the nonce, which has been
>>> deprecated with the introduction of PKCE, so neither S1 or S3 are relevant
>>> right?
>>>
>>> I'm missing the value in a "revocation mechanism" for authorization
>>> codes, if the attacker can block requests to the AS, then how would the
>>> revocation mechanism end up getting called? What would trigger that?
>>>
>>> On Fri, Nov 7, 2025 at 10:08 AM Frederik Krogsdal Jacobsen
>>> <[email protected]> wrote:
>>>
>>>> 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]
>>>>
>>>
_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to