Return-Path: <wparad@rhosys.ch>
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 9DDC285233C2
	for <oauth@mail2.ietf.org>; Fri,  7 Nov 2025 01:36:38 -0800 (PST)
X-Virus-Scanned: amavisd-new at ietf.org
X-Spam-Flag: NO
X-Spam-Score: -2.099
X-Spam-Level: 
X-Spam-Status: No, score=-2.099 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_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001]
	autolearn=ham autolearn_force=no
Authentication-Results: mail2.ietf.org (amavisd-new); dkim=pass (2048-bit key)
	header.d=rhosys.ch
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 U7Tli0W62dHR for <oauth@mail2.ietf.org>;
	Fri,  7 Nov 2025 01:36:37 -0800 (PST)
Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com
 [IPv6:2a00:1450:4864:20::534])
	(using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)
	 key-exchange X25519 server-signature ECDSA (P-256) server-digest SHA256)
	(No client certificate requested)
	by mail2.ietf.org (Postfix) with ESMTPS id 6194A8523332
	for <oauth@ietf.org>; Fri,  7 Nov 2025 01:36:30 -0800 (PST)
Received: by mail-ed1-x534.google.com with SMTP id
 4fb4d7f45d1cf-64074f01a6eso948310a12.2
        for <oauth@ietf.org>; Fri, 07 Nov 2025 01:36:30 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=rhosys.ch; s=google2024; t=1762508189; x=1763112989; darn=ietf.org;
        h=cc:to:subject:message-id:date:from:in-reply-to:references
         :mime-version:from:to:cc:subject:date:message-id:reply-to;
        bh=1iiPS9Q0TUVWRm7JUzunXhV8qN+OavETNtejkIYeNGo=;
        b=Cy4++vXuNvVk+gJ9FATdg2H8yLcPKEOhX9CYJ67dsQ1XisrhM8IzGaDnWkVDPjQtSm
         uzTzJP8heK5P/Xj4Qq+F1iau5BB2zTKJ4K/OKRyWSRpXrigsA4Mz4+kPUKnosh8u1bN4
         WnUs5C7inh0fKgIqd1PXo1dehKHUkelr/2zDKYplVCKR0If0jSYTyh/0JyaIzMuqT8nd
         31oTojDJ48VJrB5u6AVApTbDVpFT71BDmiAhJacSYXc1jvvbSXjSjzw777uv+zan4ZcL
         3ZRnybOZ7FDc2tnaabRL4Wge7up2vWiksq37zGun07YoO9LmlDOTxQzIUgD2mme37bxH
         1TWQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1762508189; x=1763112989;
        h=cc:to:subject:message-id:date:from:in-reply-to:references
         :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date
         :message-id:reply-to;
        bh=1iiPS9Q0TUVWRm7JUzunXhV8qN+OavETNtejkIYeNGo=;
        b=WgVV75YZIXDmuxKe5vaq8ZWD+SGHSC6uoWZQxdvnQ6a+rWqRa83L+ZrCbNdT+GyVIy
         eTWEBoy33mGVOy38UxYhFQEBC5UjXOJhTzpjJFbLd2PLJpLgGtsIXzEWlveKzalNJzzh
         ebeQ9FVwY7z0yRvPjJqxS+wE4c8lBs4WEzzJ1C5f3JTqyZ8DbJ4h3oTr5r9Oky61deWT
         yX9HqFjiaRvKazmFadTGMvACawmESX3CKt1ojJRHaT7nI9vtT/AcHdPs8qKBMTjnw2tq
         xmYv6YgLbzI5kEB2/r6TX7cCQOmD/PQ3tKpnlziurRfr0ci/lEj5VuivplsKW335PgBe
         hLBg==
X-Forwarded-Encrypted: i=1;
 AJvYcCU+t8uNlpS6Uj+sRkI/zUCD3vRJT1hzhyXZWYg6E+RHnLtvUyf32pFhasnyjW+8CecSJjRVZg==@ietf.org
