proposal/discussion: OAuth - disallow web application to be OAuth public client (and to have direct communication with OAuth token endpoint)
elarlang opened this issue · comments
spin-off from #1916 "Discussion/Proposal 1"
The summary for browser based communication says:
To summarize, the architecture of a browser-based OAuth 2.0 client application is straightforward, but results in a significant increase in the attack surface of the application. The attacker is not only able to hijack the client, but also to extract a full-featured set of tokens from the browser-based application.
This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data.
Write requirement (preferred) or at least "really strong recommendation" to avoid architecture where the browser communicates directly with authorization server token request and handling access token and refresh token.
Or in OAuth terminology, that OAuth confidential (and not public) client is used.
May be limited to first-party solutions.
It requires quite a strong change to widespread attitude, as with using SPA architecture, often the browser uses directly OAuth service, including token endpoint.
--
Feedback from @tghosth in #1916 (comment)
that sounds like a sensible extra requirement for L2 and L3
Overall it seems like things in Section 7 are to be banned altogether and the Browser-based OAuth 2.0 client.
--
Overlap by recommendation from @TobiasAhnoff in #1925
8 Verify that access and refresh tokens are not accessible by Javascript
--
So the question is - are there valid reasons to not disallow it?
I think this needs some clarification about the wording. The title of this issue talks about "web applications" which is defined (in OAuth 2.1) as:
A web application is a client running on a web server.
i.e. a server-side application
But you are actually referencing a draft about browser-based applications which are defined as:
a client in which the client code is downloaded from a web server and executes within a user agent (e.g., web browser) on the device used by the resource owner.
i.e. a browser-side application.
So are we talking about the first ones or the second ones ? or both ?
For some browser-based applications, it might make sense to have direct communication with OAuth token endpoint. For example, when there is not server-side logic at all.
For some browser-based applications, it might make sense to handle access tokens / refresh tokens themselves. For example, when the access token is used to allow access to a WebRTC service, you may actually want the access token to be sent to the frontend code becase the frontend code needs it to actually connect to the WebRTC service (you don't want to proxy this through your server).
Your note on the terminology is correct.
A web application is a client running on a web server.
We can call it 3rd party solution.
But you are actually referencing a draft about browser-based applications which are defined as:
We can call it 1st party solution.
It is good to know what are the needs and use cases to use tokens directly in the browser-based apps for the 1st party solution. My feeling is the public client solution is too often used when it actually should not be used.
Write requirement (preferred) or at least "really strong recommendation" to avoid architecture where the browser communicates directly with authorization server token request and handling access token and refresh token.
Another valid reason for choosing to handle the access token in the browser is when you actually want your data to be stored/processed on the user's device without ever touching a server of the application. This can be good for privacy. Forbidding an architecture where the access token is stored on the user's device can actually be detrimental for the user's privacy.
A more nuanced requirement would take this into account and recommend against passing a token on node where it's not strictly needed.
Or in OAuth terminology, that OAuth confidential (and not public) client is used.
Nitpick: This is not really the same think. Browser-based client can be confidential.
@randomstuff Fair points! From one perspective I also like a more general nuanced verification, but lets first elaborate on this some more, hope all this text will be good input! It is hard to express things both short and nuanced 😄
If ASVS would add a verification like "Verify that tokens are only managed by nodes where it's strictly needed.", with the argument that there are applications where tokens need to be accessible in Javascript frontends (even if in example OAuth BCP, https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps#section-6, states that for browser-based apps a BFF solution is by design more secure than other solutions.)
How would we then reason about other verification in ASVS? Here are two examples:
9.3.3 (added) - Verify that mutual TLS (mTLS) is used by services communicating internally within a system or "intra-service communications" to ensure all the involved parties at each end of a network connection are who they claim to be. (L3 only)
50.2.1 (moved from 14.4.3) - Verify that a Content-Security-Policy response header is in place that helps mitigate impact for XSS attacks like HTML, DOM, CSS, JSON, and JavaScript injection vulnerabilities.
We could make the same kind of argument here. There are applications that need to use a relaxed CSP, which in practice will not mitigate impact for XSS attacks, should 50.2.1 be rewritten like "If possible considering implementation decisions verify that..." and there are applications that can´t support mTLS in a reasonable way, should 9.3.3 also be made more nuanced (even if it is L3 only)?
In my opinion 9.3.3 is clear and actionable, and it is a fair requirement for L3 applications, even if it will be hard to meet for those building a micro-service Kubernetes solutions...even 9.3.1 could be hard to do properly...
50.2.1 is nuanced, but a little hard to verify, could you have a CSP with unsafe-inline and still meet this requirement? How many hosts in src attributes is ok before the CSP becomes too weak? But then again it would be hard for ASVS to state those kind of details so this might be the best ASVS can do...keeping a good consistent balance is hard!
Back to the new OAuth chapter. I believe any set of verifications for OAuth, applicable for Healthcare and Finance etc, should reflect the OAuth BCPs and, if login and OIDC is involved as well, also OIDC FAPI. If not aligned with those kind of specs ASVS will become less usefull, but it would of course be great if ASVS can capture the essence (see #1925 disscusion.)
What do you think of this approach to capture recommendations from OAuth BCPs and OIDC FAPI:
L1,L2,L3: Verify that tokens are only managed by nodes where it's strictly needed, in example avoid having tokens accessible for JavaScript frontends.
Together with some additional L3 suggestions from #1964 (comment)
L3: "Verify that all clients are confidential" (L1-L2 could allow for public clients)
L3: "Verify that all clients are configured to use strong client authentication, mTLS or private-key-jwt" (L1-L2 could also use client-secret, note that verification 9.3.3 mandates mTLS, but private-key-jwt is also regarded sufficient by e g FAPI)
L3: Verify that PAR with client authentication is used (for L1-L2 PAR is optional and could be used without client authentication)
L3: Verify that sender-constrained access-tokens are used either using mTLS or DPoP (note that for L1 and L2 this does not require client authentication if used by public clients)
L3: Verify that refresh-tokens are sender-constrained (by requiring client authentication for all token requests, while L1-L2 could allow one-time mitigation strategy for public clients, this is especially important if offline_access is granted, allowing long lived tokens not attached to active user sessions)