That would require the POST request response from the client to set yet
another session with the authenticated account that is then used/merged
with the original one in the follow up GET that the user needs to first
confirm with an explicit action?

I don't think you're missing anything but the suggestion is beyond the
realm of practical, usable or suggestable from my perspective.

S pozdravem,
*Filip Skokan*


On Wed, 5 Nov 2025 at 18:09, Primbs, Jonas <[email protected]>
wrote:

>
>
> Am 05.11.2025 um 10:54 schrieb Filip Skokan <[email protected]>:
>
> > That’s right, but you don’t need a full session for finishing the
> authorization code flow.
>
> That's a rather sweeping statement which is only conditionally true. There
> are very specific cases for which in fact this is false (e.g. step-up,
> re-auth, account-linking).
>
>
> But couldn’t this be fixed by the user clicking a confirm link on the HTML
> response of the POST redirect URI endpoint?
>
> So calling the POST callback URI would submit only the SameSite=none state
> cookie to implement the CSRF mitigation.
> If the state verification and the token request succeeded, the client
> responds with a HTML document like „You are authenticated as [the OIDC
> user] from [the IdP]. Is that right?“.
> Then the user needs to click a „confirm“ button which is a link to a
> confirmation page. Technically, this is a same-site GET request initiated
> by the user, so samesite=lax and I think even samesite=strict session
> cookies will be sent along with this request.
>
> Or did I miss anything here?
>
>
> S pozdravem,
> *Filip Skokan*
>
>
> On Wed, 5 Nov 2025 at 16:34, Primbs, Jonas <[email protected]>
> wrote:
>
>> Hi Dick,
>>
>>
>> Am 05.11.2025 um 06:32 schrieb Dick Hardt <[email protected]>:
>>
>> Jonas
>>
>> + Filip given his expertise
>>
>> I tried to follow this thread but got lost.
>>
>> My understanding is you are suggesting we recommend
>> response_mode=form_post over response_mode=redirect
>>
>>
>> * response_mode=query, but yes.
>>
>> If session cookies are sameSite=lax, they won't to be sent via form_post
>> -- so client web sites would have to set session cookies to sameSite=none
>> -- which is susceptible to CSRF of course, and while there are other ways
>> to protect against CSRF, your attack is CSRF -- so it would seem that if
>> the site has protected against CSRF then the attack can't happen.
>>
>>
>> That’s right, but you don’t need a full session for finishing the
>> authorization code flow.
>> Instead, you just need to remember the state sent in the authorization
>> request and (if PKCE is being used) the code_verifier.
>> This means, when starting the authorization code flow, you can set the
>> following cookie when redirecting from the client to the authorization
>> request URI:
>>
>> Set-Cookie: state_{state}={code-verifier}; SameSite=none
>>
>> When you will be sent back with the POST request to the client, your
>> browser sends this cookie to the client backend (because of SameSite=none)
>> and since the POST body contains the same state parameter (reflected by the
>> AS), you fulfill the double submit pattern which is a well-known CSRF
>> protection.
>>
>> Does this make things clear for you?
>>
>> Greetings,
>> Jonas
>>
>>
>> What am I missing?
>>
>> /Dick
>>
>> On Wed, Nov 5, 2025 at 3:56 AM Primbs, Jonas <
>> [email protected]> wrote:
>>
>>> Hi Neil,
>>>
>>> Am 04.11.2025 um 09:53 schrieb Neil Madden <[email protected]>:
>>>
>>>
>>>
>>> On 4 Nov 2025, at 13:37, Primbs, Jonas <[email protected]>
>>> wrote:
>>>
>>> Hi Neil,
>>>
>>> thanks for your valuable feedback.
>>> You will find my thoughts inline.
>>>
>>> Am 04.11.2025 um 04:19 schrieb Neil Madden <[email protected]>:
>>>
>>> Thanks for sharing your slides. Although this is an interesting
>>> theoretical attack, I do not think it is much of a concern in practice. If
>>> we take your attack vectors from slide 12:
>>>
>>> * Referer header leaks: the default policy in browsers since 2019 is
>>> strict-origin-when-cross-origin, which prevents this leak [1].
>>>
>>>
>>> I still think it is worth to mention in the draft because even if it’s
>>> the default, it does not mean that client implementors do not change it in
>>> a bad way.
>>> Moreover, in modern infrastructures, reverse proxies are often used for
>>> path-based routing, which results resources (images, favicons etc) being
>>> referenced on the same host but requests will be routed to external parties
>>> like CDNs.
>>>
>>> * URL sharing and analytics tools are already addressed by [2] in the
>>> original OAuth RFC 6749, which already says to avoid 3rd party analytics on
>>> the redirect endpoint and to redirect immediately after collecting the
>>> credentials. I think most providers do in fact do this?
>>>
>>>
>>> Yes, I have never seen the issue with the analytics tools in the wild
>>> before, I just added it for completeness.
>>> Out of the last 10 oauth client penetration tests, of which 6 were
>>> affected by the browser swapping attack (the other 4 did not even implement
>>> the CSRF protection), only one was affected by the URL sharing.
>>> However, redirecting to another URL, not including scripts, and ensuring
>>> that referrer-policies are applied correctly are all mitigation strategies,
>>> but not solve the general issue of sending a secret (the authorization
>>> code) as a query parameter, which is a bad practice in general [1].
>>>
>>> That leaves leakage via logs, which IMO is adequately addressed by (a)
>>> use of TLS (minimising on-path observers) and (b) using short-lived auth
>>> codes.
>>>
>>>
>>> a) That’s correct.
>>> b) According to RFC 6749, the maximum validity period is 10 minutes.
>>> Today, many logging happens in real-time, so my impression was that 10
>>> minutes is enough for attackers with access to logs. Think of a shell
>>> script which polls every minute for the logs and greps for the keyword
>>> „code“, extracts the authorization code and automatically resolves that.
>>>
>>>
>>> Attackers with real-time access to logs are generally already quite
>>> privileged (eg they have ssh access to the servers or access to a SIEM).
>>> The risk from logs mostly comes from them being copied into support tickets
>>> or archived to insecure S3 buckets and similar things. Those things don't
>>> generally happen in 10 minutes.
>>>
>>>
>>> I don’t agree here.
>>> Having read-only access to a SIEM system, which provides you real-time
>>> access to logs being collected from a client application or any involved
>>> reverse proxy, load balancer, middleware etc, should not enable you taking
>>> over the client session of any user.
>>> This is a behavior, which many service providers will not expect from an
>>> OAuth-compliant software.
>>>
>>> Moreover, this increases the criticality of misconfigured HTTP servers,
>>> e.g., an NGINX or Apache web server which allow you to access the server’s
>>> logs in real-time by browsing something like
>>> /../../../../var/logs/nginx/access.log
>>> I agree, such misconfigurations should not be in scope of OAuth.
>>> However, this increases the criticality of such a finding from an
>>> information leak to a medium or even high - and OAuth could improve that by
>>> slightly changing the specs.
>>>
>>>
>>> Using fragments or form_post both have significant downsides. Fragments
>>> only work with Javascript, which introduces new failure cases and attack
>>> surface (ideally the redirect endpoint would be served with CSP
>>> script-src=none).
>>>
>>>
>>> Yes, that’s why I recommend this for web apps running in the user’s
>>> browser with javascript anyways, or for mobile apps.
>>>
>>>
>>> Re-reading my old blog post (
>>> https://neilmadden.blog/2019/01/16/can-you-ever-safely-include-credentials-in-a-url/)
>>> reminds me of a drawback of using the fragment: if you don't explicitly
>>> clear it, then it is carried over on redirects, potentially leaking the
>>> auth code to other pages/sites. (At least, that used to be the case - I
>>> don't believe that behaviour has changed).
>>>
>>>
>>> Yes, but we have the same issue with query parameters too, right?
>>> Fragment however has the advantage of reducing the attack surface with
>>> respect to logging from an entire landscape down to the client.
>>>
>>>
>>>
>>> Form post requires use of samesite=none cookies, weakening CSRF
>>> protections. I don’t think we should be recommending weakening protections
>>> against very real threats (XSS, CSRF) to protect against something that
>>> seems unlikely.
>>>
>>>
>>> Thanks a lot for that hint with the CSRF protection with samesite=none.
>>> I think samesite=none works perfectly fine, if the „session“ cookie is
>>> not a real session cookie, but the state parameter instead, because then
>>> the „state“ cookie, which contains the state parameter combined with the
>>> identical state parameter reflected by the AS in the POST body parameter
>>> apply the double submit cookie pattern [2], which is also a well-known CSRF
>>> protection mechanism.
>>> The real session cookie (if you even need one before you are logged in)
>>> could still use samesite=strict or lax.
>>> But I get the point that maybe I should mention this in the draft.
>>>
>>> We can perhaps improve the wording around existing countermeasures if
>>> there is evidence they are being ignored, but I think that is enough. I
>>> could be persuaded otherwise, but I’d need to see more evidence that this
>>> is a problem in practice and that the countermeasures do more good than
>>> harm.
>>>
>>>
>>> I think the problem with response_mode=query in general is that the
>>> authorization code is transferred in the URL which opens up many attack
>>> vectors that all need to be fixed.
>>> The most critical one are logs because there is no general fix for that,
>>> exept not providing the authorization code as a query parameter.
>>> My impression was that our customers were really surprised that this is
>>> still the default behavior of OAuth and they didn’t expect that from such a
>>> big large-scale deployed standard.
>>> Especially our customers, which just deploy existing client
>>> implementations, did not expect that they have to care that much about logs
>>> of, e.g., their reverse proxies, and they were shocked that these logs
>>> which are sometimes audited by external partners enable the log auditor to
>>> start a browser-swapping attack and take over, e.g., administrator accounts.
>>>
>>>
>>> I agree in general, but (a) the situation is a lot less bad than it used
>>> to be and (b) the short-lived nature of auth codes does IMO mitigate a lot
>>> of these issues. According to
>>> https://www.oauth.com/oauth2-servers/authorization/the-authorization-response/,
>>> most auth codes are in fact only valid for 30–60 seconds, which would
>>> further reduce the opportunity to exploit this.
>>>
>>>
>>> That’s right, maybe we should recommend a validity period of 1 instead
>>> of 10 minutes in OAuth 2.1.
>>>
>>> By the way, Aaron and I had a discussion on that today and we figured
>>> out that the „implicit flow“ of OIDC might also be affected. Probably
>>> things are much more critical here than in OAuth.
>>>
>>> We also discovered an alternative fix for that by enforcing PKCE for
>>> every flow and sending a token request from client to AS even if state
>>> parameters don’t match.
>>> This promises to simplify the specs in general with the nice side effect
>>> that it also sufficiently fixes browser-swapping attacks without breaking
>>> changes.
>>> I will discuss that with Aaron and Mike and will send an update.
>>>
>>> I'm sympathetic to the idea that query mode is not great, but it's
>>> pretty well established at this point and we've spent a long time telling
>>> people to use it. I don't find this a compelling enough reason to suggest a
>>> change.
>>>
>>>
>>> I get your point. However, I’m not a friend of leaving things as they
>>> are, just for not having to correct previous statements, especially if
>>> we could do better.
>>>
>>> I totally agree, that we cannot simply deprecate response_mode=query for
>>> legacy reasons. However, I think we should ensure that client developers
>>> and providers are aware of the risk that authorization codes can get logged
>>> and can be used to take over user sessions.
>>>
>>> [1]
>>> https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url
>>> [2]
>>> https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#alternative-using-a-double-submit-cookie-pattern
>>>
>>>
>>> — Neil
>>>
>>>
>>> Independently of whether browser-swapping attacks are a realistic attack
>>> or not — does anyone disagree with adding or at least referencing response
>>> modes in the OAuth 2.1 spec in general?
>>> I personally would have been glad to have had any reference to them from
>>> another document instead of being lucky that I accidentially stumbled over
>>> this spec.
>>>
>>> Greetings,
>>> Jonas
>>>
>>>
>>> _______________________________________________
>>> 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