X-Gm-Message-State: AOJu0Yw30OfIKHBNJyw2jP9QHNDz+ktQHgYtN6nXqd2j7+ivNcn91nVL
	4jRFl9ct2DGpGATesQaWHAXM7u7OHqVkPeoCPP0AJ9ggs+vg2DuMp8P+6dODJ5JaT/h0EWj+703
	MSOIOV8+tg5l7PSG3jeuh0chhIe3g12cvEAVpgSI82XPZnmicOJy6j+Yo
X-Gm-Gg: ASbGnctrD5QuMny+VnebaWZXWLeVpySuNxycGBsLGihQioSV1zjbtix2T2+N455aCAn
	Wnbae1ommgWJv5keUBJ7QXBEZPLNnICeA+EpPLlkSiWcKgUXXUK7hFeobSupp9TAzXQy+6VdkJt
	BMYgo+arolem2+Vx1w+FFjxMJfHdqoxEpAHtxXMQAnEtt3eXZvctwVoofVW+g98taYPS+G9SRO9
	ekitUx4kNz0n/zsGGTa8krI+z0XZthJgS/AiadnYufy4nRxa3B46uDkSwU5MEWL06NTosNaiSnW
	NrkKNEjMmkjuM1DAyGEejZr9BJsi+u86HGKin3ZWBLkY9myQZF2IAh4CipnkNeFRIJE0xMvHwmZ
	ShEZa+YcolvuF
X-Google-Smtp-Source: 
 AGHT+IGlAt7RuxmG+zPRg+/63nebRPRY+8n/7YKKMX15Vq/v9lZkeTWU5SilDiLmbkFVvQVel1MR5kB8qw34jwG2oUo=
X-Received: by 2002:a05:6402:13c8:b0:640:eea7:c95b with SMTP id
 4fb4d7f45d1cf-6413eedc111mr2617467a12.6.1762508189086; Fri, 07 Nov 2025
 01:36:29 -0800 (PST)
MIME-Version: 1.0
References: 
 <CAGBSGjoVRxszkD967my2i53VfsXLr+b1ExO4WChtGyYmMQumuA@mail.gmail.com>
 <16E4A2B8-416A-42F7-B76A-6F4B65138AF9@runbox.eu>
 <CAGBSGjpqY9WDE0L0R+jR-nmsbNO8MymBfraVfu104ywyY91e4w@mail.gmail.com>
 <CAMQcq-YMtu5eHHgv6+BwgLHtJq5uONX8dYTpWjXConrKN3WDRQ@mail.gmail.com>
In-Reply-To: 
 <CAMQcq-YMtu5eHHgv6+BwgLHtJq5uONX8dYTpWjXConrKN3WDRQ@mail.gmail.com>
From: Warren Parad <wparad@rhosys.ch>
Date: Fri, 7 Nov 2025 10:36:17 +0100
X-Gm-Features: AWmQ_blNB_giycDwDq2bGX-lDD1MQ8yGsUnUAwOPohQcXMrJo_8p7xRYVHRTWxE
Message-ID: 
 <CAJot-L3=gkpT7XBsjmzbfoTfFr68BDmyR-+wqrAJf4sXY1CSdg@mail.gmail.com>
To: Frederik Krogsdal Jacobsen
 <frederik.krogsdal=40criipto.com@dmarc.ietf.org>
Content-Type: multipart/alternative; boundary="0000000000008649a60642fdeaad"
Message-ID-Hash: QE4DN4C5CZWRVHPTVVGRGSBXKIKYNRWM
X-Message-ID-Hash: QE4DN4C5CZWRVHPTVVGRGSBXKIKYNRWM
X-MailFrom: wparad@rhosys.ch
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: Aaron Parecki <aaron=40parecki.com@dmarc.ietf.org>, oauth@ietf.org
X-Mailman-Version: 3.3.9rc6
Precedence: list
Subject: =?utf-8?q?=5BOAUTH-WG=5D_Re=3A_Browser-Swapping?=
List-Id: OAUTH WG <oauth.ietf.org>
Archived-At: 
 <https://mailarchive.ietf.org/arch/msg/oauth/mUCeZbWS44z0DIYKbCeG1lsNULI>
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>

