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] 
> <mailto:[email protected]>> wrote:
>> Hi Neil,
>> 
>>> Am 04.11.2025 um 09:53 schrieb Neil Madden <[email protected] 
>>> <mailto:[email protected]>>:
>>> 
>>> 
>>> 
>>>> On 4 Nov 2025, at 13:37, Primbs, Jonas <[email protected] 
>>>> <mailto:[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] 
>>>>> <mailto:[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] <mailto:[email protected]>
>> To unsubscribe send an email to [email protected] 
>> <mailto:[email protected]>

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to