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 to 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 probably off-topic for this thread. Cheers, Frederik On Thu, 6 Nov 2025 at 17:43, Aaron Parecki <aaron= [email protected]> 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 AM Neil Madden <[email protected]> > wrote: > >> The only issue I have with deprecating state for CSRF protection is that >> the client has no way in general to know if the AS supports (in fact >> enforces) PKCE. If it doesn’t, then we may end up with no CSRF protection >> at all, and clients being vulnerable to Login CSRF/session fixation-like >> attacks. >> >> — Neil >> >> On 6 Nov 2025, at 16:12, Aaron Parecki <[email protected]> wrote: >> >> >> >> S1 seems like the cleanest solution to me. I think this should also come >> with language officially deprecating "state" for CSRF protection like >> Philippe said. >> >> >> On Thu, Nov 6, 2025 at 10:59 AM Primbs, Jonas < >> [email protected]> wrote: >> >>> Let’s 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 <[email protected]>: >>> >>> This makes me wonder if we could in fact have a special client_id value >>> 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 right >>> thing for most ASes, as Tim mentions. Something like >>> client_id=csrf_detected_revoke_please. >>> >>> On 6 Nov 2025, at 13:04, Tim Würtele <[email protected]> >>> 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 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... >>> >>> 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). >>> >>> >>> 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 >>> <[email protected]> <[email protected]>: >>> >>> 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 < >>> [email protected]> 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 >>>> <https://www.google.com/maps/search/Sand+13,+72076+T%C3%BCbingen,+Germany?entry=gmail&source=g> >>>> Tel.: (+49) 7071 / 29-70512 >>>> Mail: [email protected] >>>> Web: https://kn.inf.uni-tuebingen.de >>>> >>>> _______________________________________________ >>>> 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] >>> >>> -- >>> Tim Würtele, M.Sc. >>> Room V38 2.434 >>> Institute of Information Security - SEC >>> Universität StuttgartUniversitätsstraße 38 >>> <https://www.google.com/maps/search/Universit%C3%A4tsstra%C3%9Fe+38?entry=gmail&source=g> >>> D-70569 Stuttgart >>> Germany >>> Phone: +49 (0) 711 685-88468https://sec.uni-stuttgart.de >>> >>> _______________________________________________ >>> 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] >>> >>> >>> _______________________________________________ >>> 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] >
_______________________________________________ OAuth mailing list -- [email protected] To unsubscribe send an email to [email protected]