--0000000000008649a60642fdeaad
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

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=E2=80=AFAM Frederik Krogsdal Jacobsen
<frederik.krogsdal=3D40criipto.com@dmarc.ietf.org> 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 t=
o
> 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 probab=
ly
> off-topic for this thread.
>
> Cheers,
> Frederik
>
> On Thu, 6 Nov 2025 at 17:43, Aaron Parecki <aaron=3D
> 40parecki.com@dmarc.ietf.org> 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=E2=80=AFAM Neil Madden <neil.e.madden@runbo=
x.eu>
>> wrote:
>>
>>> The only issue I have with deprecating state for CSRF protection is tha=
t
>>> the client has no way in general to know if the AS supports (in fact
>>> enforces) PKCE. If it doesn=E2=80=99t, then we may end up with no CSRF =
protection
>>> at all, and clients being vulnerable to Login CSRF/session fixation-lik=
e
>>> attacks.
>>>
>>> =E2=80=94 Neil
>>>
>>> On 6 Nov 2025, at 16:12, Aaron Parecki <aaron@parecki.com> wrote:
>>>
>>> =EF=BB=BF
>>>
>>> S1 seems like the cleanest solution to me. I think this should also com=
e
>>> with language officially deprecating "state" for CSRF protection like
>>> Philippe said.
>>>
>>>
>>> On Thu, Nov 6, 2025 at 10:59=E2=80=AFAM Primbs, Jonas <
>>> jonas.primbs@uni-tuebingen.de> wrote:
>>>
>>>> Let=E2=80=99s 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 <neil.e.madden@runbox.eu>:
>>>>
>>>> This makes me wonder if we could in fact have a special client_id valu=
e
>>>> 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 ri=
ght
>>>> thing for most ASes, as Tim mentions. Something like
>>>> client_id=3Dcsrf_detected_revoke_please.
>>>>
>>>> On 6 Nov 2025, at 13:04, Tim W=C3=BCrtele <tim.wuertele@sec.uni-stuttg=
art.de>
>>>> 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 reque=
st
>>>> with the same authorization code afterwards might ensure that the issu=
ed
>>>> 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 r=
evoke
>>>> associated tokens). In 10.5, we have "Authorization codes MUST be [...=
]
>>>> single-use." - without being explicit about whether this statement app=
lies
>>>> 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 sentence=
s 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 t=
here
>>>> 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, verif=
y
>>>> 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 abou=
t
>>>> 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 bee=
n
>>>> 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 no=
t
>>>> 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 detec=
ting
>>>> the attack - and if the AS follows the SHOULD-advise from 6749, any to=
kens
>>>> issued for that code would then immediately be invalidated, which of c=
ourse
>>>> 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
>>>> <frederik.krogsdal@criipto.com> <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 respo=
nse
>>>> when the initial CSRF is detected.
>>>> This would of course only work with an AS that correctly implements th=
e
>>>> 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 t=
o
>>>> 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-authentic=
ation-core-1_0.html
>>>>
>>>> On Tue, 4 Nov 2025 at 05:10, Primbs, Jonas <
>>>> jonas.primbs@uni-tuebingen.de> wrote:
>>>>
>>>>> Hi all,
>>>>>
>>>>> according to Aaron=E2=80=99s recommendation, I have created a PR for =
OAuth
>>>>> 2.1: https://github.com/oauth-wg/oauth-v2-1/pull/230
>>>>>
>>>>> It references OpenID Connect=E2=80=99s response modes (fragment and f=
orm_post)
>>>>> as solutions for Browser-Swapping attacks, which I have presented in
>>>>> today=E2=80=99s OAuth WG meeting.
>>>>> If you have missed my presentation, but are still interested, here ar=
e
>>>>> my slides:
>>>>> https://datatracker.ietf.org/meeting/124/materials/slides-124-oauth-s=
essa-browser-swapping-01
>>>>>
>>>>> I=E2=80=99m interested in your feedback on this first draft, which cu=
rrently
>>>>> covers only recommendation #2 from my slides, because this is probabl=
y 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 =E2=80=9ENo, PKCE=E2=80=A6=
=E2=80=9C t-shirts for the rest
>>>>> of the week, so that it=E2=80=99s easier for you to find me. @Brian &=
 Mike: I have
