My responses inline.

> Hi everyone,
> 
> The document is about "OAuth 2.0 for Browser-Based Apps". Its abstract 
> further explains that it "details the security considerations and best 
> practices that must be taken into account when developing browser-based 
> applications that use OAuth 2.0.".
> 
> As such, detailing security considerations is important. I share the point of 
> view that basing web applications on proven concepts is important. The 
> approaches detailed in the document have all their advantages and 
> disadvantages.

We have discussed the topic of browser-based apps in depth at the OAuth 
Security Workshop last week. I am also working with Aaron Parecki on updating 
the specification to more accurately reflect these advantages and 
disadvantages. Updates will go out in the coming days/weeks, so we more than 
welcome concrete feedback on the content there.

> There are 2 main approaches to browser-based applications security. One of 
> them is to store security credentials at the frontend. The other one is to 
> use cookies and a BFF. Though common practice, there is nothing fundamentally 
> more secure about them in a demonstrable way. Different approaches, different 
> characteristics and security assumptions. Nobody can prove that either 
> approach is better, just that there are different concerns.
> 
> Handling security in BFFs relies on cookies that cannot be read by the 
> javascript application. This mechanism provides some reliable protection 
> about the cookie itself that is used as a kind of credential to access 
> confidential web resources. It obviously demands some additional layers in 
> the flow (proxy or light server). You also need a mechanism to share session 
> information, either at the server side, or for example by having the cookie 
> itself hold that information. A bigger concern to me is that you basically 
> give up standard mechanisms for securing the flow between the frontend and 
> the backend: the security between the two is a custom solution (based on 
> cookies, in a specific, custom way, this part being in no way OAuth or 
> standard). This solves the problem by not using OAuth at all in the browser 
> part of the application, basically making the client application purely 
> backend. However, the fact that browser-based applications cannot be secured 
> with OAuth isn't universally true, and strongly depends on one's definition 
> of "secure", and basically comes down to what the security issue is.

The updated specification will clearly outline the security considerations when 
making the browser-based application a public OAuth client. 

The main problem with a browser-only client is that the attacker with control 
over the client has the ability to run a silent Authorization Code flow, which 
provides them with an independent set of tokens. These tokens give the attacker 
long-term and unrestricted access in the name of the user. A BFF-based 
architecture does not suffer from this issue, since the OAuth client is a 
confidential client. Regardless of one’s definition of “secure”, this is a 
clear difference on the achievable level of security. 

Of course, as stated multiple times before, the use of a BFF does not eliminate 
the presence of the malicious JS, nor does it solve all abuse scenarios. 



> Storing tokens at the frontend has advantages: it solves my concern above 
> about a standard based flow between the frontend and the backend.

The use of cookies is a core building block of the web, and is quite standard. 

> It's simpler from an operational point of view. And it's been used in the 
> wild for ages.

Anyone using a browser-only client should be informed about the clear and 
significant dangers of this approach, which the updated specification will do. 


> Both flows have been compromised numerous times. This doesn't mean they are 
> not right by design, but that the specific security concerns have to be 
> addressed.

If you have specific security concerns about a BFF, I’d suggest raising them. 
Until now, I have only seen arguments that highlight the additional effort it 
takes to implement a BFF, but nothing to undermine its security. Plenty of 
highly sensitive applications in the healthcare and financial industry opt for 
a BFF for its improved security properties and consider this trade-off to be 
favorable.


> Now, the concerns we are really discussing is, what happens in case of XSS or 
> any form of malicious javascript.
> 
> In this case, for all known flows, session riding is the first real issue. 
> Whether the injected code calls protected web resources through the BFF or 
> using the stored tokens, is irrelevant: the evil is done. Seeing different 
> threat levels between token abuse and session riding is a logical shortcut: 
> in many cases, the impact will be exactly the same.

Stating that using stolen tokens is the same as sending requests through a 
compromised client in the user’s browser (client hijacking) is categorically 
false. Here are two concrete differences:

