Skip to content

Commit e9c6fc1

Browse files
authored
Merge pull request #15 from ymajoros/bffproxy
reworked some architectural patterns
2 parents 18ad753 + 3bff1fe commit e9c6fc1

File tree

2 files changed

+36
-30
lines changed

2 files changed

+36
-30
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ draft-ietf-oauth-browser-based-apps.xml
1919
package-lock.json
2020
report.xml
2121
.DS_Store
22+
/.idea/

draft-ietf-oauth-browser-based-apps.md

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -212,35 +212,36 @@ provide any built-in mechanism for these, and would instead be extended with cus
212212
Application Architecture Patterns
213213
=================================
214214

215-
There are three primary architectural patterns available when building browser-based
215+
Here are the main architectural patterns available when building browser-based
216216
applications.
217217

218-
* a JavaScript application that has methods of sharing data with resource servers, such as using common-domain cookies
219-
* a JavaScript application with a backend component
220-
* a JavaScript application with no backend, accessing resource servers directly
218+
* single-domain, not using OAuth
219+
* a JavaScript application accessing resource servers
220+
* either directly
221+
* or through a service worker
222+
* a JavaScript application with a stateful backend component for storing tokens and handling all authentication flows (BFF proxy)
221223

222-
These three architectures have different use cases and considerations.
224+
These architectures have different use cases and considerations.
223225

224226

225-
Browser-Based Apps that Can Share Data with the Resource Server
226-
---------------------------------------------------------------
227+
Single-Domain Browser-Based Apps (not using OAuth)
228+
--------------------------------------------------
227229

228230
For simple system architectures, such as when the JavaScript application is served
229-
from a domain that can share cookies with the domain of the API (resource server),
231+
from a domain that can share cookies with the domain of the API (resource server) and the authorization server,
230232
OAuth adds additional attack vectors that could be avoided with a different solution.
231233

232234
In particular, using any redirect-based mechanism of obtaining an access token
233235
enables the redirect-based attacks described in {{oauth-security-topics}} Section 4, but if
234236
the application, authorization server and resource server share a domain, then it is
235237
unnecessary to use a redirect mechanism to communicate between them.
236238

237-
An additional concern with handling access tokens in a browser is that as of the date of this publication, there is no
238-
secure storage mechanism where JavaScript code can keep the access token to be later
239-
used in an API request. Using an OAuth flow results in the JavaScript code getting an
240-
access token, needing to store it somewhere, and then retrieve it to make an API request.
239+
An additional concern with handling access tokens in a browser is that
240+
in case of successful XSS attack, tokens could be read and further used or transmitted by the injected code if no
241+
secure storage mechanism is in place.
241242

242-
Instead, a more secure design is to use an HTTP-only cookie between the JavaScript application
243-
and API so that the JavaScript code can't access the cookie value itself. The `Secure` cookie attribute should be used to ensure the cookie is not included in unencrypted HTTP requests. Additionally, the `SameSite` cookie attribute can be used to counter CSRF attacks,
243+
It could as such be considered to use an HTTP-only cookie between the JavaScript application
244+
and API so that the JavaScript code can't access the cookie value itself. The `Secure` cookie attribute should be used to ensure the cookie is not included in unencrypted HTTP requests. Additionally, the `SameSite` cookie attribute can be used to counter some CSRF attacks,
244245
but should not be considered the extent of the CSRF protection, as described in {{draft-ietf-httpbis-rfc6265bis}}
245246

246247
OAuth was originally created for third-party or federated access to APIs, so it may not be
@@ -250,12 +251,12 @@ in using OAuth even in a common-domain architecture:
250251
* Allows more flexibility in the future, such as if you were to later add a new domain to the system. With OAuth already in place, adding a new domain wouldn't require any additional rearchitecting.
251252
* Being able to take advantage of existing library support rather than writing bespoke code for the integration.
252253
* Centralizing login and multifactor support, account management, and recovery at the OAuth server, rather than making it part of the application logic.
254+
* Splitting of responsibilities between authenticating a user and serving resources
253255