>>>>> learned from the best ;-)
>>>>>
>>>>> Greetings,
>>>>> Jonas
>>>>>
>>>>>
>>>>> Jonas Primbs M.Sc.
>>>>> University of T=C3=BCbingen
>>>>> Faculty of Science
>>>>> Department of Computer Science
>>>>> Sand 13, 72076 T=C3=BCbingen, Germany
>>>>> <https://www.google.com/maps/search/Sand+13,+72076+T%C3%BCbingen,+Ger=
many?entry=3Dgmail&source=3Dg>
>>>>> Tel.: (+49) 7071 / 29-70512
>>>>> Mail: jonas.primbs@uni-tuebingen.de
>>>>> Web: https://kn.inf.uni-tuebingen.de
>>>>>
>>>>> _______________________________________________
>>>>> OAuth mailing list -- oauth@ietf.org
>>>>> To unsubscribe send an email to oauth-leave@ietf.org
>>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> OAuth mailing list -- oauth@ietf.org
>>>> To unsubscribe send an email to oauth-leave@ietf.org
>>>>
>>>> --
>>>> Tim W=C3=BCrtele, M.Sc.
>>>> Room V38 2.434
>>>> Institute of Information Security - SEC
>>>> Universit=C3=A4t StuttgartUniversit=C3=A4tsstra=C3=9Fe 38 <https://www=
.google.com/maps/search/Universit%C3%A4tsstra%C3%9Fe+38?entry=3Dgmail&sourc=
e=3Dg>
>>>> D-70569 Stuttgart
>>>> Germany
>>>> Phone: +49 (0) 711 685-88468https://sec.uni-stuttgart.de
>>>>
>>>> _______________________________________________
>>>> OAuth mailing list -- oauth@ietf.org
>>>> To unsubscribe send an email to oauth-leave@ietf.org
>>>>
>>>>
>>>> _______________________________________________
>>>> OAuth mailing list -- oauth@ietf.org
>>>> To unsubscribe send an email to oauth-leave@ietf.org
>>>>
>>>>
>>>> _______________________________________________
>>>> OAuth mailing list -- oauth@ietf.org
>>>> To unsubscribe send an email to oauth-leave@ietf.org
>>>>
>>> _______________________________________________
>> OAuth mailing list -- oauth@ietf.org
>> To unsubscribe send an email to oauth-leave@ietf.org
>>
> _______________________________________________
> OAuth mailing list -- oauth@ietf.org
> To unsubscribe send an email to oauth-leave@ietf.org
>

--0000000000008649a60642fdeaad
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">If PKCE fixes a problem, then that&#39;s the solution to t=
he problem, it doesn&#39;t make sense to add a &quot;standard alternative&q=
uot; because of that. State, never existed for CSRF protection, that was th=
e nonce, which has been deprecated with the introduction of PKCE, so neithe=
r S1 or S3 are relevant right?<br><br>I&#39;m missing the value in a &quot;=
revocation mechanism&quot; for authorization codes, if the attacker can blo=
ck requests to the AS, then how would the revocation mechanism end up getti=
ng called? What would trigger that?</div><br><div class=3D"gmail_quote gmai=
l_quote_container"><div dir=3D"ltr" class=3D"gmail_attr">On Fri, Nov 7, 202=
5 at 10:08=E2=80=AFAM Frederik Krogsdal Jacobsen &lt;frederik.krogsdal=3D<a=
 href=3D"mailto:40criipto.com@dmarc.ietf.org">40criipto.com@dmarc.ietf.org<=
/a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><=
div dir=3D"ltr">I think S1 is the best bet for a standard solution to menti=
on in OAuth 2.1.<div>State could be deprecated as a solution for CSRF prote=
ction, but it is still useful for other things.</div><div><br></div><div>An=
 AS could individually recommend variations on S2 if they do not plan to im=
plement PKCE.</div><div><br></div><div>I still think that a more general ca=
ncellation/revocation mechanism as mentioned by Max would be useful (also f=
or other grant types such as auth_req_ids from CIBA), but I understand that=
 introducing this is probably off-topic for this thread.</div><div><br></di=