Stolen refresh tokens give an attacker long-term access in the name of the 
user. Client hijacking only works as long as the user’s browser is online and 
the client is effectively running.
Stolen access tokens give an attacker unfettered access to any resource server 
that accepts it. Client hijacking forces the attacker to play by the rules of 
the client. For example, an attacker can abuse a stolen token with fake origin 
headers to access a resource server that would accept the token, but has a CORS 
policy that rejects requests from the client’s origin

As stated before, the DPoP specification takes a similar point of view on these 
consequences. They explicitly aim to prevent the abuse of stolen tokens, while 
considering client hijacking to be out of scope 
(https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#name-objectives)


On a sidenote, the term “session riding” seems to refer to CSRF, not to client 
hijacking. I have only learned this myself recently and have mis-used this term 
before as well. I wanted to point this out to avoid further confusion.


> 
> Reducing the attack surface with a BFF or even a simple proxy is a possible 
> but separate topic: this doesn't have to be linked to where tokens are 
> stored. Alternatively, services that shouldn't be accessible could simply not 
> be exposed, and token scope and audience must be well thought.
> 
> As such, BFFs as well as frontend token storage, though different, are 
> application design choices and have no demonstrable superiority from a 
> security point of view. 

The security differences between a BFF and a browser-only app are not about 
token storage, but about the attacker being able to run a new flow to obtain 
tokens.

You also talk about “demonstrable” differences. I have shown examples (both in 
text and video) of these consequences in browser-only apps, resulting in the 
attacker obtaining both an access token and a refresh token. If you claim that 
BFFs are just the same, I invite you to demonstrate your point of view.


> Still, it seems it matters to some people to not exfiltrate tokens in case of 
> successful XSS. In the first instance, I don't share this need to protect 
> short-lived tokens in a game over scenario, but the whole investigation of 
> more secure frontend storage mechanisms started because some customers are 
> concerned. We are in the realm of choice, not of provable security need, but 
> it is still important to them.
> 
> Documenting security concerns and possible solutions is part of the document. 
> Where you store the tokens has an impact on how easy it will be for an 
> attacker to exfiltrate them. Local or session storage is obviously not the 
> best choice here, as injected javascript can easily access it.

Again, the security benefits of a BFF are not about stoken storage. Even if you 
find the perfect storage solution for non-extractable tokens in the browser, an 
attacker still controls the client application and can simply request a new set 
of tokens. 

This link points to the exact demo scenario in the video I have referenced 
before: https://youtu.be/OpFN6gmct8c?feature=shared&t=1366 
<https://youtu.be/OpFN6gmct8c?feature=shared&t=1366> It clearly shows how the 
attacker runs a new flow to obtain tokens, without ever touching the 
application’s tokens. 


> A service worker is an interesting place to store them, as it can 
> additionally play the role of a front-end proxy that both holds the token 
> securely, and securely proxy requests to the resource server. Besides, a 
> track was started with Rifaat to initiate changes to the service worker 
> specifications to make some things simpler.
> 
> The point that the service worker solution isn't that widespread is indeed 
> correct and should be addressed. I propose transparently mentioning that it 
> is seen as a possible but uncommon storage mechanism. There should also be 
> some explanation about other kinds of web workers, which are more commonly 
> used but exploitable, so less secure when token exfiltration is a concern. 
> The document isn't only about security best practices, though, but about 
> security concerns. Implementations are explicitly out of scope.

Using a SW for storage does not solve anything, since the attacker can simply 
request fresh tokens. 

> 
> My conclusion is that, though we can surely make the document better, there 
> is no all-encompassing solution. Similarly, BFFs are not a higher level of 
> security for healthcare of banks, just a different solution. Service workers 
> are still an interesting solution for people who absolutely want to secure 
> tokens at the frontend, and as improvable as the document is, shouldn't be 
> left out.

You, as the creator of the SW approach, have clearly stated that you don’t even 
use it in practice, so I don’t really understand the urge to make this a 
recommended pattern. On the contrary, BFFs are used in practice in a variety of 
scenarios. 

That said, the SW approach should indeed be mentioned in the document, to 
clearly illustrate the security considerations and limitations. 



> 
> About some specific concerns:
> > While content injection attacks are still possible, the BFF limits the 
> > attacker’s ability to abuse APIs by constraining access through a 
> > well-defined interface to the backend which eliminates the possibility of 
> > arbitrary API calls.
> Session riding is still the main issue and isn't addressed at all. If the 
> intention here was to limit the number of exposed endpoints, the application 
> can still be designed to either only expose what is needed, or put a proxy or 
> api manager between for limiting exposition, unrelated to where token storage 
> happen.

No-one has ever stated that a BFF would solve the consequences of an attacker 
hijacking a client. However, when the attacker is forced to launch attacks 
through a client running in the user’s browser, they are forced to go through 
the BFF. That gives you a point of control which you could use to implement 
restrictions. This is not required to benefit from a BFF, since the main 
benefit is moving from a public client to a confidential client.

You state that you can achieve the same by using a careful design of the 
application. However, you fail to mention what you consider the “application” 
and where exactly this restriction fits in. This is important, because once the 
attacker has exfiltrated access tokens, they can send arbitrary requests. If 
the resource servers are not fully shielded by an API manager, the attacker can 
contact them directly with a stolen token. And if you apply this close to the 
resource servers, how will you then configure them to only allow certain 
clients to access certain endpoints?


> > No, because running a silent flow in an iframe typically uses a web message 
> > response. In essence, the callback is not the redirect URI, but a minimal 
> > JS page that sends the code to the main application context using the web 
> > messaging mechanism. The message will have the origin of the authorization 
> > server as a sender. 
> The iframe needs to get the auth code somehow, and that typically happens by 
> setting its src to the auth endpoint, and having a redirect URI that points 
> to that minimal js page. This would mean an  attacker can change the redirect 
> URI to be able to point to some custom js in the application, which is a 
> whole different 
> 
> Philippe, I'm honestly quite skeptical about that attack, but it sounds 
> interesting. Can you provide some details or a reproducer?
> 

In all honesty, my understanding that the Web Messaging approach was 
universally used turned out to be inaccurate. There are two concrete ways to 
run a silent authorization code flow: (1) using response_mode=web_message and 
(2) using the proper redirect URI. Both scenarios allow the attacker to obtain 
the authorization code by starting the flow with an authorization request that 
is indistinguishable from a request coming from the legitimate application.

Scenario 1 (web messaging)

The iframe src points to the authorize endpoint
The AS does not redirect, but responds with an HTML page containing JS code. 
This JS code uses postmessage to send a message containing the authorization 
code to the main application context.
The attacker receives this message and obtains the authorization code

This approach is used by Auth0 and Apple. I have tested my attack scenario 
against Auth0. Note that while this flow does not use the redirect URI, it does 
validate the provided redirect URI. Additionally, the admin needs to configure 
the AS to include the client’s origin in a list of “Allowed Web Origins”.

This is also the scenario I use in the demo I have linked to above, so you can 
see it in action there.


Scenario 2 (redirect)

The iframe src points to the authorize endpoint
The AS redirects the frame to the application’s callback with the authorization 
code as a query parameter
The attacker can monitor the iframe for a URL that contains the authorization 
code, stop the frame from loading (and redeeming the authorization code), and 
extract the code

This approach is more universal, but just as vulnerable. The scenario is 
exactly the same as in the demo linked to above, but the attack code looks 
slightly different.



To conclude, I have carefully argued my point of view on this mailing list, in 
recorded videos, and in the sessions at the OAuth Security Workshop last week. 
As far as I can tell, the experts in the community acknowledge the dangers of 
browser-only apps (i.e., the attacker running a silent flow)  and agree that 
the browser-based apps BCP should accurately reflect this information. We’re 
currently working on updating the specification (which will happen in multiple 
steps, so we ask for a bit of patience). 

Unless you have anything new to add or any new issues to raise, I respectfully 
opt to disengage from further discussion. 

Kind regards

Philippe

_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to