[OAUTH-WG] Re: Browser-Swapping
"Primbs, Jonas" <jonas.primbs@uni-tuebingen.de> Thu, 06 November 2025 15:52 UTC
Return-Path: <jonas.primbs@uni-tuebingen.de>
X-Original-To: oauth@mail2.ietf.org
Delivered-To: oauth@mail2.ietf.org
Received: from localhost (localhost [127.0.0.1]) by mail2.ietf.org (Postfix) with ESMTP id 69E098472AFA for <oauth@mail2.ietf.org>; Thu, 6 Nov 2025 07:52:06 -0800 (PST)
X-Virus-Scanned: amavisd-new at ietf.org
X-Spam-Flag: NO
X-Spam-Score: -4.4
X-Spam-Level:
X-Spam-Status: No, score=-4.4 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_MED=-2.3, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: mail2.ietf.org (amavisd-new); dkim=pass (2048-bit key) header.d=uni-tuebingen.de
Received: from mail2.ietf.org ([166.84.6.31]) by localhost (mail2.ietf.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AwKt586Jthuc for <oauth@mail2.ietf.org>; Thu, 6 Nov 2025 07:52:05 -0800 (PST)
Received: from mx04.uni-tuebingen.de (mx04.uni-tuebingen.de [IPv6:2001:7c0:300c:3105::8602:5d6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-256) server-digest SHA256) (No client certificate requested) by mail2.ietf.org (Postfix) with ESMTPS id 989868472A93 for <oauth@ietf.org>; Thu, 6 Nov 2025 07:51:47 -0800 (PST)
Received: from exchange.uni-tuebingen.de (ex01.uni-tuebingen.de [134.2.21.161]) by mx04.uni-tuebingen.de (Postfix) with ESMTPS id 436FF20CC6C5; Thu, 6 Nov 2025 16:51:46 +0100 (CET)
DKIM-Filter: OpenDKIM Filter v2.11.0 mx04.uni-tuebingen.de 436FF20CC6C5
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uni-tuebingen.de; s=20211202prod; t=1762444306; bh=3VKYR26dvu5cT6DmZYqJuF1AY+L3av6eiEv0oE2w6ok=; h=From:To:CC:Subject:Date:References:In-Reply-To:From; b=TfASwj0tGFnG+g1HtiDC+ia71WXOUFfg1cF5Tj5719EX2dAN0rCQmCfD8tAUKT7A3 s/50iO7xw9piq592GsDvsp1p0l4CwlIamghwkZuy/C6fls5GULZ1hJxJYbJXw1vrBo KnQJPh8semsHOx31XtRyjndfyLJ4Mii878FrniRjoCJu+FA/FelwhHxW+7iNL1zrkw ZMGUsCxc/DCiA5KhiXrb5sTa5LU8EFA/dY3103cFtjnRK09ljrqWMAl95UlbQG3zuq a3fS6MdXcHrkO5slqWmS38fV59i+QPwaKEDJ8EN59+O8jm+6t5C3lOn2wHJP8avFdf 2KMRGmah08C1Q==
Received: from Ex02.uni-tuebingen.de (134.2.21.162) by EX01.uni-tuebingen.de (134.2.21.161) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.61; Thu, 6 Nov 2025 16:51:45 +0100
Received: from Ex02.uni-tuebingen.de ([fe80::5ddd:1152:31fc:6bd3]) by EX02.uni-tuebingen.de ([fe80::5ddd:1152:31fc:6bd3%7]) with mapi id 15.01.2507.061; Thu, 6 Nov 2025 16:51:45 +0100
From: "Primbs, Jonas" <jonas.primbs@uni-tuebingen.de>
To: Tim Würtele <tim.wuertele@sec.uni-stuttgart.de>
Thread-Topic: [OAUTH-WG] Browser-Swapping
Thread-Index: AQHcTzVBzY7xOGMAAE29Y7kvAuhdgQ==
Date: Thu, 06 Nov 2025 15:51:45 +0000
Message-ID: <00DED1BB-78FE-49E8-BC1E-E94D3C057515@uni-tuebingen.de>
References: <F032F35A-D55E-40A7-8589-3DD64BF8F7A0@uni-tuebingen.de> <CAMQcq-ZF5QFBELsycQdyQeH8E2kaeCG4P2b=yNtwh=gJRja5hw@mail.gmail.com> <BA78ED94-7575-4ACA-9C26-C135BC424282@uni-tuebingen.de> <d57dfbe9-2935-4b6b-8c9a-b3fba6bdf682@sec.uni-stuttgart.de>
In-Reply-To: <d57dfbe9-2935-4b6b-8c9a-b3fba6bdf682@sec.uni-stuttgart.de>
Accept-Language: de-DE, en-US
Content-Language: en-US
X-MS-Has-Attach: yes
X-MS-TNEF-Correlator:
x-mailer: Apple Mail (2.3864.200.81.1.6)
x-originating-ip: [134.2.21.181]
Content-Type: multipart/signed; boundary="Apple-Mail=_CAD73C4B-0691-41CB-A749-93F9BFE9255D"; protocol="application/pkcs7-signature"; micalg="sha-256"
MIME-Version: 1.0
Message-ID-Hash: KQJCTKUUB7BDA3PW6QDPQX3S4N6RONQV
X-Message-ID-Hash: KQJCTKUUB7BDA3PW6QDPQX3S4N6RONQV
X-MailFrom: jonas.primbs@uni-tuebingen.de
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-oauth.ietf.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: "oauth@ietf.org" <oauth@ietf.org>
X-Mailman-Version: 3.3.9rc6
Precedence: list
Subject: [OAUTH-WG] Re: Browser-Swapping
List-Id: OAUTH WG <oauth.ietf.org>
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/zgfjuwMZlcEJgj3ufgleLqK4Weg>
List-Archive: <https://mailarchive.ietf.org/arch/browse/oauth>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Owner: <mailto:oauth-owner@ietf.org>
List-Post: <mailto:oauth@ietf.org>
List-Subscribe: <mailto:oauth-join@ietf.org>
List-Unsubscribe: <mailto:oauth-leave@ietf.org>
Hi Tim,
Thanks for these well-founded clarifications and references to the standard documents!
Comments inline.
> Am 06.11.2025 um 08:04 schrieb Tim Würtele <tim.wuertele@sec.uni-stuttgart.de>:
>
> 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...
>
Oh, maybe that should be changed in the spec. I thought I read it somewhere but maybe it was just an assumption of myself because that worked well for all AS implementations I have seen so far.
Do you see any reasons why a client sending a token request without providing a valid code_verifier when PKCE has been used in the authorization request is not a legitimate reason to invalidate the authorization code?
> 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).
>
My experience is that this is not true, because many authorization servers identify authoirzation codes in combination with the client_id. This is because the specs tell developers to do so in the last paragraph here: https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1
Greetings,
Jonas
>>
>> 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 <frederik.krogsdal@criipto.com> <mailto:frederik.krogsdal@criipto.com>:
>>>
>>> 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 <jonas.primbs@uni-tuebingen.de <mailto:jonas.primbs@uni-tuebingen.de>> 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
>>>> Tel.: (+49) 7071 / 29-70512
>>>> Mail: jonas.primbs@uni-tuebingen.de <mailto:jonas.primbs@uni-tuebingen.de>
>>>> Web: https://kn.inf.uni-tuebingen.de <https://kn.inf.uni-tuebingen.de/>
>>>> _______________________________________________
>>>> OAuth mailing list -- oauth@ietf.org <mailto:oauth@ietf.org>
>>>> To unsubscribe send an email to oauth-leave@ietf.org <mailto:oauth-leave@ietf.org>
>>
>>
>>
>> _______________________________________________
>> OAuth mailing list -- oauth@ietf.org <mailto:oauth@ietf.org>
>> To unsubscribe send an email to oauth-leave@ietf.org <mailto:oauth-leave@ietf.org>
> --
> Tim Würtele, M.Sc.
> Room V38 2.434
> Institute of Information Security - SEC
> Universität Stuttgart
> Universitätsstraße 38
> D-70569 Stuttgart
> Germany
> Phone: +49 (0) 711 685-88468
> https://sec.uni-stuttgart.de <https://sec.uni-stuttgart.de/>_______________________________________________
> OAuth mailing list -- oauth@ietf.org <mailto:oauth@ietf.org>
> To unsubscribe send an email to oauth-leave@ietf.org <mailto:oauth-leave@ietf.org>
- [OAUTH-WG] Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Neil Madden
- [OAUTH-WG] Re: Browser-Swapping Filip Skokan
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Neil Madden
- [OAUTH-WG] Re: Browser-Swapping Vladimir Dzhuvinov | Connect2id
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Dick Hardt
- [OAUTH-WG] Re: Browser-Swapping Frederik Krogsdal Jacobsen
- [OAUTH-WG] Re: Browser-Swapping Frederik Krogsdal Jacobsen
- [OAUTH-WG] Re: Browser-Swapping Thomas Broyer
- [OAUTH-WG] Re: Browser-Swapping Max Gerber
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Filip Skokan
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Filip Skokan
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Neil Madden
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Tim Würtele
- [OAUTH-WG] Re: Browser-Swapping Max Gerber
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Frederik Krogsdal Jacobsen
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Philippe De Ryck
- [OAUTH-WG] Re: Browser-Swapping Neil Madden
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Aaron Parecki
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Neil Madden
- [OAUTH-WG] Re: Browser-Swapping Aaron Parecki
- [OAUTH-WG] Re: Browser-Swapping Max Gerber
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Frederik Krogsdal Jacobsen
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Frederik Krogsdal Jacobsen
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Frederik Krogsdal Jacobsen
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Philippe De Ryck
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Warren Parad
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Thomas Broyer
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Thomas Broyer
- [OAUTH-WG] Re: Browser-Swapping Will Bartlett
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Logan Widick
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping kcloud
- [OAUTH-WG] Re: Browser-Swapping Aaron Parecki
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Logan Widick
- [OAUTH-WG] Re: Browser-Swapping Primbs, Jonas
- [OAUTH-WG] Re: Browser-Swapping Warren Parad