v><div>Cheers,<br>Frederik</div></div><br><div class=3D"gmail_quote"><div d=
ir=3D"ltr" class=3D"gmail_attr">On Thu, 6 Nov 2025 at 17:43, Aaron Parecki =
&lt;aaron=3D<a href=3D"mailto:40parecki.com@dmarc.ietf.org" target=3D"_blan=
k">40parecki.com@dmarc.ietf.org</a>&gt; wrote:<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rg=
b(204,204,204);padding-left:1ex"><div dir=3D"auto">I think that&#39;s cover=
ed as part of the discussion of how a client and AS know that each other ar=
e speaking OAuth 2.1 vs 2.0.=C2=A0</div><div dir=3D"auto"><br></div><div><b=
r><div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Thu, =
Nov 6, 2025 at 11:40=E2=80=AFAM Neil Madden &lt;<a href=3D"mailto:neil.e.ma=
dden@runbox.eu" target=3D"_blank">neil.e.madden@runbox.eu</a>&gt; wrote:<br=
></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"auto">=
<div dir=3D"ltr"></div><div dir=3D"ltr">The only issue I have with deprecat=
ing state for CSRF protection is that the client has no way in general to k=
now if the AS supports (in fact enforces) PKCE. If it doesn=E2=80=99t, then=
 we may end up with no CSRF protection at all, and clients being vulnerable=
 to Login CSRF/session fixation-like attacks.=C2=A0</div><div dir=3D"ltr"><=
br></div><div dir=3D"ltr">=E2=80=94 Neil</div><div dir=3D"ltr"><br><blockqu=
ote type=3D"cite">On 6 Nov 2025, at 16:12, Aaron Parecki &lt;<a href=3D"mai=
lto:aaron@parecki.com" target=3D"_blank">aaron@parecki.com</a>&gt; wrote:<b=
r><br></blockquote></div><blockquote type=3D"cite"><div dir=3D"ltr">=EF=BB=
=BF</div></blockquote></div><div dir=3D"auto"><blockquote type=3D"cite"><di=
v dir=3D"ltr"><div dir=3D"ltr">S1 seems like the cleanest solution to me. I=
 think this should also come with language officially deprecating &quot;sta=
te&quot; for CSRF protection like Philippe said.<div><br></div></div><br><d=
iv class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Thu, Nov =
6, 2025 at 10:59=E2=80=AFAM Primbs, Jonas &lt;<a href=3D"mailto:jonas.primb=
s@uni-tuebingen.de" target=3D"_blank">jonas.primbs@uni-tuebingen.de</a>&gt;=
 wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>Let=
=E2=80=99s collect auth code revocation solutions:<div><br></div><div>S1: E=
nforce PKCE + normal token request but without code_verifier.</div><div>+ N=
o additional endpoints</div><div>+ Works for many existing implementations<=
/div><div>- AS must implement PKCE and enforce it for all clients (bad for =
testing)</div><div><br></div><div>S2: Use specific client_id at the token e=
ndpoint.</div><div>+ No additional endpoints</div><div>- =C2=A0A bit hacky<=
/div><div><br></div><div>S3: Specify a dedicated token endpoint</div><div>+=
 One official way</div><div>- Huge changes required</div><div><div><br></di=
v><div>S4: Use token revocation endpoint</div><div>+ Just an extension of e=
xisting endpoints</div><div>- Client cannot know if the AS implements this<=
/div><div><br></div><div><br></div><div><br><blockquote type=3D"cite"><div>=
Am 06.11.2025 um 08:24 schrieb Neil Madden &lt;<a href=3D"mailto:neil.e.mad=
den@runbox.eu" target=3D"_blank">neil.e.madden@runbox.eu</a>&gt;:</div><br>=
<div>
<div>This makes me wonder if we could in fact have a special client_id valu=
e that indicates that the AS should revoke the code (and any tokens if issu=
es)? It&#39;s a bit hacky but has the advantage of likely doing the right t=
hing for most ASes, as Tim mentions. Something like client_id=3Dcsrf_detect=
ed_revoke_please.<br id=3D"m_-5703508952399800982m_6846576542695170099m_469=
5593859186459781m_-828033087976261327lineBreakAtBeginningOfMessage"><div><b=
r><blockquote type=3D"cite"><div>On 6 Nov 2025, at 13:04, Tim W=C3=BCrtele =
&lt;<a href=3D"mailto:tim.wuertele@sec.uni-stuttgart.de" target=3D"_blank">=
tim.wuertele@sec.uni-stuttgart.de</a>&gt; wrote:</div><br><div>

 =20
   =20
 =20
  <div><p>Hi Jonas,</p><p>a minor (but imho relevant to this discussion) ni=
