Return-Path: <t.broyer@gmail.com>
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 300899062F4B
	for <oauth@mail2.ietf.org>; Tue, 25 Nov 2025 09:29:05 -0800 (PST)
X-Virus-Scanned: amavisd-new at ietf.org
X-Spam-Flag: NO
X-Spam-Score: -2.098
X-Spam-Level: 
X-Spam-Status: No, score=-2.098 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, FREEMAIL_FROM=0.001,
	HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,
	SPF_PASS=-0.001] autolearn=unavailable autolearn_force=no
Authentication-Results: mail2.ietf.org (amavisd-new); dkim=pass (2048-bit key)
	header.d=gmail.com
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 82dbyGLN_z0u for <oauth@mail2.ietf.org>;
	Tue, 25 Nov 2025 09:29:03 -0800 (PST)
Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com
 [IPv6:2607:f8b0:4864:20::1036])
	(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 F33F59062DD6
	for <oauth@ietf.org>; Tue, 25 Nov 2025 09:27:51 -0800 (PST)
Received: by mail-pj1-x1036.google.com with SMTP id
 98e67ed59e1d1-3436a97f092so7169976a91.3
        for <oauth@ietf.org>; Tue, 25 Nov 2025 09:27:51 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20230601; t=1764091671; x=1764696471; 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=ga70Nos+z7c5Q4f5FeA5/ObPVcGskZMmrJvZ2HYCh14=;
        b=WfJ7OoSVTYEW7UO2MbL1rjfmUCLmztgH2j0kvQ+tD1ClzC8mir04sojfqRL59Fjxj4
         tnyDqyEhD2aUshAeBIPRfc3xbbbq6B+jz5Om4xPl7HV8RMbnWMVthfIICEV0kYruB4kM
         WoPjCn6fYbsWExNVl8AYPucEpUJB2zxwzIut6MldTeSZaSoFevkAWI0uZBIywUZzPZs8
         MTobmDck07690s6OAkmRMfysOyT986GTpnH2olZP4uIwRhI6Sd5SyO1uMlUDDe99AHcV
         t6cZSq/kZHCDHjp7lvlqPgJk7PZY+Uyt+hHka2Ar4Bg5JKscbRx3uqODc/88eiLFcNtx
         1bCA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1764091671; x=1764696471;
        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=ga70Nos+z7c5Q4f5FeA5/ObPVcGskZMmrJvZ2HYCh14=;
        b=YkFz3tprNCQ/yUVYu10Wy+wbJf1WqEUH4X9ltT0vxGxsapPPR40sf03xk/fTwcngLy
         Wfb+lflwsjh8PFvlxuyVyxWORfZVYN7XaM+awUNgKSKwUHrsPCqRrhSMXXlZujdH8Puy
         ZPuZOT4G7D5WlG+u8jhELp89Wr0DmTa88ptf0lqpqRAq4DpO2cIfo4LsxHpc5Ar5fSum
         QVL3vYESSuJPMBY32lh631tlcn4LcAwJUeEoyUqBrkBs8KrsWoT5q5ZsGR24XVLRSfVd
         Es2LilYY4T9BHOQDbSNHCD+rHCtYbcx9jhCDE2+k7OyCSEuiROMKUQ0R4OKUy6Rhdps1
         1g3w==
X-Forwarded-Encrypted: i=1;
 AJvYcCW8ECyhMLF0eTrz3XdxmgAAHVd+lQp9VnAQIVnNHIYE4AafpsOHbmAdceqg5406usO+aaj1EA==@ietf.org
X-Gm-Message-State: AOJu0YzBhznSNwqYHK2sf4sF66bdyu0JAayIQ7h5IwrGiap6hN8J+JH6
	qmkrhzuptlSJcU1kgGVtRTQml2Hm/wmp+pAN7dwGwcuh15XYzir+lC3xJ/cRY+4mXI2pgnNfAqF
	KTlGeaMkDDoAp6ZuuIpN+/21l+Lm8TvmTOmYB
X-Gm-Gg: ASbGncuYlTvbDWTfKuy3wwxAoHYent9KUW9Doc/YG9N5nWcuq8jiqDFhMelEU2y4tqY
	YacaYh3jVEJPa7mnQ8UNDsC81L0l2tlu5yF8kFTeJt5jrHevpNdA98daN0sO7+//yPpCdaLWJAc
	hEmDmUkTYyPFosA+Ln4UcQA6wQDhqat4nrkSTH0Tq9jEps0QarUm4WvIvEBS27FX1PdMnPUf8Vs
	lNQ+cctzBKcJQntC9MHi+eVuleKpS8JFQaVIewwkUdTQdo4zwa0lQ==
X-Google-Smtp-Source: 
 AGHT+IHA03Rf1ZB1TjvmjV4iDdfALxepA4jPkd+qj8dhx4xn1623yZfmsTfjXeIZWJPf4eb11RvqkgIhFxfv+k/K5KM=
X-Received: by 2002:a17:90b:2f0c:b0:340:c179:3657 with SMTP id
 98e67ed59e1d1-3475ed6afd5mr3850140a91.33.1764091670996; Tue, 25 Nov 2025
 09:27:50 -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>
 <CAJot-L3=gkpT7XBsjmzbfoTfFr68BDmyR-+wqrAJf4sXY1CSdg@mail.gmail.com>
 <CAMQcq-aVPGbgHFZH6CaVDSZW4pcCvdeka=go9BVGKeqchF_GnA@mail.gmail.com>
 <9B9C0226-CC50-4810-9A18-CEF2C5B8537A@pragmaticwebsecurity.com>
In-Reply-To: <9B9C0226-CC50-4810-9A18-CEF2C5B8537A@pragmaticwebsecurity.com>
From: Thomas Broyer <t.broyer@gmail.com>
Date: Tue, 25 Nov 2025 18:27:39 +0100
X-Gm-Features: AWmQ_bn9yu2f216ymR0aGc79RR7hwfYzCUm4AEiVIfgX-dlsTZBsn9HzzrcoCns
Message-ID: 
 <CAEayHEN9zXNU+KwE-C6VzqVgxLHxW_FT4tsQXs52aKtcOB963w@mail.gmail.com>
To: Philippe De Ryck <philippe@pragmaticwebsecurity.com>
Content-Type: multipart/alternative; boundary="00000000000066aa3606446e99e5"
Message-ID-Hash: BP7KNMF6ZPTF7MIL6L2GKASMM5UMBXFU
X-Message-ID-Hash: BP7KNMF6ZPTF7MIL6L2GKASMM5UMBXFU
X-MailFrom: t.broyer@gmail.com
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: Frederik Krogsdal Jacobsen
 <frederik.krogsdal=40criipto.com@dmarc.ietf.org>,
 Warren Parad <wparad=40rhosys.ch@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/juzJwavYWL-ju677dNWrGFXL0zc>
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>

--00000000000066aa3606446e99e5
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hi all, re-upping that conversation as a client and client library
developer (OIDC relying party actually)

Do we all agree that the specific scenario where authorization codes leak
through near real-time access to access logs can be mitigated by always
exchanging the authorization code, even when CSRF is suspected? (absence of
or non-matching state; assuming a conformant AS/IdP that has single-use
authorization codes)
response_mode=3Dform_post can also work but has severe implications wrt
cookies (requires either using SameSite=3DNone cookies to store
"authentication state" between the redirects, or running the AS/IdP and the
application "same-site"; Chromium has had a "temporary" Lax+POST mitigation
that also allows this to work:
https://www.chromium.org/updates/same-site/faq/#q-what-is-the-lax-post-miti=
gation
)

And the other scenarios (brought in another thread) where the authorization
code leaks through a downgrade to response_mode=3Dfragment, or the victim
sharing the URL (with authorization code) following an error, can be
mitigated by always redirecting, even (particularly) in case of errors, to
remove any code from the URL? (I chose to redirect to the same callback
endpoint but with an error=3D, using a custom error value for cases like
missing input =E2=80=93likely a response_mode=3Dfragment downgrade=E2=80=93=
 or missing
session state =E2=80=93i.e. no cookies=E2=80=93, and always including a has=
h in the
redirect URL =E2=80=93I use the same error=3D=E2=80=93 to remove any author=
ization code from
a response_mode=3Dfragment downgrade)

AFAICT, hardly anything can be done if the attacker is able to block the
redirect back to the client callback so it never reaches the server. IIUC,
this is the only scenario where response_mode=3Dform_post would be the only
way to mitigate the attack.

And for those who deploy AS/IdP (we regularly ship Keycloak alongside our
applications), they should configure them (assuming the clients are
compatible) to:
* enforce PKCE
* forbid response_mode=3Dfragment (and implicit grants btw)
* follow other best practices (e.g. validating redirect URIs using exact
URI matching)
Keycloak can do that using Client Policies for instance.

Am I missing something?

Fwiw, I reproduced those scenarios (near real time access logs leak,
response_mode=3Dfragment downgrade, URL sharing) in functional tests of my
client library and confirmed the above mitigations work in those cases.

Spec-wise, I'd suggest including some wording to OAuth 2.1 recommending the
above-mentioned mitigations.

On Sat, Nov 8, 2025 at 8:00=E2=80=AFAM Philippe De Ryck <
philippe@pragmaticwebsecurity.com> wrote:

> I believe that the quoted line below is important:
>
> On 7 Nov 2025, at 10:42, Frederik Krogsdal Jacobsen <frederik.krogsdal=3D
> 40criipto.com@dmarc.ietf.org> wrote:
>
> 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 th=
at
> you could accidentally use.
>
>
>
> It seems very logical that a client implementation that needs to exchange
> an authorization code would need a PKCE verifier. It is trying to look it
> up, but due to this being a malicious or tampered with flow, that lookup =
is
> likely to fail (i.e, no PKCE verifier available). If I would write this
> code, I would not call the AS knowing up front that this request is going
> to fail. So based on this discussion, it really seems that we *should* ma=
ke
> this a guideline for implementing PKCE on the client.
>
> Philippe
> _______________________________________________
> OAuth mailing list -- oauth@ietf.org
> To unsubscribe send an email to oauth-leave@ietf.org
>


--=20
Thomas Broyer
/t=C9=94.ma.b=CA=81wa.je/
<https://ipa-reader.com/?text=3Dt%C9%94.ma.b%CA%81wa.je&voice=3DMathieu>

--00000000000066aa3606446e99e5
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Hi all, re-upping=C2=A0that conversation as a client =
and client library developer (OIDC relying party actually)</div><div><br></=
div><div>Do we all agree that the specific scenario where authorization cod=
es leak through near real-time access to access logs can be mitigated by al=
ways exchanging the authorization code, even when CSRF is suspected? (absen=
ce of or non-matching state; assuming a conformant AS/IdP that has single-u=
se authorization codes)</div><div>response_mode=3Dform_post can also work b=
ut has severe implications wrt cookies (requires either using SameSite=3DNo=
ne cookies to store &quot;authentication state&quot; between the redirects,=
 or running the AS/IdP and the application &quot;same-site&quot;; Chromium =
has had a &quot;temporary&quot; Lax+POST mitigation that also allows this t=
o work: <a href=3D"https://www.chromium.org/updates/same-site/faq/#q-what-i=
s-the-lax-post-mitigation">https://www.chromium.org/updates/same-site/faq/#=
q-what-is-the-lax-post-mitigation</a>)</div><div><br></div><div>And the oth=
er scenarios (brought in another thread) where the authorization code leaks=
 through a downgrade to response_mode=3Dfragment, or the victim sharing the=
 URL (with authorization code) following an error, can be mitigated by alwa=
ys redirecting, even (particularly) in case of errors, to remove any code f=
rom the URL? (I chose to redirect to the same callback endpoint but with an=
 error=3D, using a custom error value for cases like missing input =E2=80=
=93likely a response_mode=3Dfragment downgrade=E2=80=93 or missing session =
state =E2=80=93i.e. no cookies=E2=80=93, and always including a hash in the=
 redirect URL =E2=80=93I use the same error=3D=E2=80=93 to remove any autho=
rization code from a response_mode=3Dfragment downgrade)</div><div><br></di=
v><div>AFAICT, hardly anything can be done if the attacker is able to block=
 the redirect back to the client callback so it never reaches the server. I=
IUC, this is the only scenario where response_mode=3Dform_post would be the=
 only way to mitigate the attack.</div><div><br></div><div>And for those wh=
o deploy AS/IdP (we regularly ship Keycloak alongside our applications), th=
ey should configure them (assuming the clients are compatible) to:</div><di=
v>* enforce PKCE</div><div>* forbid response_mode=3Dfragment (and implicit =
grants btw)</div><div>* follow other best practices (e.g. validating redire=
ct URIs using exact URI matching)</div><div>Keycloak can do that using Clie=
nt Policies for instance.</div><div><br></div><div>Am I missing something?<=
/div><div><br></div><div>Fwiw, I reproduced those scenarios (near real time=
 access logs leak, response_mode=3Dfragment downgrade, URL sharing) in func=
tional tests of my client library and confirmed the above mitigations work =
in those cases.</div><div><br></div><div>Spec-wise, I&#39;d suggest includi=
ng some wording to OAuth 2.1 recommending the above-mentioned mitigations.<=
/div></div><br><div class=3D"gmail_quote gmail_quote_container"><div dir=3D=
"ltr" class=3D"gmail_attr">On Sat, Nov 8, 2025 at 8:00=E2=80=AFAM Philippe =
De Ryck &lt;<a href=3D"mailto:philippe@pragmaticwebsecurity.com">philippe@p=
ragmaticwebsecurity.com</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><div>I believe that the quoted line below is im=
portant:</div>
<div><br><blockquote type=3D"cite"><div>On 7 Nov 2025, at 10:42, Frederik K=
rogsdal Jacobsen &lt;frederik.krogsdal=3D<a href=3D"mailto:40criipto.com@dm=
arc.ietf.org" target=3D"_blank">40criipto.com@dmarc.ietf.org</a>&gt; wrote:=
</div><br><div><span style=3D"font-family:Helvetica;font-size:12px;font-sty=
le:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;te=
xt-align:start;text-indent:0px;text-transform:none;white-space:normal;word-=
spacing:0px;text-decoration:none;float:none;display:inline">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 accident=
ally use.</span></div></blockquote></div><br><div><br></div><div>It seems v=
ery logical that a client implementation that needs to exchange an authoriz=
ation code would need a PKCE verifier. It is trying to look it up, but due =
to this being a malicious or tampered with flow, that lookup is likely to f=
ail (i.e, no PKCE verifier available). If I would write this code, I would =
not call the AS knowing up front that this request is going to fail. So bas=
ed on this discussion, it really seems that we <b><u>should</u></b>=C2=A0ma=
ke this a guideline for implementing PKCE on the client.=C2=A0</div><div><b=
r></div><div>Philippe</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><br clear=3D"all"></div><div><br></div><span class=
=3D"gmail_signature_prefix">-- </span><br><div dir=3D"ltr" class=3D"gmail_s=
ignature"><div dir=3D"ltr">Thomas Broyer<br><a href=3D"https://ipa-reader.c=
om/?text=3Dt%C9%94.ma.b%CA%81wa.je&amp;voice=3DMathieu" target=3D"_blank">/=
t=C9=94.ma.b=CA=81wa.je/</a></div></div>

--00000000000066aa3606446e99e5--

