I'm also not confident, which is why I just want to know what exactly is
happening *only on the victim's side*. It's trivial to figure out what the
attacker can do on their side. But if you're correct, and it's a question
about exfiltrated authorization codes, is the assumption that PKCE doesn't
solve the problem because PKCE too could be logged?

On Fri, Nov 7, 2025 at 11:30 AM Frederik Krogsdal Jacobsen
<[email protected]> wrote:

> 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 <wparad=
> [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