tpicking inline.</p><p>Best,</p><p>Tim<br>
    </p>
    <div>On 05.11.25 16:25, Primbs, Jonas wrote:<br>
    </div>
    <blockquote type=3D"cite">Hi
      Frederik,
      <div><br>
      </div>
      <div>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.</div>
      <div>However, I am not sure=C2=A0what 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).</div>
      <div>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.</div>
      <div><br>
      </div>
      <div>Again, this might fail=C2=A0if the client faces any issues. So I
        prefer a standardized authorization code invalidation mechanism.</d=
iv>
      <div>One opportunity here, which is already standardized, is
        enforcing PKCE and sending no code_verifier in the token request
        intentionally.</div>
    </blockquote><p>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:</p><p>RFC 6749 says (in 4.x) the c=
lient 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 &quot;Authorizatio=
n
      codes MUST be [...] single-use.&quot; - without being explicit about
      whether this statement applies to the &quot;user&quot; of the code (t=
he
      client), the AS, or both; although I&#39;d argue that interpreting
      this as &quot;the client may only use it once&quot; is a justifiable
      interpretation (especially because the subsequent sentences in
      10.5 also just repeat the SHOULD statement from 4.x).</p><p>RFC 6819,=
 4.4.1.1 does say &quot;The authorization server should
      enforce a one-time usage restriction (see Section 5.1.5.4).&quot;; bu=
t
      the language there is not normative (&quot;may&quot;, &quot;may want&=
quot;, ...); the
      same is true for 5.2.1.1.</p><p>OIDC is even more vague (3.1.3.2): Th=
e AS MUST ... &quot;If possible,
      verify that the Authorization Code has not been previously used.&quot=
;</p><p>... just a few examples.<br>
    </p><p>Using PKCE does not change this ambiguity; RFC 7636 does not tal=
k
      about code invalidation at all.<br>
    </p><p><br>
    </p><p>In other words: An error response from the AS&#39;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 &quot;on purpose&quot;, or due to CAP). Of
      course, one might argue that these are not standards-compliant,
      but I don&#39;t think there&#39;s a very strong case for that claim, =
given
      the (historically) inaccurate wording...</p><p>That being said: If I =
were to implement a client today, I would
      make such a &quot;wrong&quot; 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.</p><p>Side note: This &quot;best effort=
&quot; 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 &quot;did the AS implement
      6749&#39;s SHOULD&quot; perspective).<br>
    </p>
    <blockquote type=3D"cite">
      <div><br>
      </div>
      <div>If there already is a spec for that in CIBA, we should
        include or at least reference this in the OAuth 2.1 spec.</div>
      <div><br>
      </div>
      <div>Greetings,</div>
      <div>Jonas</div>
      <div><br id=3D"m_-5703508952399800982m_6846576542695170099m_469559385=
9186459781m_-828033087976261327lineBreakAtBeginningOfMessage">
        <div><br>
          <blockquote type=3D"cite">
            <div>Am 05.11.2025 um 04:02 schrieb Frederik Krogsdal
              Jacobsen <a href=3D"mailto:frederik.krogsdal@criipto.com" tar=