254-
Using OAuth for browser-based apps in a first-party same-domain scenario provides these advantages, and can be accomplished by either of the two architectural patterns described below.
256+
Using OAuth for browser-based apps in a first-party same-domain scenario provides these advantages, and can be accomplished by any of the architectural patterns described below.
255257

256-
257-
JavaScript Applications with a Backend
258-
--------------------------------------
258+
Backend For Frontend (BFF) Proxy
259+
--------------------------------
259260

260261
+-------------+ +--------------+ +---------------+
261262
| | | | | |
@@ -268,12 +269,11 @@ JavaScript Applications with a Backend
268269
| (D)| (G)|
269270
| v v
270271
|
271-
| +--------------------------------+
272-
| | |
273-
| | Application |
274-
(B)| | Server |
275-
| | |
276-
| +--------------------------------+
272+
| +--------------------------------------+
273+
| | |
274+
| | Backend for Frontend Proxy (BFF) |
275+
(B)| | |
276+
| +--------------------------------------+
277277
|
278278
| ^ ^ + ^ +
279279
| (A)| (C)| (E)| (F)| |(H)
@@ -285,13 +285,14 @@ JavaScript Applications with a Backend
285285
| |
286286
+-------------------------------------------------+
287287

288-
In this architecture, commonly referred to as "backend for frontend" or "BFF", the JavaScript code is loaded from a dynamic Application Server (A) that also has the ability to execute code itself. This enables the ability to keep
289-
all of the steps involved in obtaining an access token outside of the JavaScript
288+
In this architecture, commonly referred to as "backend for frontend" or "BFF", the JavaScript code is loaded from a dynamic Application Server (A) that has the ability to execute code and handle the full authentication flow itself. This enables the ability to keep
289+
the call to actually get an access token outside the JavaScript
290290
application.
291291

292-
Note that this application backend is not the Resource Server, it is still considered part of the OAuth client and would be accessing data at a separate resource server.
292+
Note that this BFF is not the Resource Server, it is the OAuth client and would be accessing data at a separate resource server.
293293

294-
In this case, the Application Server initiates the OAuth flow itself, by redirecting the browser to the authorization endpoint (B). When the user is redirected back, the browser delivers the authorization code to the application server (C), where it can then exchange it for an access token at the token endpoint (D) using its client secret. The application server then keeps the access token and refresh token stored internally, and creates a separate session with the browser-based app via a
294+
In this case, the BFF initiates the OAuth flow itself, by redirecting the browser to the authorization endpoint (B). When the user is redirected back, the browser delivers the authorization code to the application server (C), where it can then exchange it for an access token at the token endpoint (D) using its client secret and PKCE code verifier.
295+
The application server then keeps the access token and refresh token stored internally, and creates a separate session with the browser-based app via a
295296
traditional browser cookie (E).
296297

297298
When the JavaScript application in the browser wants to make a request to the Resource Server,
@@ -307,15 +308,19 @@ The Application Server SHOULD be considered a confidential client, and issued it
307308
In this scenario, the connection between the browser and Application Server SHOULD be a
308309
session cookie provided by the Application Server.
309310

311+
### Security considerations
310312
Security of the connection between code running in the browser and this Application Server is
311313
assumed to utilize browser-level protection mechanisms. Details are out of scope of
312314
this document, but many recommendations can be found in the OWASP Cheat Sheet series (https://cheatsheetseries.owasp.org/),
313315
such as setting an HTTP-only and `Secure` cookie to authenticate the session between the
314316
browser and Application Server.
315317

316-
<!--
317-
TODO: security considerations around things like Server Side Request Forgery or logging the cookies
318+
Additionally, cookies MUST be protected from leakage by other means, such as logs.
318319

320+
This architecture protects against tokens leakage from the browser, but creates a CSRF attack vector:
321+
once the user is authenticated, the BFF proxy will automatically add tokens to calls to the resource server.
322+
323+
<!--
319324
TODO: Add another description of the alternative architecture where access tokens are passed to JS and the JS app makes API calls directly. https://mailarchive.ietf.org/arch/msg/oauth/sl-g6zYSpJW3sYqrR0peadUw54U/
320325
-->
321326

0 commit comments

Comments
 (0)