get=3D"_blank">&lt;frederik.krogsdal@criipto.com&gt;</a>:</div>
            <br>
            <div>
              <div dir=3D"ltr">Hi Jonas,
                <div><br>
                </div>
                <div>Thanks for the detailed explanation of the attack
                  and possible mitigations.</div>
                <div><br>
                </div>
                <div>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.</div>
                <div>This would of course only work with an AS that
                  correctly implements the security guidance in section
                  10.5 of RFC 6749: &quot;A<span>uthorization codes MUST be
                    short lived and single-use.&quot;</span></div>
                <div><span>The main problem with this approach is that
                    it is a bit confusing to explain.</span></div>
                <div><span><br>
                  </span></div>
                <div><span>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
                    &quot;cancel request&quot; that uses up a code without
                    returning a token.</span></div>
                <div><span>Defining such a request might also make the
                    approach easier to explain.</span></div>
                <div><span>In fact, many OIDC providers already define
                    custom &quot;cancel&quot; requests to mitigate phishing=
. A
                    &quot;cancel&quot; request might also be useful for Ope=
nID
                    CIBA [1].</span></div>
                <div><span><br>
                  </span></div>
                <div><span>Do you see any problems with this approach?</spa=
n></div>
                <div><br>
                </div>
                <div><span>Cheers,<br>
                    Frederik</span></div>
                <div><span><br>
                  </span></div>
                <div><span>[1]:=C2=A0</span><a href=3D"https://openid.net/s=
pecs/openid-client-initiated-backchannel-authentication-core-1_0.html" targ=
et=3D"_blank">https://openid.net/specs/openid-client-initiated-backchannel-=
authentication-core-1_0.html</a></div>
              </div>
              <br>
              <div class=3D"gmail_quote">
                <div dir=3D"ltr" class=3D"gmail_attr">On Tue, 4 Nov 2025 at
                  05:10, Primbs, Jonas &lt;<a href=3D"mailto:jonas.primbs@u=
ni-tuebingen.de" target=3D"_blank">jonas.primbs@uni-tuebingen.de</a>&gt;
                  wrote:<br>
                </div>
                <blockquote class=3D"gmail_quote">
                  <div>Hi all,
                    <div><br>
                    </div>
                    <div>according to Aaron=E2=80=99s recommendation, I hav=
e
                      created a PR for OAuth 2.1:=C2=A0<a href=3D"https://g=
ithub.com/oauth-wg/oauth-v2-1/pull/230" target=3D"_blank">https://github.co=
m/oauth-wg/oauth-v2-1/pull/230</a></div>
                    <div><br>
                    </div>
                    <div>It references OpenID Connect=E2=80=99s response mo=
des
                      (fragment and form_post) as solutions for
                      Browser-Swapping attacks, which I have presented
                      in today=E2=80=99s OAuth WG meeting.</div>
                    <div>If you=C2=A0have missed my presentation, but are
                      still interested, here are my slides:=C2=A0<a href=3D=
"https://datatracker.ietf.org/meeting/124/materials/slides-124-oauth-sessa-=
browser-swapping-01" target=3D"_blank">https://datatracker.ietf.org/meeting=
/124/materials/slides-124-oauth-sessa-browser-swapping-01</a></div>
                    <div><br>
                    </div>
                    <div>I=E2=80=99m interested in your feedback on this fi=
rst
                      draft, which currently covers only recommendation
                      #2 from my slides, because this is probably the
                      least controversial change.</div>
                    If you are attending onsite, also feel free to speak
                    to me in the hallway. My company gave me enough of
                    the =E2=80=9ENo, PKCE=E2=80=A6=E2=80=9C t-shirts for th=
e rest of the week,
                    so that it=E2=80=99s easier for you to find me. @Brian =
&amp;
                    Mike: I have learned from the best ;-)
                    <div><br>
                      Greetings,
                      <div>Jonas</div>
                      <div><br>
                        <br>
                        <div>
                          <div dir=3D"auto">
                            <div>Jonas Primbs M.Sc.</div>
                            <div>University of T=C3=BCbingen</div>
                            <div>Faculty of Science</div>
                            <div>Department of Computer Science</div>
                            <div><a href=3D"https://www.google.com/maps/sea=
rch/Sand+13,+72076+T%C3%BCbingen,+Germany?entry=3Dgmail&amp;source=3Dg" tar=
get=3D"_blank">Sand 13, 72076 T=C3=BCbingen, Germany</a></div>
                            <div>Tel.: (+49) 7071 / 29-70512</div>
                            <div>Mail: <a href=3D"mailto:jonas.primbs@uni-t=
uebingen.de" target=3D"_blank">jonas.primbs@uni-tuebingen.de</a></div>
                            <div>Web: <a href=3D"https://kn.inf.uni-tuebing=
en.de/" target=3D"_blank">https://kn.inf.uni-tuebingen.de</a></div>
                          </div>
                        </div>
                        <br>
                      </div>
                    </div>
                  </div>
                  _______________________________________________<br>
                  OAuth mailing list -- <a href=3D"mailto:oauth@ietf.org" t=
arget=3D"_blank">oauth@ietf.org</a><br>
                  To unsubscribe send an email to <a href=3D"mailto:oauth-l=
eave@ietf.org" target=3D"_blank">oauth-leave@ietf.org</a><br>
                </blockquote>
              </div>
            </div>
          </blockquote>
        </div>
        <br>
      </div>
      <br>
      <fieldset></fieldset>
      <pre>_______________________________________________
OAuth mailing list -- <a href=3D"mailto:oauth@ietf.org" target=3D"_blank">o=
auth@ietf.org</a>
To unsubscribe send an email to <a href=3D"mailto:oauth-leave@ietf.org" tar=
get=3D"_blank">oauth-leave@ietf.org</a>
</pre>
    </blockquote>
    <pre cols=3D"72">--=20
Tim W=C3=BCrtele, M.Sc.
Room V38 2.434
Institute of Information Security - SEC
Universit=C3=A4t Stuttgart
<a href=3D"https://www.google.com/maps/search/Universit%C3%A4tsstra%C3%9Fe+=
38?entry=3Dgmail&amp;source=3Dg" target=3D"_blank">Universit=C3=A4tsstra=C3=
=9Fe 38</a>
D-70569 Stuttgart
Germany
Phone: +49 (0) 711 685-88468
<a href=3D"https://sec.uni-stuttgart.de/" target=3D"_blank">https://sec.uni=
-stuttgart.de</a></pre>
  </div>

_______________________________________________<br>OAuth mailing list -- <a=
 href=3D"mailto:oauth@ietf.org" target=3D"_blank">oauth@ietf.org</a><br>To =
unsubscribe send an email to <a href=3D"mailto:oauth-leave@ietf.org" target=
=3D"_blank">oauth-leave@ietf.org</a><br></div></blockquote></div><br></div>=
_______________________________________________<br>OAuth mailing list -- <a=
 href=3D"mailto:oauth@ietf.org" target=3D"_blank">oauth@ietf.org</a><br>To =
unsubscribe send an email to <a href=3D"mailto:oauth-leave@ietf.org" target=
=3D"_blank">oauth-leave@ietf.org</a><br></div></blockquote></div><br></div>=
</div>_______________________________________________<br>
OAuth mailing list -- <a href=3D"mailto:oauth@ietf.org" target=3D"_blank">o=
auth@ietf.org</a><br>
To unsubscribe send an email to <a href=3D"mailto:oauth-leave@ietf.org" tar=
get=3D"_blank">oauth-leave@ietf.org</a><br>
</blockquote></div>
</div></blockquote></div></blockquote></div></div>
_______________________________________________<br>
OAuth mailing list -- <a href=3D"mailto:oauth@ietf.org" target=3D"_blank">o=
auth@ietf.org</a><br>
To unsubscribe send an email to <a href=3D"mailto:oauth-leave@ietf.org" tar=
get=3D"_blank">oauth-leave@ietf.org</a><br>
</blockquote></div>
_______________________________________________<br>
OAuth mailing list -- <a href=3D"mailto:oauth@ietf.org" target=3D"_blank">o=
auth@ietf.org</a><br>
To unsubscribe send an email to <a href=3D"mailto:oauth-leave@ietf.org" tar=
get=3D"_blank">oauth-leave@ietf.org</a><br>
</blockquote></div>

--0000000000008649a60642fdeaad--

