Subject: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

From: Vittorio Bertocci <[email-masked]>
Date: Fri, 12 Feb 2021 20:46:00 +0000

Dear all,
Brian and yours truly are proposing a new specification that shows how the user agent frontend of a web app can delegate token acquisition and persistence to its backend, and request such tokens when needed for direct access of protected resources from the frontend code.

The pattern is already in use, in proprietary form, by various modern development stacks, such as Next.JS. Variants of the pattern, often discussed under the catch-all term BFF (backend for frontend), have been often mentioned in this workgroup’s activity, but always left all implementation details to the reader.
We believe the pattern has merit, as corroborated by its growing adoption. By delegating access token acquisition to the backend, we avoid many of the often brittle moving parts (and implied attack surface) required to acquire access tokens from a user agent. The topology also relieves the frontend from the need of persisting tokens in local storage, a well known sore point of using OAuth directly in JavaScript, by relying on its backend storage and session to preserve tokens.

Although the specification is very simple, providing explicit guidance on the scenario offers many advantages.  
- It makes it possible to create interoperable SDKs, where frontend dev stacks (any JS flavor) can be mixed and matched with compliant backend stacks (middlewares in node, java, ASP.NET, PHP etc)
- It allows us to provide guidance on how to properly tackle the scenario and warn implementers against security risks (scope escalations, using IDtokens instead of access tokens, etc)
- It allows us to discuss (and when appropriate, promote) this pattern as part of the browser apps security guidance, and position the scenario where frontend only calls API on its own backed (hence doesn’t need access tokens) simply as a special case of this more general pattern
- This approach makes mocking and testing apps very easy, possibly preventing developers from weakening the security of their system (eg turning on ROPG options)  or turning to risky practices like scraping

Needless to say, this specification doesn’t entirely eliminate the risks inherent to direct use of access tokens from a browser. But reality is that the pattern is in widespread use, and the circumstances leading to that (eg developers on a particular project only work with frontend stacks; components like reverse proxies might not always be viable; etc) aren’t going away any time soon. By providing simple guidance on this pattern, we can simplify the life of many developers while enshrining basic security hygiene in scenarios that would have otherwise be left to their own device.
 
Looking forward for your feedback!

B&V  

On 2/12/21, 12:41, "[email-masked]" <[email-masked]> wrote:

    A new version of I-D, draft-bertocci-oauth2-tmi-bff-00.txt
    has been successfully submitted by Vittorio Bertocci and posted to the
    IETF repository.
    
    Name:		draft-bertocci-oauth2-tmi-bff
    Revision:	00
    Title:		Token Mediating and session Information Backend For Frontend
    Document date:	2021-02-12
    Group:		Individual Submission
    Pages:		16
    URL:            https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.txt
    Status:         https://datatracker.ietf.org/doc/draft-bertocci-oauth2-tmi-bff/
    Html:           https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.html
    Htmlized:       https://tools.ietf.org/html/draft-bertocci-oauth2-tmi-bff-00

    Abstract:
       This document describes how a JavaScript frontend can delegate access
       token acquisition to a backend component.  In so doing, the frontend
       can access resource servers directly without taking on the burden of
       communicating with the authorization server, persisting tokens, and
       performing operations that are fraught with security challenges when
       executed in a user agent, but are safe and well proven when executed
       by a confidential client running on a backend.

    
    Please note that it may take a couple of minutes from the time of submission
    until the htmlized version and diff are available at tools.ietf.org.
    
    The IETF Secretariat

---

From: Stoycho Sleptsov <[email-masked]>
Date: Sun, 14 Feb 2021 05:39:26 +0200

Hello Mr. Bertocci,

I am a novice yet at APIs and OAuth, but nevertheless am entrusted by the
executives of our organisation to expose some of the capabilities of our
system through APIs. For that I have set out to implement an OAuth server
(based on the 2.1 draft), which is basically functional now, and the
corresponding APIs (resource servers). Our team will also have to implement
some initial frontend applications which will
consume those exposed resources. I was exactly at the point of considering
how to organise the correspondence of the access token from the auth server
to the frontend and from the frontend to the
resource servers, when I received as a very nice surprise the news about
tmi-bff draft. It was such a relief, as the option to delegate access token
acquisition to a backend component, while still accessing resource servers
directly from the frontend, seemed most suitable and
well balanced for our case.

I have read the draft with great pleasure, but one thing concerns me in it.

In the description of the protocol flow (1.2), in the step of token request
from backend to AS (step B), it mentions that the AS should "issue the
requested token without requiring user interaction". Same
thing is reconfirmed in section 4, step 4: "the backend verifies whether it
has the necessary artifacts to request it to the
authorization server without requiring user interaction".

But an initial interaction between the resource owner and the authorization
server is required by the authorization code flow (section 1.3.1 of the
draft-ietf-oauth-v2-1-01).

So where does this interaction fit in the tmi-bff protocol flow? Or tmi-bff
is not supposed to be used with authorization code flow?

Thank you for your time,
hoping to hear from you,
Stoycho.

На пт, 12 фев 2021 г., 22:46 Vittorio Bertocci <vittorio.bertocci=
[email-masked]> написа:

> Dear all,
> Brian and yours truly are proposing a new specification that shows how the
> user agent frontend of a web app can delegate token acquisition and
> persistence to its backend, and request such tokens when needed for direct
> access of protected resources from the frontend code.
>
> The pattern is already in use, in proprietary form, by various modern
> development stacks, such as Next.JS. Variants of the pattern, often
> discussed under the catch-all term BFF (backend for frontend), have been
> often mentioned in this workgroup’s activity, but always left all
> implementation details to the reader.
> We believe the pattern has merit, as corroborated by its growing adoption.
> By delegating access token acquisition to the backend, we avoid many of the
> often brittle moving parts (and implied attack surface) required to acquire
> access tokens from a user agent. The topology also relieves the frontend
> from the need of persisting tokens in local storage, a well known sore
> point of using OAuth directly in JavaScript, by relying on its backend
> storage and session to preserve tokens.
>
> - It makes it possible to create interoperable SDKs, where frontend dev
> stacks (any JS flavor) can be mixed and matched with compliant backend
> stacks (middlewares in node, java, ASP.NET, PHP etc)
> - It allows us to provide guidance on how to properly tackle the scenario
> and warn implementers against security risks (scope escalations, using
> IDtokens instead of access tokens, etc)
> - It allows us to discuss (and when appropriate, promote) this pattern as
> part of the browser apps security guidance, and position the scenario where
> frontend only calls API on its own backed (hence doesn’t need access
> tokens) simply as a special case of this more general pattern
> - This approach makes mocking and testing apps very easy, possibly
> preventing developers from weakening the security of their system (eg
> turning on ROPG options)  or turning to risky practices like scraping
>
> Needless to say, this specification doesn’t entirely eliminate the risks
> inherent to direct use of access tokens from a browser. But reality is that
> the pattern is in widespread use, and the circumstances leading to that (eg
> developers on a particular project only work with frontend stacks;
> components like reverse proxies might not always be viable; etc) aren’t
> going away any time soon. By providing simple guidance on this pattern, we
> can simplify the life of many developers while enshrining basic security
> hygiene in scenarios that would have otherwise be left to their own device.
>
>     URL:
> https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.txt
>     Status:
> https://datatracker.ietf.org/doc/draft-bertocci-oauth2-tmi-bff/
>     Html:
> https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.html
>     Htmlized:
> https://tools.ietf.org/html/draft-bertocci-oauth2-tmi-bff-00
>
>
>     Abstract:
> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth
>

---

From: Neil Madden <[email-masked]>
Date: Sun, 14 Feb 2021 08:17:46 +0000

I have a lot of security concerns about this draft. 

The draft alludes to security issues associated with handling access tokens in the frontend but never really spells them out. From the Security Considerations it seems that the primary concern is with theft of access tokens from local storage. To do this you’d need an XSS attack. But in that case, wouldn’t the attacker simply use the XSS to make a call to the bff-token endpoint instead? 

The combination of the bff-token endpoint recommending the use of GET requests together with the hint to use cookie-based authentication is likely going to punch a hole in most CSRF defenses, which assume that GETs are safe. The only thing preventing this being exploitable is Cross-Origin Read Blocking (https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md) due to the JSON content-type. That makes me really nervous. We should at least mandate X-Content-Type-Options: nosniff on that response. I’d feel more comfortable if this was a POST request only. 

As Stoycho Sleptsov mentioned in the other email, the lack of front-channel communication between the AS and the RO seems odd. If the backend is already implicitly trusted then couldn’t you skip OAuth and just get the backend to issue short-lived JWTs to the frontend that it can use for API access?

If you want to allow auth code flow etc then perhaps the bff-token endpoint can return a standard error code with an authorization endpoint URI that the SPA then navigates the user to. (Eg the backend can do a PAR request first and return a URI that references that so that authorization details aren’t passed through the frontend). 

— Neil

> On 12 Feb 2021, at 20:46, Vittorio Bertocci <vittorio.bertocci=[email-masked]> wrote:
> Dear all,

-- 
ForgeRock values your Privacy <https://www.forgerock.com/your-privacy>

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 10:51:35 +0100

I also flat out reject the premise of this draft. It introduces a pseudo
AS-like proxy which now has all the requirements of an AS and more. While
AS SDKs provide easy ways for client UIs to effectively deal with
communication via the AS, there's no way for the AS to provide standard AS
specific services prototypes to support BFF. That means that everyone is
writing their own BFF AS-proxy.

Additionally, I too am lacking the clarity on the *WHY*. The only thing
mentioned in the draft is

> That approach is not always viable, as in the absence of reverse proxy
> deployments the creation and maintenance of a facade for multiple APIs can
> be expensive

Which isn't ever justified, but even if we accept that as a true premise,
what are these AS doing that even require a BFF?

Hypothetically you could argue that the auth code flow requires a BFF and
that's required for user login since implicit flow no longer exists, but
that isn't true. You can use client side PKCE for validation of these via
not requiring the client secret in the front end, and then the problem
there is solved. And if you argue that this can't be done, then the
solution is introducing a better way to handle this so that a BFF for AS
flows don't have to exist.

So what concrete problem is this solving?

There was also the argument of *there are lots of people doing this*, which
is always a terrible argument, but even if we do permit that in the
discussion, we still need to answer the *why. *Why are developers creating
BFF for their frontends to communicate with an AS. Is it because AS are
terrible, is it because *front ends as a service* are terrible, etc...
Until we know why this is happening concretely, I don't think we should
encourage further use of a pattern rife with potential security risks by
telling everyone how you can do it (because the guidance we are offering
doesn't even slightly increase safety).

Further, even if we were to accept this pattern and want to create a
standard around it, we are effectively creating an AS proxy here, which
means we should require it to act like an AS, and delegate the
specification of resources, endpoints, terminology, and patterns to
existing or future AS related RFCs. (We already have a problem with the
current draft as it attempts to redefine and introduce new terms/patterns
that have the same functionality as existing ones in the AS, yet fail to
capture the full importance of the original RFCs. This is bad duplication).
And therefore in conclusion we should focus only on the aspects that are
absolutely required which aren't already present in some form in existing
AS related RFCs, but what are those?

The one counterpoint to all of this is the potential introduction of domain
specific *cookie* language (which doesn't exist in the current draft).
Concretely, *let's add a response_type=cookie*, to AS to support domain
first-party cookies and session management. When we built our AS we
explicitly added this so that services can use the JWT found in the
HttpOnly SameSite=Strict cookie as a security measure against XSS attacks
that attempt to exfiltrate access tokens. That's a potential suggestion I
would favor, although I still can't know if that solves the problem being
presented in the draft.

- Warren

Warren Parad

Founder, CTO
Secure your user data and complete your authorization architecture.
Implement Authress <https://authress.io>.

On Sun, Feb 14, 2021 at 9:18 AM Neil Madden <[email-masked]>
wrote:

> The draft alludes to security issues associated with handling access
> tokens in the frontend but never really spells them out. From the Security
> Considerations it seems that the primary concern is with theft of access
> tokens from local storage. To do this you’d need an XSS attack. But in that
> case, wouldn’t the attacker simply use the XSS to make a call to the
> bff-token endpoint instead?
>
> The combination of the bff-token endpoint recommending the use of GET
> requests together with the hint to use cookie-based authentication is
> likely going to punch a hole in most CSRF defenses, which assume that GETs
> are safe. The only thing preventing this being exploitable is Cross-Origin
> Read Blocking (
> https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md)
> due to the JSON content-type. That makes me really nervous. We should at
> least mandate X-Content-Type-Options: nosniff on that response. I’d feel
> more comfortable if this was a POST request only.
>
> As Stoycho Sleptsov mentioned in the other email, the lack of
> front-channel communication between the AS and the RO seems odd. If the
> backend is already implicitly trusted then couldn’t you skip OAuth and just
> get the backend to issue short-lived JWTs to the frontend that it can use
> for API access?
>
> If you want to allow auth code flow etc then perhaps the bff-token
> endpoint can return a standard error code with an authorization endpoint
> URI that the SPA then navigates the user to. (Eg the backend can do a PAR
> request first and return a URI that references that so that authorization
> details aren’t passed through the frontend).
>
> — Neil
>
>

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 11:07:26 +0000

Thanks Stoycho for your comment!
The TMI-BFF assumes that the interactive part of the flow (code grant for giving consent and getting access+refresh tokens, and anything necessary for establishing the session) occurs beforehand. It is not described in the spec itself, but it is expected that such flow (or extension grant with the same characteristics) happened.
HTH!
V.

From: OAuth <[email-masked]> on behalf of Stoycho Sleptsov <[email-masked]>
Date: Saturday, February 13, 2021 at 19:39
To: "[email-masked]" <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

Hello Mr. Bertocci,

I am a novice yet at APIs and OAuth, but nevertheless am entrusted by the executives of our organisation to expose some of the capabilities of our system through APIs. For that I have set out to implement an OAuth server (based on the 2.1 draft), which is basically functional now, and the corresponding APIs (resource servers). Our team will also have to implement some initial frontend applications which will
consume those exposed resources. I was exactly at the point of considering how to organise the correspondence of the access token from the auth server to the frontend and from the frontend to the
resource servers, when I received as a very nice surprise the news about tmi-bff draft. It was such a relief, as the option to delegate access token acquisition to a backend component, while still accessing resource servers directly from the frontend, seemed most suitable and
well balanced for our case.

In the description of the protocol flow (1.2), in the step of token request from backend to AS (step B), it mentions that the AS should "issue the requested token without requiring user interaction". Same
thing is reconfirmed in section 4, step 4: "the backend verifies whether it has the necessary artifacts to request it to the
authorization server without requiring user interaction".

But an initial interaction between the resource owner and the authorization server is required by the authorization code flow (section 1.3.1 of the draft-ietf-oauth-v2-1-01).

So where does this interaction fit in the tmi-bff protocol flow? Or tmi-bff is not supposed to be used with authorization code flow?

Thank you for your time,
hoping to hear from you,
Stoycho.

На пт, 12 фев 2021 г., 22:46 Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:[email-masked]>> написа:
Dear all,
Brian and yours truly are proposing a new specification that shows how the user agent frontend of a web app can delegate token acquisition and persistence to its backend, and request such tokens when needed for direct access of protected resources from the frontend code.

- It makes it possible to create interoperable SDKs, where frontend dev stacks (any JS flavor) can be mixed and matched with compliant backend stacks (middlewares in node, java, ASP.NET<http://ASP.NET>, PHP etc)

B&V

On 2/12/21, 12:41, "[email-masked]<mailto:[email-masked]>" <[email-masked]<mailto:[email-masked]>> wrote:

    Abstract:

    Please note that it may take a couple of minutes from the time of submission
    until the htmlized version and diff are available at tools.ietf.org<http://tools.ietf.org>.

    The IETF Secretariat

_______________________________________________
OAuth mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/oauth

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 11:28:52 +0000

Hi Neil,
Thanks for the prompt comments!

  *   Re: GET vs POST,
personally I’d be fine with restricting to POST.

  *   Re: RO-AS, interaction-
perhaps it is not very clear from the text at the moment (first draft), but that is assumed that the RO went thru whatever interactive steps are necessary to establish a session (eg sign in, assuming the AS is say an OIDC provider) and obtain beforehand the access token and refresh tokens that will be needed during the app activities taking place after  that. In concrete terms, imagine that the backend performs an authorization code grant requesting an IDtoken, access token and refresh token BEFORE the activities described in TMI-BFF take place.
The current language trying to express that is in 1.2:
As a prerequisite for the flow described below, the backend MUST have established a secure session with the user agent, so that all requests from that user agent toward the backend occur over HTTPS and carry a valid session artifact (such as a cookie) that the backend can validate. This document does not mandate any specific mechanism to establish and maintain that session.
And
cached, it requests to the authorization server a new access token with the required characteristics, using any artifacts previousy obtained (eg refresh token) and grants that will allow the authorization server to issue the requested token without requiring user interaction.

  *    If the backend is already implicitly trusted then couldn’t you skip OAuth and just get the backend to issue short-lived JWTs to the frontend that it can use for API access?
For the trusted part, see above. For the short lived JWTs, that’s not really an option. The most generic scenario addressed here is for APIs that accept tokens issued by the AS; the backend can request them as a client, but it cannot mint them. Imagine we’re talking about a SPA application that signs in users using Azure AD, and needs to call Office and Azure APIs. The SPA backend cannot issue tokens for those APIs, it can only request them to the Azure AD AS.

  *   If you want to allow auth code flow etc then perhaps the bff-token endpoint can return a standard error code with an authorization endpoint URI that the SPA then navigates the user to. (Eg the backend can do a PAR request first and return a URI that references that so that authorization details aren’t passed through the frontend).
We did consider adding something to that effect, an error message that can direct the frontend to perform the interactive portion necessary for this topology to work. It would be something similar to the IDP initiated login in OIDC, where the client offers an endpoint that is guaranteed to initiate a sign in flow (hence inject all the necessary nonces etc). We didn’t add it upfront and left it as exercise for the reader mostly because it’s not easy to model properly and before opening that work front we wanted to see how the idea was received.

From: OAuth <[email-masked]> on behalf of Neil Madden <[email-masked]>
Date: Sunday, February 14, 2021 at 00:17
To: Vittorio Bertocci <vittorio.bertocci=[email-masked]>
Cc: "[email-masked]" <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

— Neil

B&V

   Abstract:

   The IETF Secretariat

ForgeRock values your Privacy<https://www.forgerock.com/your-privacy>

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 12:48:19 +0100

>
> For the trusted part, see above. For the short lived JWTs, that’s not
> really an option. The most generic scenario addressed here is for APIs that
> accept tokens issued by the AS; the backend can request them as a client,
> but it cannot mint them. Imagine we’re talking about a SPA application that
> signs in users using Azure AD, and needs to call Office and Azure APIs. The
> SPA backend cannot issue tokens for those APIs, it can only request them to
> the Azure AD AS.

For UI related functionality, i.e. document selection, user profile
display/changes, contact updates, etc... You should be able to execute the
client side *silent authentication* using the provided session token from
the Azure AD AS, without needing to make any RO api calls nor user
redirects. For RO responsibilities, you can present the user with a button
"Grant RO access to Azure resources" button and the user will go through a
permission scope elevation flow, again no reason to need a BFF here.

We did consider adding something to that effect, an error message that can
> direct the frontend to perform the interactive portion necessary for this
> topology to work. It would be something similar to the IDP initiated login
> in OIDC, where the client offers an endpoint that is guaranteed to initiate
> a sign in flow (hence inject all the necessary nonces etc). We didn’t add
> it upfront and left it as exercise for the reader mostly because it’s not
> easy to model properly and before opening that work front we wanted to see
> how the idea was received.

It may make sense for the app to have an error message, or even better
might be a 302 *Location header* depending on what you are doing. There is
nothing here that is OAuth specific however (nor common), and then we
should challenge the need to directly provide an RFC recommendation for
handling this.

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 12:29 PM Vittorio Bertocci <vittorio.bertocci=
[email-masked]> wrote:

>    - Re: GET vs POST,
>    - Re: RO-AS, interaction-
>
> perhaps it is not very clear from the text at the moment (first draft),
> but that is assumed that the RO went thru whatever interactive steps are
> necessary to establish a session (eg sign in, assuming the AS is say an
> OIDC provider) and obtain beforehand the access token and refresh tokens
> that will be needed during the app activities taking place after  that. In
> concrete terms, imagine that the backend performs an authorization code
> grant requesting an IDtoken, access token and refresh token BEFORE the
> activities described in TMI-BFF take place.
>
> As a prerequisite for the flow described below, the backend MUST have
> established a secure session with the user agent, so that all requests from
> that user agent toward the backend occur over HTTPS and carry a valid
> session artifact (such as a cookie) that the backend can validate. This
> document does not mandate any specific mechanism to establish and maintain
> that session.
>
> And
>
> cached, it requests to the authorization server a new access token with
> the required characteristics, using any artifacts previousy obtained (eg
> refresh token) and grants that will allow the authorization server to issue
> the requested token without requiring user interaction.
>
>
>
>    -  If the backend is already implicitly trusted then couldn’t you skip
>    OAuth and just get the backend to issue short-lived JWTs to the frontend
>    that it can use for API access?
>
> For the trusted part, see above. For the short lived JWTs, that’s not
> really an option. The most generic scenario addressed here is for APIs that
> accept tokens issued by the AS; the backend can request them as a client,
> but it cannot mint them. Imagine we’re talking about a SPA application that
> signs in users using Azure AD, and needs to call Office and Azure APIs. The
> SPA backend cannot issue tokens for those APIs, it can only request them to
> the Azure AD AS.
>
>
>
>    - If you want to allow auth code flow etc then perhaps the bff-token
> We did consider adding something to that effect, an error message that can
> direct the frontend to perform the interactive portion necessary for this
> topology to work. It would be something similar to the IDP initiated login
> in OIDC, where the client offers an endpoint that is guaranteed to initiate
> a sign in flow (hence inject all the necessary nonces etc). We didn’t add
> it upfront and left it as exercise for the reader mostly because it’s not
> easy to model properly and before opening that work front we wanted to see
> how the idea was received.
>
>
>
> *From: *OAuth <[email-masked]> on behalf of Neil Madden <
> [email-masked]>
> *Date: *Sunday, February 14, 2021 at 00:17
> *To: *Vittorio Bertocci <vittorio.bertocci=[email-masked]>
> *Cc: *"[email-masked]" <[email-masked]>
> *Subject: *Re: [OAUTH-WG] Token Mediating and session Information Backend
> For Frontend (TMI BFF)
>
>
>

---

From: Dominick Baier <[email-masked]>
Date: Sun, 14 Feb 2021 12:06:04 +0000

Hi,

Just making sure I understand - in your protocol flow diagram step D it
looks like that the BFF is returning the access token to the front-end. Is
that correct?

My biggest concern with browser-based applications is that the JavaScript /
browser has access to the access token (don’t care if it is in-memory or
local storage) - but this exactly seems to happen in D.

Thanks
———
Dominick Baier

On 12. February 2021 at 21:46:20, Vittorio Bertocci (
vittorio.bertocci=[email-masked]) wrote:

Dear all,

Although the specification is very simple, providing explicit guidance on
the scenario offers many advantages.

B&V

On 2/12/21, 12:41, "[email-masked]" <[email-masked]>
wrote:

Abstract:

Please note that it may take a couple of minutes from the time of
submission
until the htmlized version and diff are available at tools.ietf.org.

The IETF Secretariat

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 13:24:42 +0100

>
> My biggest concern with browser-based applications is that the JavaScript
> / browser has access to the access token (don’t care if it is in-memory or

Unless the AS passes the token back in a HttpOnly cookie (which Oauth
doesn't technically support) it will always be available to Javascript in
browser, right?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 1:06 PM Dominick Baier <[email-masked]>
wrote:

> My biggest concern with browser-based applications is that the JavaScript
> / browser has access to the access token (don’t care if it is in-memory or

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 12:27:23 +0000

Hi Warren, thanks for the thoughtful comments.
Inline.

  *   . It introduces a pseudo AS-like proxy which now has all the requirements of an AS and more. While AS SDKs provide easy ways for client UIs to effectively deal with communication via the AS, there's no way for the AS to provide standard AS specific services prototypes to support BFF. That means that everyone is writing their own BFF AS-proxy.
TMI-BFF does provide a sort of proxy for the AS, but it is very constrained both in functionality (only one simple request type) and topology (only one requestor type, with assumptions about sessions, origin provenance etc) hence the requirements are a very limited subset of a full blown AS.
In terms of everyone doing their own implementation, the intent here is the exact opposite. By providing guidance on how to format requests/responses and what endpoints to refer to, the implementation details can be factored out from individual apps and stacks, facilitating interoperability.

  *   [..] Which isn't ever justified, but even if we accept that as a true premise, what are these AS doing that even require a BFF?
I am not sure how to interpret the statement about “ever justified”. This has little to do with the authorization server. Not every application can have a backend that exposes a façade replicating all the APIs the frontend need to invoke, for all sorts of reasons: maintenance, performance, skills of the developers involved, capabilities of the stacks of choice, and so on. This isn’t theoretical, I had this discussions many times with prospects and developers.

  *   Hypothetically you could argue that the auth code flow requires a BFF and that's required for user login since implicit flow no longer exists, but that isn't true. You can use client side PKCE for validation of these via not requiring the client secret in the front end, and then the problem there is solved.
In concrete terms, things are a bit more complicated than “a grant for SPAs already exist”. I am well aware that code+PKCE is a viable solution for SPAs to get access tokens, however that has its own challenges. For example, if you want to use refresh tokens in it, you need to sender constrain them or support refresh token rotation. If you check the current situation across the industry, you’ll see that very few SDKs actually do support rotation or sender constraint today- arguably introducing a new security issue. And of course, there’s the huge debacle about saving tokens in local storage- something that many applications need to do in order to offer the experience their customers require.
If a SPA app does not have a backend, code+PKCE is the only game in town. If it has a backend AND can leave all actual API calls to it, there’s no need to get tokens in the user agent.
But if you are in one situation where you do have a backend and cannot delegate API calls (see my preceding comment), then TMI-BFF can get tokens to your frontend without requiring complex javascript logic, without having to persist anything in local storage and without requiring the AS to support rotation or sender constraint. As long as the traffic with bff-token proxy is hardened, I would argue TMI-BFF might actually be easier to implement securely that code+PKCE+rotation/SC. Having access tokens in the frontend remains not great, but it seems that giving people who would do it anyway some guidance is better than leaving them at their own device- unless we conclude that this flow cannot be secured, in which case I agree we should explicitly idnciate this as anti pattern. But so far, it seems still to be demosntrated.

  *   There was also the argument of there are lots of people doing this, which is always a terrible argument, but even if we do permit that in the discussion, we still need to answer the why. Why are developers creating BFF for their frontends to communicate with an AS. Is it because AS are terrible, is it because front ends as a service are terrible, etc... Until we know why this is happening concretely, I don't think we should encourage further use of a pattern rife with potential security risks by telling everyone how you can do it (because the guidance we are offering doesn't even slightly increase safety).
The preceding comments should have shed more light about the why, and on some of the security concerns (there was one concern raised by Neil, and it seems there are possible mitigations in place) plus how this might actually increase safety in some aspects. But to add more color, one of the other reasons for which this is happening is because it’s simple. Backend OAUth/OIDC SDKs like middlewares and similar are very mature at this point, and they aren’t saddled by a lot of the complexity and uncertainly that browser based SDKs carry. Things like IE zones, ITP, SameSite and our own changing guidance (for good reasons) plus disomogeneous support from providers of the features required for the latest guidance create uncertainty and complexity that many non-initiated won’t put up with. Add to this that the more app development moves to the frontend, the more you don’t get full stack developers and getting a frontend developer to deal with all those quirks is hard. Getting tokens thru well supported middlewares and forward them to the frontend is simple.
Also, to be clear. This exact topology has been considered discussed in the past during IETF meetings, in Montreal we had a discussion about including it in some BCP and whether we should have a mechanism for the client to signal to the AS that the tokens will be used by code executing in a weaker security context (user agent) than the requestor’s (confidential client on backed). I am sure we can find the minutes of that. This isn’t something completely left field.

  *   Further, even if we were to accept this pattern and want to create a standard around it, we are effectively creating an AS proxy here, which means we should require it to act like an AS, and delegate the specification of resources, endpoints, terminology, and patterns to existing or future AS related RFCs.
I don’t believe that the scope of the proposal warrants doing al that. Could you point at the area in the spec that suggest we’d need to add anything beyond what’s suggested at the moment to achieve the stated goals?

  *   And therefore in conclusion we should focus only on the aspects that are absolutely required which aren't already present in some form in existing AS related RFCs, but what are those?
I am still missing how this has to do with missing AS functionality. One of the things we tried to do was not to require any change to the AS. The problem being solved here is how to allow javascript developers to call API directly from their frontend when they have a backend with basic oauth capabilities at their disposal, in the simplest possible way. Changes in the AS doen’t appear to be necessary there

  *   The one counterpoint to all of this is the potential introduction of domain specific cookie language (which doesn't exist in the current draft). Concretely, let's add a response_type=cookie, to AS to support domain first-party cookies and session management.
Could you expand on how you envision this would work/solve the problems described above?

From: Warren Parad <wparad=[email-masked]>
Date: Sunday, February 14, 2021 at 01:51
To: Neil Madden <[email-masked]>
Cc: Vittorio Bertocci <[email-masked]>, oauth <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

I also flat out reject the premise of this draft. It introduces a pseudo AS-like proxy which now has all the requirements of an AS and more. While AS SDKs provide easy ways for client UIs to effectively deal with communication via the AS, there's no way for the AS to provide standard AS specific services prototypes to support BFF. That means that everyone is writing their own BFF AS-proxy.

Additionally, I too am lacking the clarity on the WHY. The only thing mentioned in the draft is
That approach is not always viable, as in the absence of reverse proxy deployments the creation and maintenance of a facade for multiple APIs can be expensive
Which isn't ever justified, but even if we accept that as a true premise, what are these AS doing that even require a BFF?

Hypothetically you could argue that the auth code flow requires a BFF and that's required for user login since implicit flow no longer exists, but that isn't true. You can use client side PKCE for validation of these via not requiring the client secret in the front end, and then the problem there is solved. And if you argue that this can't be done, then the solution is introducing a better way to handle this so that a BFF for AS flows don't have to exist.

There was also the argument of there are lots of people doing this, which is always a terrible argument, but even if we do permit that in the discussion, we still need to answer the why. Why are developers creating BFF for their frontends to communicate with an AS. Is it because AS are terrible, is it because front ends as a service are terrible, etc... Until we know why this is happening concretely, I don't think we should encourage further use of a pattern rife with potential security risks by telling everyone how you can do it (because the guidance we are offering doesn't even slightly increase safety).

Further, even if we were to accept this pattern and want to create a standard around it, we are effectively creating an AS proxy here, which means we should require it to act like an AS, and delegate the specification of resources, endpoints, terminology, and patterns to existing or future AS related RFCs. (We already have a problem with the current draft as it attempts to redefine and introduce new terms/patterns that have the same functionality as existing ones in the AS, yet fail to capture the full importance of the original RFCs. This is bad duplication). And therefore in conclusion we should focus only on the aspects that are absolutely required which aren't already present in some form in existing AS related RFCs, but what are those?

The one counterpoint to all of this is the potential introduction of domain specific cookie language (which doesn't exist in the current draft). Concretely, let's add a response_type=cookie, to AS to support domain first-party cookies and session management. When we built our AS we explicitly added this so that services can use the JWT found in the HttpOnly SameSite=Strict cookie as a security measure against XSS attacks that attempt to exfiltrate access tokens. That's a potential suggestion I would favor, although I still can't know if that solves the problem being presented in the draft.

- Warren

[Image removed by sender.]

Warren Parad

Founder, CTO
Secure your user data and complete your authorization architecture. Implement Authress<https://authress.io>.

On Sun, Feb 14, 2021 at 9:18 AM Neil Madden <[email-masked]<mailto:[email-masked]>> wrote:
I have a lot of security concerns about this draft.

The draft alludes to security issues associated with handling access tokens in the frontend but never really spells them out. >From the Security Considerations it seems that the primary concern is with theft of access tokens from local storage. To do this you’d need an XSS attack. But in that case, wouldn’t the attacker simply use the XSS to make a call to the bff-token endpoint instead?

— Neil

On 12 Feb 2021, at 20:46, Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:[email-masked]>> wrote:
Dear all,
Brian and yours truly are proposing a new specification that shows how the user agent frontend of a web app can delegate token acquisition and persistence to its backend, and request such tokens when needed for direct access of protected resources from the frontend code.

B&V

   Abstract:

   The IETF Secretariat

ForgeRock values your Privacy<https://www.forgerock.com/your-privacy>_______________________________________________
OAuth mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/oauth

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 12:32:57 +0000

*   For UI related functionality, i.e. document selection, user profile display/changes, contact updates, etc... You should be able to execute the client side silent authentication using the provided session token from the Azure AD AS, without needing to make any RO api calls nor user redirects.
Can you expand on what silent authentication and session token stands for here? If you are referring to the iframe scenario, the new browser measures make it problematic. In code+PKCE you can use a refresh token, but see the other reply for how this proposal is an alternative to that in some situations. This answer was specifically on why having backend-issued tokens didn’t apply to this scenario.

From: Warren Parad <wparad=[email-masked]>
Date: Sunday, February 14, 2021 at 03:48
To: Vittorio Bertocci <[email-masked]>
Cc: Neil Madden <[email-masked]>, "[email-masked]" <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

For UI related functionality, i.e. document selection, user profile display/changes, contact updates, etc... You should be able to execute the client side silent authentication using the provided session token from the Azure AD AS, without needing to make any RO api calls nor user redirects. For RO responsibilities, you can present the user with a button "Grant RO access to Azure resources" button and the user will go through a permission scope elevation flow, again no reason to need a BFF here.

We did consider adding something to that effect, an error message that can direct the frontend to perform the interactive portion necessary for this topology to work. It would be something similar to the IDP initiated login in OIDC, where the client offers an endpoint that is guaranteed to initiate a sign in flow (hence inject all the necessary nonces etc). We didn’t add it upfront and left it as exercise for the reader mostly because it’s not easy to model properly and before opening that work front we wanted to see how the idea was received.
It may make sense for the app to have an error message, or even better might be a 302 Location header depending on what you are doing. There is nothing here that is OAuth specific however (nor common), and then we should challenge the need to directly provide an RFC recommendation for handling this.

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 12:29 PM Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:[email-masked]>> wrote:
Hi Neil,
Thanks for the prompt comments!

  *   Re: GET vs POST,

From: OAuth <[email-masked]<mailto:[email-masked]>> on behalf of Neil Madden <[email-masked]<mailto:[email-masked]>>
Date: Sunday, February 14, 2021 at 00:17
To: Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:[email-masked]>>
Cc: "[email-masked]<mailto:[email-masked]>" <[email-masked]<mailto:[email-masked]>>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

— Neil

B&V

   Abstract:

   The IETF Secretariat

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 12:35:18 +0000

Correct, the access token ends up in the JavaScript – the outcome is the same as code+PKCE, the access token end up in the user agent. The main difference is that some of the functionality is now outsourced to the backend but the calls to the RS still take place from the user agent.

From: Dominick Baier <[email-masked]>
Date: Sunday, February 14, 2021 at 04:06
To: Vittorio Bertocci <[email-masked]>, Brian Campbell <[email-masked]>, "[email-masked]" <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

Hi,

Just making sure I understand - in your protocol flow diagram step D it looks like that the BFF is returning the access token to the front-end. Is that correct?

My biggest concern with browser-based applications is that the JavaScript / browser has access to the access token (don’t care if it is in-memory or local storage) - but this exactly seems to happen in D.

Thanks
———
Dominick Baier

On 12. February 2021 at 21:46:20, Vittorio Bertocci (vittorio.bertocci=[email-masked]<mailto:vittorio.bertocci=[email-masked]>) wrote:
Dear all,
Brian and yours truly are proposing a new specification that shows how the user agent frontend of a web app can delegate token acquisition and persistence to its backend, and request such tokens when needed for direct access of protected resources from the frontend code.

B&V

Abstract:

The IETF Secretariat

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 12:53:55 +0000

One thing I should add here, and then I’ll head to bed given that it’s almost 5am here 😊-
I am fully behind code+PKCE. Auth0 has been supporting code+PKCE in its JS SPA SDKs, including refresh token rotation support, since early last year.
I stress this so that no one thinks this an attempt to get out of supporting code+PKCE, it’s not. For true SPAs (no backend) that remains the main way for enabling frontents to call API. This is  more about trying to take advantage of the presence of the backend to make things simpler when viable, and to bring some guidance to emerging practices that risk drifting into insecure waters without it.

From: Vittorio Bertocci <[email-masked]>
Date: Sunday, February 14, 2021 at 04:27
To: Warren Parad <wparad=[email-masked]>, Neil Madden <[email-masked]>
Cc: oauth <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

- Warren

Warren Parad

Founder, CTO

— Neil

B&V

   Abstract:

   The IETF Secretariat

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 13:54:06 +0100

>
> Can you expand on what silent authentication and session token stands for
> here? If you are referring to the iframe scenario, the new browser measures
> make it problematic.

Which new browser measures?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 1:33 PM Vittorio Bertocci <vittorio.bertocci=
[email-masked]> wrote:

>
>    - For UI related functionality, i.e. document selection, user profile
>    client side *silent authentication* using the provided session token
>    from the Azure AD AS, without needing to make any RO api calls nor user
>    redirects.
>
> Can you expand on what silent authentication and session token stands for
> here? If you are referring to the iframe scenario, the new browser measures
> make it problematic. In code+PKCE you can use a refresh token, but see the
> other reply for how this proposal is an alternative to that in some
> situations. This answer was specifically on why having backend-issued
> tokens didn’t apply to this scenario.
>
>
>
>
>
> *From: *Warren Parad <wparad=[email-masked]>
> *Date: *Sunday, February 14, 2021 at 03:48
> *To: *Vittorio Bertocci <[email-masked]>
> *Cc: *Neil Madden <[email-masked]>, "[email-masked]" <
> [email-masked]>
> might be a 302 *Location header* depending on what you are doing. There
> is nothing here that is OAuth specific however (nor common), and then we
> *Warren Parad*

---

From: Stoycho Sleptsov <[email-masked]>
Date: Sun, 14 Feb 2021 15:48:04 +0200

I would like to add my reasons about the "Why are developers creating BFF
for their frontends to communicate with an AS",
with the objective to verify if they are valid.

I need the client app. to be authenticated at the AS (to determine if it is
a first-party app., for example).
If we decide to implement our client as a frontend SPA , then we have no
other option except through a BFF, as PKCE does not help for authentication.

Or is it considered a bad practice to do that?

Regards,
Stoycho.

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 14:53:21 +0100

Why doesn't PKCE help for authentication?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 2:48 PM Stoycho Sleptsov <[email-masked]>
wrote:

> I need the client app. to be authenticated at the AS (to determine if it
> is a first-party app., for example).

---

From: Stoycho Sleptsov <[email-masked]>
Date: Sun, 14 Feb 2021 16:10:42 +0200

If I understood correctly, PKCE try to guarantee that the app which
requests the access token in exchange for authorization code is the
same as the application which initiated the authorization request, but
it cannot help to guarantee which app exactly that is (as per section
2.3 of the draft-ietf-oauth-v2-1-01, through mTLS, Basic
authentication with client secret, "private_key_jwt", or other means).

On Sun, 14 Feb 2021 at 15:53, Warren Parad <[email-masked]> wrote:
> Secure your user data and complete your authorization architecture. Implement Authress.
>
>
> On Sun, Feb 14, 2021 at 2:48 PM Stoycho Sleptsov <[email-masked]> wrote:
>>
>> I would like to add my reasons about the "Why are developers creating BFF for their frontends to communicate with an AS",
>> I need the client app. to be authenticated at the AS (to determine if it is a first-party app., for example).
>> If we decide to implement our client as a frontend SPA , then we have no other option except through a BFF, as PKCE does not help for authentication.
>>

---

From: Torsten Lodderstedt <[email-masked]>
Date: Sun, 14 Feb 2021 15:11:48 +0100

Hi,

I’m trying to understand your proposal. 

Section 1.2, bullet (B) states

(B) If the backend does not already have a suitable access token
      obtained in previous flows and cached, it requests to the
      authorization server a new access token with the required
      characteristics, using any artifacts previousy obtained (eg
      refresh token) and grants that will allow the authorization server
      to issue the requested token without requiring user interaction.

Can you please explain how the authorization process works towards the AS, especially in case of the authorisation code grant type. I would have expected to frontend to pass an authorisation code to the bff-token request. 

But section 4.1. only defines the parameters „resource" and „scope" for the bff-token endpoint. 

thanks,
Torsten. 

> Am 12.02.2021 um 21:46 schrieb Vittorio Bertocci <vittorio.bertocci=[email-masked]>:
> 
> Dear all,
>    URL:            https://www.google.com/url?q=https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.txt&source=gmail-imap&ust=1613767591000000&usg=AOvVaw3Rb-S0l6cEv0ytjDxtYLAP
>    Status:         https://www.google.com/url?q=https://datatracker.ietf.org/doc/draft-bertocci-oauth2-tmi-bff/&source=gmail-imap&ust=1613767591000000&usg=AOvVaw3-qg5MDtY7kD1HpR5jR2QY
>    Html:           https://www.google.com/url?q=https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.html&source=gmail-imap&ust=1613767591000000&usg=AOvVaw05WK4GSEKcWjZzNhvb1p5d
>    Htmlized:       https://www.google.com/url?q=https://tools.ietf.org/html/draft-bertocci-oauth2-tmi-bff-00&source=gmail-imap&ust=1613767591000000&usg=AOvVaw0qm45MWGbZf0zbBjZj3ggz
> 
> 
>    Abstract:
> https://www.google.com/url?q=https://www.ietf.org/mailman/listinfo/oauth&source=gmail-imap&ust=1613767591000000&usg=AOvVaw1Bfu9fJ2Fj_BZJ3H9yw7od

---

From: Neil Madden <[email-masked]>
Date: Sun, 14 Feb 2021 14:28:08 +0000

Public clients are implicitly authenticated by their ownership of the registered redirect_uri. This why it’s important to use a redirect_uri for which ownership can be reasonably established, such as HTTPS endpoints with exact URI matching. 

There are more things that can go wrong with that (see the security BCP), but it can be made reasonably secure. 

— Neil

> On 14 Feb 2021, at 13:48, Stoycho Sleptsov <[email-masked]> wrote:
> 
>

---

From: Stoycho Sleptsov <[email-masked]>
Date: Sun, 14 Feb 2021 16:51:17 +0200

Thanks a lot for your answer Neil,

as I am no expert (yet :-)) in security I was afraid to rely on
redirect_uri for authentication of the client,
but I will consider that option as more trustworthy now.

(it is also not very clear for me which part of the app can be
regarded as the redirect_uri owner, the BFF or the loaded frontend
SPA, but maybe it is not so important)

If you had the two options for authentication of the frontend SPA
client - the redirect_uri on the one hand, and the Basic
authentication with client secret through the BFF on the other, which
one would you recommend?

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 16:35:20 +0100

redirect_uri and use PKCE via the code verifier.

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 3:51 PM Stoycho Sleptsov <[email-masked]>
wrote:

> > Public clients are implicitly authenticated by their ownership of the
> registered redirect_uri. This why it’s important to use a redirect_uri for
> which ownership can be reasonably established, such as HTTPS endpoints with
> exact URI matching.
> >
> > There are more things that can go wrong with that (see the security
> BCP), but it can be made reasonably secure.
> >
> > — Neil
> >
> > > I would like to add my reasons about the "Why are developers creating
> BFF for their frontends to communicate with an AS",
> > > If we decide to implement our client as a frontend SPA , then we have
> no other option except through a BFF, as PKCE does not help for
> authentication.
> > >

---

From: Stoycho Sleptsov <[email-masked]>
Date: Sun, 14 Feb 2021 19:27:15 +0200

Thanks Warren,

as I see you and Neil have the same idea,
but as of this moment I think this method is not a valid option for
authenticating
a client according to the draft-ietf-oauth-v2-1.

On the other hand, authenticating the client through the BFF
seems conforming to the spec., but in the case when the access token is used
in the browser in fact, I am afraid that it can be regarded as
some kind of "deception" of the AS.

It seems the frontend SPA is not the easiest way to go with oauth...

Stoycho.

On Sun, 14 Feb 2021 at 17:35, Warren Parad <[email-masked]> wrote:

> On Sun, Feb 14, 2021 at 3:51 PM Stoycho Sleptsov <
> [email-masked]> wrote:
>

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 18:44:55 +0100

Correct it would never need to be used to authenticate a client, as a
client is always offline and can directly use the backchannel. You would
never need the front channel to authenticate a client, however you might
need the front channel to authorize a client to access user resources
offline. Is that what you are talking about, i.e. the offline refresh_token
authorization code flow?

If yes, then the standard would be to use the authorization code flow
requesting as you've mentioned. Although that flow already exists and well
established, and without any issues, having a standard specifying how to
communicate with the client doesn't seem to be useful, as you only need to
pass an *auth code* and the *issuer* to the client. But since these
endpoints are never exposed nor need to have interoperability between
different owners (i.e. the owner of the front-channel is different from the
owner of the back-channel), what's the benefit of specifying the explicit
endpoints necessary for the BFF to have?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 6:27 PM Stoycho Sleptsov <[email-masked]>
wrote:

>>> > > I would like to add my reasons about the "Why are developers
>>> creating BFF for their frontends to communicate with an AS",
>>> > > I need the client app. to be authenticated at the AS (to determine
>>> if it is a first-party app., for example).
>>> > > If we decide to implement our client as a frontend SPA , then we
>>> have no other option except through a BFF, as PKCE does not help for
>>> authentication.
>>> > >

---

From: Neil Madden <[email-masked]>
Date: Sun, 14 Feb 2021 18:30:47 +0000

Within the spec “client authentication” refers to explicit authentication of the client using credentials. But you said initially that you wanted this to “determine if it is a first-party app, for example”. You can determine this based on the redirect_uri and the fact that only the legitimate client can receive an authorization code at that redirect_uri (if its HTTPS, exact matching of URIs, etc). This is what I refer to as implicit authentication - the AS knows at the point of auth code exchange that only the legitimate client could have obtained that code. 

(This is not true for mobile clients using private-use URI schemes).

Note that for both public and confidential clients, the confirmation of the client identity happens after the user has gone through the authorization flow. PAR fixes this for confidential clients, but not public ones. So that is one reason to prefer a BFF pattern and a confidential client. 

Confidential clients also have an extra layer of defence in depth: they need a redirect_uri *and* client credentials. So that is another reason to use a confidential client and BFF. 

A backend server may also have a more reliable connection to the AS. So that may also be a good reason to use a BFF - eg to avoid having to reauthorize with the user because an auth code or refresh request timed out due to a flaky network connection. 

So there may be many good reasons to use a BFF pattern. But if you just want a reasonable assurance of client identity at the point of issuing tokens, then IMO a public client + PKCE is fine for many cases. 

— Neil

> On 14 Feb 2021, at 17:27, Stoycho Sleptsov <[email-masked]> wrote:
> 
> Thanks Warren,
> 
> but as of this moment I think this method is not a valid option for authenticating
>> On Sun, Feb 14, 2021 at 3:51 PM Stoycho Sleptsov <[email-masked]> wrote:

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 18:57:25 +0000

ITP, for example

Date: Sunday, February 14, 2021 at 04:54

Can you expand on what silent authentication and session token stands for here? If you are referring to the iframe scenario, the new browser measures make it problematic.
Which new browser measures?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 1:33 PM Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:[email-masked]>> wrote:

From: Warren Parad <wparad=[email-masked]<mailto:[email-masked]>>
Date: Sunday, February 14, 2021 at 03:48
To: Vittorio Bertocci <[email-masked]<mailto:[email-masked]>>
Cc: Neil Madden <[email-masked]<mailto:[email-masked]>>, "[email-masked]<mailto:[email-masked]>" <[email-masked]<mailto:[email-masked]>>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

Error! Filename not specified.

Warren Parad

Founder, CTO

  *   Re: GET vs POST,

— Neil

B&V

   Abstract:

   The IETF Secretariat

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 19:19:17 +0000

Hi Torsten, thanks for looking into this!
The idea is that the application backend performed all the interactive token acquisition steps before TMI-BFF come into play.
Imagine that a regular web app performs an authorization code grant, requesting access token and refresh token in the process (and often also setting its own session with the user agent in the process, if the AS is also their IdP via OIDC or similar, but that's not strictly necessary). Now the app backend has an access token and refresh token persisted on the server side.
All TMI-BFF does is to describe how the backend can share those tokens with its fronted, either directly (if the persisted AT is still valid) or indirectly (if it has to use an RT to obtain a new AT before sending it back).
The frontend provides resource and scope to select what token it needs, but the current idea is that the backend already obtained both consent and artifacts to obtain those tokens from the AS. And if it doesn't, at the moment we simply fail and expect the app developer to take the steps required to prompt the user with whatever is necessary for updating the backend with the right permissions, eg creating a new authorization request asking for a scope the frontend needs and that the user wasn't prompted to consent yet. At the moment TMI-BFF does not provide a mechanism for that prompt to occur, it just errors out saying "you've got to  update your authorization artifacts before the frontend can get the token w the scopes it needs".
Another way to think about this: in TMI-BFF the frontend treats the backend is a tokens database. Indicating the resource and scopes is a query. If the backend can serve that query (with the ATs it saved, or by using the RTs it saved AND the grants the user already gave) it returns a token. If it doesn't, it fails the query. The frontend does not play a direct role into inserting in the DB more tokens. That is left to the backend, that can do so by initiating a new authorization grant, not described in TMI-BFF, that must conclude successfully for the frontend to be able to repeat its query and this time get the token they want out. Note that the backend might decide that it won’t try to get the token requested, or it might unable to do so (eg the user/app cannot meet some requirements as the AS is concerned), hence the request of it might at times be permanently denied. This last part is to say that providing in the error message details about the remediation might take more work than one realizes at first, and ultimately acting on the error situation to retrieve a new token is still up to the backend anyway, hence providing elaborate machinery to inform the frontend beyond the error situation might not be as effective as it might look at first glance. I am totally open to it, just making sure we understand what it can buy us.  

On 2/14/21, 06:11, "Torsten Lodderstedt" <torsten=[email-masked]> wrote:

    Hi,

    

    
    thanks,
    Torsten.

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 19:38:56 +0000

In the TMI-BFF topology, the backend and frontend developer are the same person. The operations TMI-BFF describes are the functional equivalent of what the JS code of one SPA app using a code+PKCE SDK would do when retrieving previously obtaining tokens from the store in order to perform an API call. Whereas such an app would make that call in memory (and result in the same operations described here, either use a previously saved access token matching the requirements of the API call, or use artifacts like RTs to request a new access token matching the request) in TMI-BFF al the logic and persistence layer are in the backend, hence that query becomes a request to the backend instead of a local function call.
The advantages have been described in other branches of this thread, but TL;DR- a lot of the token requesting work can be performed more reliably (eg less things can go wrong) from a confidential client and it’s easier for SDK developers to package it (see existing middlewares vs JS SDKs). Note that for the app developer this might still look like the same flow, asking a JS SDK to get the token the app needs to call an API, but the JS SDK would be dramatically simpler than the one performing code+PKCE in the user agent and entail communication between frontend a backend, hence the need to define how that communication happens if we want developers to be able to mix and match frontend and backend dev stacks.
Again, this does not necessarily add security to the code+PKCE in the user agent model (which remains the only game in town for backendless SPAs), but it does make things simpler for the frontend developer and requires less advanced capabilities in the AS.

From: Warren Parad <[email-masked]>
Date: Sunday, February 14, 2021 at 09:45
To: Stoycho Sleptsov <[email-masked]>
Cc: Neil Madden <[email-masked]>, Vittorio Bertocci <[email-masked]>, oauth <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

Correct it would never need to be used to authenticate a client, as a client is always offline and can directly use the backchannel. You would never need the front channel to authenticate a client, however you might need the front channel to authorize a client to access user resources offline. Is that what you are talking about, i.e. the offline refresh_token authorization code flow?

If yes, then the standard would be to use the authorization code flow requesting as you've mentioned. Although that flow already exists and well established, and without any issues, having a standard specifying how to communicate with the client doesn't seem to be useful, as you only need to pass an auth code and the issuer to the client. But since these endpoints are never exposed nor need to have interoperability between different owners (i.e. the owner of the front-channel is different from the owner of the back-channel), what's the benefit of specifying the explicit endpoints necessary for the BFF to have?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 6:27 PM Stoycho Sleptsov <[email-masked]<mailto:[email-masked]>> wrote:
Thanks Warren,

Stoycho.

On Sun, 14 Feb 2021 at 17:35, Warren Parad <[email-masked]<mailto:[email-masked]>> wrote:
redirect_uri and use PKCE via the code verifier.

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 3:51 PM Stoycho Sleptsov <[email-masked]<mailto:[email-masked]>> wrote:
Thanks a lot for your answer Neil,

On Sun, 14 Feb 2021 at 16:28, Neil Madden <[email-masked]<mailto:[email-masked]>> wrote:
> > On 14 Feb 2021, at 13:48, Stoycho Sleptsov <[email-masked]<mailto:[email-masked]>> wrote:
> >
> >

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 20:40:07 +0100

That only applies to third party cookies, it shouldn't affect third-party
iframes as far as I'm aware. So unless we expect those to break, we
probably shouldn't include that as a driving use case. Is there another
measure that would be relevant here?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 7:57 PM Vittorio Bertocci <vittorio.bertocci=
[email-masked]> wrote:

> *Date: *Sunday, February 14, 2021 at 04:54
> *Error! Filename not specified.*
>
> *Warren Parad*
>
> Founder, CTO
>

---

From: Torsten Lodderstedt <[email-masked]>
Date: Sun, 14 Feb 2021 20:45:28 +0100

Hi Vittorio,

thanks for the explanation. Do you assume the frontend passes the code or initial refresh token to the backend using an application specific mechanism? Why isn’t this part of the bff-token request?

best regards,
Torsten.

> Am 14.02.2021 um 20:19 schrieb Vittorio Bertocci <vittorio.bertocci=[email-masked]>:
> 
>>   URL:            https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.txt%26source%3Dgmail-imap%26ust%3D1613767591000000%26usg%3DAOvVaw3Rb-S0l6cEv0ytjDxtYLAP&source=gmail-imap&ust=1613935165000000&usg=AOvVaw3p5263a_rEePNbnX7jWFjq
>>   Status:         https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://datatracker.ietf.org/doc/draft-bertocci-oauth2-tmi-bff/%26source%3Dgmail-imap%26ust%3D1613767591000000%26usg%3DAOvVaw3-qg5MDtY7kD1HpR5jR2QY&source=gmail-imap&ust=1613935165000000&usg=AOvVaw1YZmVHpENHa-bqqtbezRpa
>>   Html:           https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.html%26source%3Dgmail-imap%26ust%3D1613767591000000%26usg%3DAOvVaw05WK4GSEKcWjZzNhvb1p5d&source=gmail-imap&ust=1613935165000000&usg=AOvVaw2HibfQtTYv3talGT379MOu
>>   Htmlized:       https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://tools.ietf.org/html/draft-bertocci-oauth2-tmi-bff-00%26source%3Dgmail-imap%26ust%3D1613767591000000%26usg%3DAOvVaw0qm45MWGbZf0zbBjZj3ggz&source=gmail-imap&ust=1613935165000000&usg=AOvVaw0gZZ0ZU8QVx7OBjxDcG8d-
>> 
>> 
>>   Abstract:
>> https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.ietf.org/mailman/listinfo/oauth%26source%3Dgmail-imap%26ust%3D1613767591000000%26usg%3DAOvVaw1Bfu9fJ2Fj_BZJ3H9yw7od&source=gmail-imap&ust=1613935165000000&usg=AOvVaw3a73buBtPOBoDQ3SMH_XJW
> 
>

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 20:57:07 +0100

>
> but it does make things simpler for the frontend developer and requires
> less advanced capabilities in the AS.

I guess I'm still getting lost on this point, which seems not yet justified
for me. What is the frontend developer doing any different in the new
hypothetical world than they would be, right now they are including an SDK
and writing one line of code on login redirect/silent auth and one line of
code for PKCE+code validation. If a service client needs to be authorized
there would be a third line of code to call the backend. These three lines
still need to be present irrespective of whether you use an AS-proxy
TMI-BFF or the AS directly. Except now we are encouraging every app to
write a BFF and integrate their front channel with it.

Additionally, we aren't requiring less capabilities from the spec, we are
just also requiring additional ones for a BFF. If there are capabilities
this lets us drop from OAuth could you explain which ones those are,
because since an AS can't know whether "customers" are going to want to use
a BFF or not, it will still have to implement all the necessary AS features
that already exist (and the new ones that don't). I don't see how this
affords an AS any additional freedom.

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 8:39 PM Vittorio Bertocci <
[email-masked]> wrote:

> In the TMI-BFF topology, the backend and frontend developer are the same
> person. The operations TMI-BFF describes are the functional equivalent of
> what the JS code of one SPA app using a code+PKCE SDK would do when
> retrieving previously obtaining tokens from the store in order to perform
> an API call. Whereas such an app would make that call in memory (and result
> in the same operations described here, either use a previously saved access
> token matching the requirements of the API call, or use artifacts like RTs
> to request a new access token matching the request) in TMI-BFF al the logic
> and persistence layer are in the backend, hence that query becomes a
> request to the backend instead of a local function call.
>
> The advantages have been described in other branches of this thread, but
> TL;DR- a lot of the token requesting work can be performed more reliably
> (eg less things can go wrong) from a confidential client and it’s easier
> for SDK developers to package it (see existing middlewares vs JS SDKs).
> Note that for the app developer this might still look like the same flow,
> asking a JS SDK to get the token the app needs to call an API, but the JS
> SDK would be dramatically simpler than the one performing code+PKCE in the
> user agent and entail communication between frontend a backend, hence the
> need to define how that communication happens if we want developers to be
> able to mix and match frontend and backend dev stacks.
>
> Again, this does not necessarily add security to the code+PKCE in the user
> agent model (which remains the only game in town for backendless SPAs), but
> it does make things simpler for the frontend developer and requires less
> advanced capabilities in the AS.
>
>
>
> *From: *Warren Parad <[email-masked]>
> *Date: *Sunday, February 14, 2021 at 09:45
> *To: *Stoycho Sleptsov <[email-masked]>
> *Cc: *Neil Madden <[email-masked]>, Vittorio Bertocci <
> [email-masked]>, oauth <[email-masked]>
> On Sun, Feb 14, 2021 at 6:27 PM Stoycho Sleptsov <

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 20:20:41 +0000

Let me rewind a bit here. This was never presented as driving use case.

  *   Neil suggested that the backend could simply give short lived JTWs for the frontent to call API.
  *   I clarified that this would not be viable in the general case and provided an example scenario where backend issued short lived tokens would not have worked
  *   You commented that the frontend can obtain AS tokens from JS and mentioned silent authentication. I clarified (or tried to) that this offshoot of the discussion wasn’t to say that there is no viable way of doing the scenario already, and by the way using an iFrame to do silent authentication is now problematic. At this point we are no longer discussing TMI-BFF, but current affairs in the authentication world. The fact that we are proposing TMI-BFF and the fact that silent authentication is less and less viable are independent facts, the former isn’t meant to be a solution for the latter (it’s already addressed by using RTs in coke+PKCE)

That clarified. Not only we expect ITP to affect silent authentication, it has been affected for the past year and that has been one of the primary business drivers for the rapid adoption of code+PKCE+RTs in the user agent, as customers with pure SPAs found themselves unable to renew tokens without prompting as their access to cookies in flows driven by iframes became less and less reliable.
When ITP was introduced we put many companies together to try to get Apple to change it (you can find the doc in https://docs.google.com/document/d/1Rs--DFzZj_SfQjtz8oH9DlLII0ra3viMEHrK7sKsaiU/edit#heading=h.p3nvp6xmxvzf) but they didn’t bulge and ultimately the introduction of RTs in user agent code (albeit with extra restrictions, the one I mentioned not everyone is following) made the problem manageable. We have an initiative cross working groups (IETF, OIDC etc)for working with browser vendors to try containing similar regressions in the future. For a summary of similar problems see https://identiverse.gallery.video/detail/video/6184443037001/browser-features-vs-identity-protocols.

To restate, the TMI-BFF proposal is not trying to fix any of that, nor per the above some of it need fixing. The only indirect connection might be that less stuff happening in the user agent means less opportunities for similar changes to impact the flows, but it’s definitely not a top level driver.

Date: Sunday, February 14, 2021 at 11:41

That only applies to third party cookies, it shouldn't affect third-party iframes as far as I'm aware. So unless we expect those to break, we probably shouldn't include that as a driving use case. Is there another measure that would be relevant here?

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 7:57 PM Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:[email-masked]>> wrote:
ITP, for example

Warren Parad

Founder, CTO

Warren Parad

Founder, CTO

  *   Re: GET vs POST,

— Neil

B&V

   Abstract:

   The IETF Secretariat

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 20:35:48 +0000

Thanks!
I expect the frontend (as in JS code) not to kick in until the initial authorization has been perfomed. Breaking it down as a classic possible flow:

- User navigates to the app page, clicks "sign in"
- The backend redirects the user to the AS to perform a code grant (for the sake of argument let's also say they ask for an IDtoken as well tho it isn’t strictly necessary), with the purpose of gathering consent for the scopes required. No frontend code involved. 
- The code grant concludes successfully, the backend now has a session with the user agent and an AT, RT stored on the server side
- --> here TMI-BFF begins. Whenever the frontend needs a token to call an API, they use TMI-BFF to ask for that token to the backend
- if the backend can return the requested token, via stored AT or by using the RT, it does it
- if the backend cannot get the requested token with what it already has without suer interaction, it fails
--> here there's where TMI-BFF ends- it's up to the backend to decide how to meet the new requirements, eg by triggering another authorization code grant for new scopes. The frontend is not involved apart from perhaps offering affordances to the end upper to start such process

TMI-BFF does not include the actual authorization requests mostly for simplicity. We don’t really know how the app is structured nor the reasons for which a backend might be unable to get the requested token. The RT might be expired; or the current scopes might be insufficient; or the AS might decide that now issuing an AT with that scope might require a different authentication method; and many other reasons I can’t think of. If we were to provide a mechanism that includes in the error message indications on what the frontent should do to remediate the error, we might need to either scope down the scenarios or create a very flexible mechanism. I am not opposed, but before venturing into that we wanted to see what the reaction would be.  

On 2/14/21, 11:45, "Torsten Lodderstedt" <torsten=[email-masked]> wrote:

    Hi Vittorio,

    best regards,
    Torsten.

---

From: Warren Parad <[email-masked]>
Date: Sun, 14 Feb 2021 21:59:27 +0100

>
> To restate, the TMI-BFF proposal is not trying to fix any of that... it’s
> definitely not a top level driver.

Great, then we are back to: what is the top level driver. Because, while I
appreciate the circumstances around ITP2.1~ as I fully understand how
identity providers like Auth0 are using iframes and thirdparty cookies,
this problem vanishes with the use of first-party domains. So let's skip
the digression and assume we aren't solving ITP future related issues.

The real problem I have with the draft is that it essentially suggests that
every app needs to run a BFF to do user token generation because an AS is
no longer afforded the capability for some reason. If we pull in expecting
to solve ITP related issues then I think that justification is in play and
we can work together to come up with a solution, rather than starting with
the current deleterious prevalent pattern on the internet (which honestly
is the most ridiculous paradigm I have seen). If we don't assume ITP is an
issue, then I fail to see the core problem that existing AS have (as you
pointed out code+PKCE already works) without the front channel or back
channel needing really to make any additional changes.

I assume there is a flaw in my reasoning somewhere, so please help me find
it.

- Warren

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 9:20 PM Vittorio Bertocci <vittorio.bertocci=
[email-masked]> wrote:

>    - Neil suggested that the backend could simply give short lived JTWs
>    for the frontent to call API.
>    - I clarified that this would not be viable in the general case and
>    provided an example scenario where backend issued short lived tokens would
>    not have worked
>    - You commented that the frontend can obtain AS tokens from JS and
>    mentioned silent authentication. I clarified (or tried to) that this
>    offshoot of the discussion wasn’t to say that there is no viable way of
>    doing the scenario already, and by the way using an iFrame to do silent
>    authentication is now problematic. At this point we are no longer
>    discussing TMI-BFF, but current affairs in the authentication world. The
>    fact that we are proposing TMI-BFF and the fact that silent authentication
>    is less and less viable are independent facts, the former isn’t meant to be
>    a solution for the latter (it’s already addressed by using RTs in coke+PKCE)
>
>
>
> That clarified. Not only we expect ITP to affect silent authentication, it
> has been affected for the past year and that has been one of the primary
> business drivers for the rapid adoption of code+PKCE+RTs in the user agent,
> as customers with pure SPAs found themselves unable to renew tokens without
> prompting as their access to cookies in flows driven by iframes became less
> and less reliable.
>
> When ITP was introduced we put many companies together to try to get Apple
> to change it (you can find the doc in
> https://docs.google.com/document/d/1Rs--DFzZj_SfQjtz8oH9DlLII0ra3viMEHrK7sKsaiU/edit#heading=h.p3nvp6xmxvzf)
> but they didn’t bulge and ultimately the introduction of RTs in user agent
> code (albeit with extra restrictions, the one I mentioned not everyone is
> following) made the problem manageable. We have an initiative cross working
> groups (IETF, OIDC etc)for working with browser vendors to try containing
> similar regressions in the future. For a summary of similar problems see
> https://identiverse.gallery.video/detail/video/6184443037001/browser-features-vs-identity-protocols.
>
>
>
>
> To restate, the TMI-BFF proposal is not trying to fix any of that, nor per
> the above some of it need fixing. The only indirect connection might be
> that less stuff happening in the user agent means less opportunities for
> similar changes to impact the flows, but it’s definitely not a top level
> driver.
>
>
>
> *Date: *Sunday, February 14, 2021 at 11:41

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 21:01:59 +0000

*    What is the frontend developer doing any different in the new hypothetical world than they would be, right now they are including an SDK and writing one line of code on login redirect/silent auth and one line of code for PKCE+code validation. If a service client needs to be authorized there would be a third line of code to call the backend.

As mentioned, the client code might not look very different- although in the TMI-BFF model the JS code might be even more succinct (given that the sign in parts are handled by the backend, they might simply be decorated routes on the middleware- no need for the JS to make those calls directly, just to hit the routes) and the SDK far more lightweight. The difference might be that if your authorization server does not support refresh token rotation or sender constraining RTs, with code+PKCE you might not be able to obtain the same functionality as TMI-BFF given that you might not have a way of renewing short lived tokens without full redirects (see discussion on ITP). That is a temporary situation, hopefully eventually all AS vendors will support rotation and/or sender constraint, but it is an example of how the proposal does have advantages.

  *   These three lines still need to be present irrespective of whether you use an AS-proxy TMI-BFF or the AS directly.
See above. That’s not necessarily the case, and what the client code looks like isn’t what TMI-BFF is trying to address anyway.

  *   Except now we are encouraging every app to write a BFF and integrate their front channel with it.
That is not the case. The scope of this proposal remains limited to apps that already have a backend.

  *   Additionally, we aren't requiring less capabilities from the spec, we are just also requiring additional ones for a BFF. If there are capabilities this lets us drop from OAuth could you explain which ones those are, because since an AS can't know whether "customers" are going to want to use a BFF or not, it will still have to implement all the necessary AS features that already exist (and the new ones that don't). I don't see how this affords an AS any additional freedom.
Once again, this proposal is not meant to lighten the AS burden, but to make the life of developers easier. I already mentioned the rotation/sender constraint capabilities that code+PKCE require for RTs to be used in a user agent, and the fact that various important AS on the market today do not offer that capability. There might be others: for example, until recently various important AS did not support CORS on their metadata and token endpoints, making the code+PKCE in the user agent impossible. My hope and assumption is that those are all temporary situations, and TMI-BFF goal is NOT to dispense AS developers from implementing those features.  But those are concrete examples of cases in which TODAY an app developer (whose app has a backend) took a dependency on one AS without those features might be able to do more things in their app when using TMI-BFF than with JS code that relies on those AS capabilities to function.

From: Warren Parad <[email-masked]>
Date: Sunday, February 14, 2021 at 11:57
To: Vittorio Bertocci <[email-masked]>
Cc: Stoycho Sleptsov <[email-masked]>, Neil Madden <[email-masked]>, oauth <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

but it does make things simpler for the frontend developer and requires less advanced capabilities in the AS.
I guess I'm still getting lost on this point, which seems not yet justified for me. What is the frontend developer doing any different in the new hypothetical world than they would be, right now they are including an SDK and writing one line of code on login redirect/silent auth and one line of code for PKCE+code validation. If a service client needs to be authorized there would be a third line of code to call the backend. These three lines still need to be present irrespective of whether you use an AS-proxy TMI-BFF or the AS directly. Except now we are encouraging every app to write a BFF and integrate their front channel with it.

Additionally, we aren't requiring less capabilities from the spec, we are just also requiring additional ones for a BFF. If there are capabilities this lets us drop from OAuth could you explain which ones those are, because since an AS can't know whether "customers" are going to want to use a BFF or not, it will still have to implement all the necessary AS features that already exist (and the new ones that don't). I don't see how this affords an AS any additional freedom.

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 8:39 PM Vittorio Bertocci <[email-masked]<mailto:[email-masked]>> wrote:
In the TMI-BFF topology, the backend and frontend developer are the same person. The operations TMI-BFF describes are the functional equivalent of what the JS code of one SPA app using a code+PKCE SDK would do when retrieving previously obtaining tokens from the store in order to perform an API call. Whereas such an app would make that call in memory (and result in the same operations described here, either use a previously saved access token matching the requirements of the API call, or use artifacts like RTs to request a new access token matching the request) in TMI-BFF al the logic and persistence layer are in the backend, hence that query becomes a request to the backend instead of a local function call.
The advantages have been described in other branches of this thread, but TL;DR- a lot of the token requesting work can be performed more reliably (eg less things can go wrong) from a confidential client and it’s easier for SDK developers to package it (see existing middlewares vs JS SDKs). Note that for the app developer this might still look like the same flow, asking a JS SDK to get the token the app needs to call an API, but the JS SDK would be dramatically simpler than the one performing code+PKCE in the user agent and entail communication between frontend a backend, hence the need to define how that communication happens if we want developers to be able to mix and match frontend and backend dev stacks.
Again, this does not necessarily add security to the code+PKCE in the user agent model (which remains the only game in town for backendless SPAs), but it does make things simpler for the frontend developer and requires less advanced capabilities in the AS.

From: Warren Parad <[email-masked]<mailto:[email-masked]>>
Date: Sunday, February 14, 2021 at 09:45
To: Stoycho Sleptsov <[email-masked]<mailto:[email-masked]>>
Cc: Neil Madden <[email-masked]<mailto:[email-masked]>>, Vittorio Bertocci <[email-masked]<mailto:[email-masked]>>, oauth <[email-masked]<mailto:[email-masked]>>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

Warren Parad

Founder, CTO

Stoycho.

Warren Parad

Founder, CTO

---

From: Vittorio Bertocci <[email-masked]>
Date: Sun, 14 Feb 2021 21:31:12 +0000

*   Draft [..] essentially suggests that every app needs to run a BFF to do user token generation because an AS is no longer afforded the capability for some reason
I believe this might be the crux of the problem, my impression is that you are attributing to the draft a way larger scope than it is intended to have. The draft makes no such suggestion. The draft says nothing about AS losing capabilities. The draft is not trying to solve an AS problem. And above all, the draft does not target every app.

The draft is an optimization aimed at a very specific, albeit very common, application topology where there is a frontend and a backend, and the developer wants to perform API calls from the frontend directly to the RS. This is only a specific topology, and the proposal is scoped down to that. All other topologies are unaffected. Also, the draft isn’t pushing this topology as the preferred one. It’s best to keep tokens out of the frontend altogether. But if the developer is adamant in performing API calls direct from their JS, and if they already have a backend, and only in that case, the current proposal has less moving parts and less requirements than code+PKCE .

Code+PKCE already has the expressive power to handle the scenario described here, and is applicable to a wider range of scenarios. The main point the draft brings to the table is the ability for a frontend to delegate to a backend a lot of logic that in the code+PKCE case executes in an environment that is naturally more constrained and prone to attacks than a backend. That doesn’t mean developers whose app has a backend should automatically choose the new model over code+PKCE, more that the model discussed here might be viable and require less capabilities/moving parts to achieve the same expressive power, especially if the SDKs used in the solution have a standard way to handle it. That is far from every app, but it is a situation I encountered in the wild often enough to prompt the discussion with Brian and the draft.

As a side note, the initial reactions of practitioners have been very positive. I am really hoping the discussion will lead to identifying and weeding out security issues, or land on security flaws in the model so grave that they can be properly used to discourage its use. No matter what way it will go, I am very glad the discussion is taking place.

Date: Sunday, February 14, 2021 at 12:59

To restate, the TMI-BFF proposal is not trying to fix any of that... it’s definitely not a top level driver.
Great, then we are back to: what is the top level driver. Because, while I appreciate the circumstances around ITP2.1~ as I fully understand how identity providers like Auth0 are using iframes and thirdparty cookies, this problem vanishes with the use of first-party domains. So let's skip the digression and assume we aren't solving ITP future related issues.

The real problem I have with the draft is that it essentially suggests that every app needs to run a BFF to do user token generation because an AS is no longer afforded the capability for some reason. If we pull in expecting to solve ITP related issues then I think that justification is in play and we can work together to come up with a solution, rather than starting with the current deleterious prevalent pattern on the internet (which honestly is the most ridiculous paradigm I have seen). If we don't assume ITP is an issue, then I fail to see the core problem that existing AS have (as you pointed out code+PKCE already works) without the front channel or back channel needing really to make any additional changes.

I assume there is a flaw in my reasoning somewhere, so please help me find it.

- Warren

Warren Parad

Founder, CTO

On Sun, Feb 14, 2021 at 9:20 PM Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:[email-masked]>> wrote:
Let me rewind a bit here. This was never presented as driving use case.

Warren Parad

Founder, CTO

Warren Parad

Founder, CTO

Warren Parad

Founder, CTO

  *   Re: GET vs POST,

— Neil

B&V

   Abstract:

   The IETF Secretariat

---

From: Philippe De Ryck <[email-masked]>
Date: Mon, 15 Feb 2021 07:45:29 +0100

A couple of notes from my end:

Developers building an application that consists of a frontend, a backend, and APIs indeed often struggle with identifying the correct client, especially with the combination of OAuth 2.0 and OIDC. Having a standardized way of handling such cases is definitely useful. 

That said, the current spec is a bit all over the place. Vittorio stated here that the main goal is to make it easier for developers, but the spec makes quite a bit of (vague) security statements. It also aims to avoid the need for a reverse proxy-based BFF, but comes up short compared to such a BFF. 

A few detailed security notes:

1) Section 6.1 states not to use localStorage (I assume because of malicious JS code), which makes no sense. If malicious code is running in the frontend, it can simply call the bff-token endpoint and grab the token from there. Other attacks typically also allow to steal tokens from memory (e.g., prototype pollution attacks as I discuss here: https://pragmaticwebsecurity.com/articles/oauthoidc/localstorage-xss.html <https://pragmaticwebsecurity.com/articles/oauthoidc/localstorage-xss.html>). 

2) The use of confidential clients is a big plus, but since the access token is used in the frontend, you lose the ability to use sender constrained tokens, which a proxy BFF would be able to do. A proxy-based BFF can also limit the API endpoints it exposes to a specific frontend and can apply traffic analysis to detect malicious behavior from a compromised frontend.

3) Keeping refresh tokens on the backend is good, but not necessarily better than keeping them in a web worker, as Auth0’s JS SDK (and presumably others, haven’t checked) does by default. 

Overall, my recommendation is to focus on the specific use case of handling tokens in a “frontend with backend” application type, and forget about trying to also solve security issues in frontends caused by malicious JS.

Philippe

—
Pragmatic Web Security
Security for developers
https://pragmaticwebsecurity.com/

> On 14 Feb 2021, at 22:31, Vittorio Bertocci <vittorio.bertocci=[email-masked]> wrote:
> 
> Draft [..] essentially suggests that every app needs to run a BFF to do user token generation because an AS is no longer afforded the capability for some reason
> From: Warren Parad <wparad=[email-masked] <mailto:wparad=[email-masked]>>
> To: Vittorio Bertocci <[email-masked] <mailto:[email-masked]>>
> Cc: Neil Madden <[email-masked] <mailto:[email-masked]>>, "[email-masked] <mailto:[email-masked]>" <[email-masked] <mailto:[email-masked]>>
> On Sun, Feb 14, 2021 at 9:20 PM Vittorio Bertocci <vittorio.bertocci=[email-masked] <mailto:[email-masked]>> wrote:
> Neil suggested that the backend could simply give short lived JTWs for the frontent to call API.
> I clarified that this would not be viable in the general case and provided an example scenario where backend issued short lived tokens would not have worked
> You commented that the frontend can obtain AS tokens from JS and mentioned silent authentication. I clarified (or tried to) that this offshoot of the discussion wasn’t to say that there is no viable way of doing the scenario already, and by the way using an iFrame to do silent authentication is now problematic. At this point we are no longer discussing TMI-BFF, but current affairs in the authentication world. The fact that we are proposing TMI-BFF and the fact that silent authentication is less and less viable are independent facts, the former isn’t meant to be a solution for the latter (it’s already addressed by using RTs in coke+PKCE)
>  
> When ITP was introduced we put many companies together to try to get Apple to change it (you can find the doc in https://docs.google.com/document/d/1Rs--DFzZj_SfQjtz8oH9DlLII0ra3viMEHrK7sKsaiU/edit#heading=h.p3nvp6xmxvzf <https://docs.google.com/document/d/1Rs--DFzZj_SfQjtz8oH9DlLII0ra3viMEHrK7sKsaiU/edit#heading=h.p3nvp6xmxvzf>) but they didn’t bulge and ultimately the introduction of RTs in user agent code (albeit with extra restrictions, the one I mentioned not everyone is following) made the problem manageable. We have an initiative cross working groups (IETF, OIDC etc)for working with browser vendors to try containing similar regressions in the future. For a summary of similar problems see https://identiverse.gallery.video/detail/video/6184443037001/browser-features-vs-identity-protocols <https://identiverse.gallery.video/detail/video/6184443037001/browser-features-vs-identity-protocols>.  
>  
> From: Warren Parad <wparad=[email-masked] <mailto:[email-masked]>>
> To: Vittorio Bertocci <[email-masked] <mailto:[email-masked]>>
> Cc: Neil Madden <[email-masked] <mailto:[email-masked]>>, "[email-masked] <mailto:[email-masked]>" <[email-masked] <mailto:[email-masked]>>
> Secure your user data and complete your authorization architecture. Implement Authress <https://authress.io/>.
>  
>  
> On Sun, Feb 14, 2021 at 7:57 PM Vittorio Bertocci <vittorio.bertocci=[email-masked] <mailto:[email-masked]>> wrote:
> ITP, for example
>  
> From: Warren Parad <wparad=[email-masked] <mailto:[email-masked]>>
> To: Vittorio Bertocci <[email-masked] <mailto:[email-masked]>>
> Cc: Neil Madden <[email-masked] <mailto:[email-masked]>>, "[email-masked] <mailto:[email-masked]>" <[email-masked] <mailto:[email-masked]>>
> Secure your user data and complete your authorization architecture. Implement Authress <https://authress.io/>.
>  
>  
> On Sun, Feb 14, 2021 at 1:33 PM Vittorio Bertocci <vittorio.bertocci=[email-masked] <mailto:[email-masked]>> wrote:
> For UI related functionality, i.e. document selection, user profile display/changes, contact updates, etc... You should be able to execute the client side silent authentication using the provided session token from the Azure AD AS, without needing to make any RO api calls nor user redirects. 
> From: Warren Parad <wparad=[email-masked] <mailto:[email-masked]>>
> To: Vittorio Bertocci <[email-masked] <mailto:[email-masked]>>
> Cc: Neil Madden <[email-masked] <mailto:[email-masked]>>, "[email-masked] <mailto:[email-masked]>" <[email-masked] <mailto:[email-masked]>>
> Secure your user data and complete your authorization architecture. Implement Authress <https://authress.io/>.
>  
>  
> On Sun, Feb 14, 2021 at 12:29 PM Vittorio Bertocci <vittorio.bertocci=[email-masked] <mailto:[email-masked]>> wrote:
> Hi Neil,
> Re: GET vs POST,
> Re: RO-AS, interaction- 
>  If the backend is already implicitly trusted then couldn’t you skip OAuth and just get the backend to issue short-lived JWTs to the frontend that it can use for API access?
> From: OAuth <[email-masked] <mailto:[email-masked]>> on behalf of Neil Madden <[email-masked] <mailto:[email-masked]>>
> To: Vittorio Bertocci <vittorio.bertocci=[email-masked] <mailto:[email-masked]>>
> Cc: "[email-masked] <mailto:[email-masked]>" <[email-masked] <mailto:[email-masked]>>
> The combination of the bff-token endpoint recommending the use of GET requests together with the hint to use cookie-based authentication is likely going to punch a hole in most CSRF defenses, which assume that GETs are safe. The only thing preventing this being exploitable is Cross-Origin Read Blocking (https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md <https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md>) due to the JSON content-type. That makes me really nervous. We should at least mandate X-Content-Type-Options: nosniff on that response. I’d feel more comfortable if this was a POST request only. 
>  
> On 12 Feb 2021, at 20:46, Vittorio Bertocci <vittorio.bertocci=[email-masked] <mailto:[email-masked]>> wrote:
> 
> Dear all,
> - It makes it possible to create interoperable SDKs, where frontend dev stacks (any JS flavor) can be mixed and matched with compliant backend stacks (middlewares in node, java, ASP.NET <http://asp.net/>, PHP etc)
> On 2/12/21, 12:41, "[email-masked] <mailto:[email-masked]>" <[email-masked] <mailto:[email-masked]>> wrote:
> 
> 
>    URL:            https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.txt <https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.txt>
>    Status:         https://datatracker.ietf.org/doc/draft-bertocci-oauth2-tmi-bff/ <https://datatracker.ietf.org/doc/draft-bertocci-oauth2-tmi-bff/>
>    Html:           https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.html <https://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.html>
>    Htmlized:       https://tools.ietf.org/html/draft-bertocci-oauth2-tmi-bff-00 <https://tools.ietf.org/html/draft-bertocci-oauth2-tmi-bff-00>
> 
> 
>    Abstract:
>    until the htmlized version and diff are available at tools.ietf.org <http://tools.ietf.org/>.
> 
>    The IETF Secretariat
> 
> 
> 
> [email-masked] <mailto:[email-masked]>
> https://www.ietf.org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>
> 
> [email-masked] <mailto:[email-masked]>
> https://www.ietf.org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>_______________________________________________
> OAuth mailing list
> [email-masked] <mailto:[email-masked]>
> https://www.ietf.org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>

---

From: Vittorio Bertocci <[email-masked]>
Date: Mon, 15 Feb 2021 07:50:27 +0000

Thank you Philippe for your comments! Some considerations:

  *   It also aims to avoid the need for a reverse proxy-based BFF, but comes up short compared to such a BFF.
That isn’t a goal. If the developer can use a reverse proxy, they should definitely go for it. Not getting tokens in the user agent at all is the safest option. TMI-BFF is for the cases where it is not a viable option- thru the threads I mentioned some of those cases.

  *   Section 6.1 states not to use localStorage (I assume because of malicious JS code),…
We might have been naïve there- a common discussion point even when considering code+PKCE is that local storage is somehow vulnerable to more exploits than memory.
If there are attacks that only work with storage but not with memory, this would be an incremental improvement. If every attack that can access the storage can also access memory, then I agree it’s a moot point- but then the current public discourse needs a severe reset given that the two options are presented as having very different security properties.

  *   you lose the ability to use sender constrained tokens, which a proxy BFF would be able to do
Absolutely. If the reverse proxy is an option, the security improves for sure. TMI-BFF is meant to help when it is not an option.

  *   Keeping refresh tokens on the backend is good, but not necessarily better than keeping them in a web worker, as Auth0’s JS SDK
A web worker is definitely good practice, but it’s still on the local machine. One might argue it’s enough security for the scenario, but not the same as not having the tokens available at all in the local box. But as you say, the thrust behind TMI-BFF is more about dev experience- I’d be happy with equivalent security with code+PKCE+RTs

From: Philippe De Ryck <[email-masked]>
Date: Sunday, February 14, 2021 at 22:45
To: Vittorio Bertocci <[email-masked]>
Cc: Warren Parad <[email-masked]>, "[email-masked]" <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

1) Section 6.1 states not to use localStorage (I assume because of malicious JS code), which makes no sense. If malicious code is running in the frontend, it can simply call the bff-token endpoint and grab the token from there. Other attacks typically also allow to steal tokens from memory (e.g., prototype pollution attacks as I discuss here: https://pragmaticwebsecurity.com/articles/oauthoidc/localstorage-xss.html).

Philippe

—
Pragmatic Web Security
Security for developers

On 14 Feb 2021, at 22:31, Vittorio Bertocci <vittorio.bertocci=[email-masked]<mailto:vittorio.bertocci=[email-masked]>> wrote:

From: Warren Parad <wparad=[email-masked]<mailto:wparad=[email-masked]>>

- Warren

Error! Filename not specified.
Warren Parad
Founder, CTO
Secure your user data and complete your authorization architecture. Implement Authress<https://authress.io/>.

Error! Filename not specified.
Warren Parad
Founder, CTO
Secure your user data and complete your authorization architecture. Implement Authress<https://authress.io/>.

Error! Filename not specified.
Warren Parad
Founder, CTO
Secure your user data and complete your authorization architecture. Implement Authress<https://authress.io/>.

  *   Re: GET vs POST,

— Neil

?Dear all,

- It makes it possible to create interoperable SDKs, where frontend dev stacks (any JS flavor) can be mixed and matched with compliant backend stacks (middlewares in node, java, ASP.NET<http://asp.net/>, PHP etc)

B&V

?On 2/12/21, 12:41, "[email-masked]<mailto:[email-masked]>" <[email-masked]<mailto:[email-masked]>> wrote:

   Abstract:

   Please note that it may take a couple of minutes from the time of submission
   until the htmlized version and diff are available at tools.ietf.org<http://tools.ietf.org/>.

   The IETF Secretariat

---

From: Philippe De Ryck <[email-masked]>
Date: Mon, 15 Feb 2021 09:32:35 +0100

> On 15 Feb 2021, at 08:50, Vittorio Bertocci <[email-masked]> wrote:
> 
> It also aims to avoid the need for a reverse proxy-based BFF, but comes up short compared to such a BFF.

OK, seems that I got thrown off by the introduction. Adding a section to describe these architectural patterns and their trade-offs could definitely help to scope this spec.

> Section 6.1 states not to use localStorage (I assume because of malicious JS code),…

Welcome to my life :)

Let me try to give an analogy to frame this problem a bit. You're worried about burglars breaking into your home, so instead of leaving jewellery on the kitchen table, you lock it away in a safe. Rookie burglars will break in, and not find anything on the kitchen table, and be stumped on how to proceed. However, a veteran burglar probably knows where to find your safe. If they can't unlock the safe, they can just hide behind the door until you open your safe, hit you on the head with a bat, and take your jewellery. In essence, removing valuables from the kitchen table only addresses a consequence, but not the underlying problem.

The same applies to malicious JS and localStorage. Going after data in localStorage is an easy and simple attack. It's what a script kiddie would do when they have no idea what they are really doing. However, a targeted attack will not be hampered by that. They can apply the following techniques:
Override any JS function used by the legitimate application for handling the token (e.g., setRequestHeader)
Send a request to the backend to obtain an access token (this would be indistinguishable from a legitimate request)

Without the use of a TMI-BFF, the attacker would also be able to run a silent flow to obtain a new set of tokens from the AS. Moving to a confidential client, as the spec proposes, addresses this major vulnerability.

Note that "in memory" here means "in memory of the application's execution context". A web worker runs in a separate context and is isolated by design.

> you lose the ability to use sender constrained tokens, which a proxy BFF would be able to do

See the note above about a separate section on the trade-offs. 

> Keeping refresh tokens on the backend is good, but not necessarily better than keeping them in a web worker, as Auth0’s JS SDK

I get the impression that this spec lacks a concrete threat model. A worker is an isolated environment in the browser. If the local machine is considered untrusted, then what about the user's credentials that are entered on that machine, or the U2F/WebAuthN authentication used for MFA? The local machine is part of the TCB here, and that includes the browser and its extensions. So I'd say that RTs in such an environment are properly secured. Also, since workers live in memory only, RTs for a frontend web should have a similar lifetime as a traditional session (e.g., 12 hours).

Compared to using a worker for handling RTs, I believe the TMI-BFF only adds a single security benefit: an attacker is no longer able to run a silent flow to obtain a fresh set of tokens (since the client is now a confidential client). 

Hope this helps

Philippe

> https://pragmaticwebsecurity.com/ <https://pragmaticwebsecurity.com/>
> 
> 
> On 14 Feb 2021, at 22:31, Vittorio Bertocci <vittorio.bertocci=[email-masked] <mailto:vittorio.bertocci=[email-masked]>> wrote:
>

---

From: Neil Madden <[email-masked]>
Date: Mon, 15 Feb 2021 10:14:47 +0000

> On 15 Feb 2021, at 08:32, Philippe De Ryck <[email-masked]> wrote:
> 
> [...]
> 

But they can just call the bff-token endpoint to do the same. If there is a security advantage, IMO it is as a defence in depth against open redirects, unicode normalisation attacks (ie not validating the redirect_uri correctly at the AS), etc. 

— Neil

---

From: Philippe De Ryck <[email-masked]>
Date: Mon, 15 Feb 2021 11:26:54 +0100

> On 15 Feb 2021, at 11:14, Neil Madden <[email-masked]> wrote:
> 

A Web Worker and the TMI-BFF both encapsulate the RT and only expose the (short-lived) AT.

With the worker-based approach, the client is a public client that completes the code exchange without authentication. This allows an attacker to run an independent silent flow in an iframe within the legitimate application. This flow relies on the existing cookie-based session with the AS to obtain an AT and RT, independent of the tokens of the client application. A confidential client does not suffer from this problem (a stolen code cannot be exchanged without client authN, and when done through the BFF, the RT is not exposed). 

And as you state, there are other benefits as well.

Philipp

—
Pragmatic Web Security
Security for developers

---

From: Neil Madden <[email-masked]>
Date: Mon, 15 Feb 2021 10:50:51 +0000

> On 15 Feb 2021, at 10:26, Philippe De Ryck <[email-masked]> wrote:
> 
> 
> 

I don’t think this distinction matters at all from a security point of view. It’s the AT that attackers are after - why bother with a RT if I can just call the bff-token endpoint to get a new AT every time?

---

From: Warren Parad <[email-masked]>
Date: Mon, 15 Feb 2021 11:54:13 +0100

Totally agree.

Warren Parad

Founder, CTO
Secure your user data with IAM authorization as a service. Implement
Authress <https://authress.io/>.

On Mon, Feb 15, 2021 at 11:51 AM Neil Madden <[email-masked]>
wrote:

>
>
> On 15 Feb 2021, at 10:26, Philippe De Ryck <
> [email-masked]> wrote:
>
> 
>
> On 15 Feb 2021, at 08:32, Philippe De Ryck <
> [email-masked]> wrote:
>
> [...]
>
> *Compared to using a worker for handling RTs, I believe the TMI-BFF only
> adds a single security benefit: an attacker is no longer able to run a
> silent flow to obtain a fresh set of tokens (since the client is now a
> confidential client). *
>
>
> But they can just call the bff-token endpoint to do the same. If there is
> a security advantage, IMO it is as a defence in depth against open
> redirects, unicode normalisation attacks (ie not validating the
> redirect_uri correctly at the AS), etc.
>
>
> I don’t think this distinction matters at all from a security point of
> view. It’s the AT that attackers are after - why bother with a RT if I can
> just call the bff-token endpoint to get a new AT every time?
>
>
> With the worker-based approach, the client is a public client that
> completes the code exchange without authentication. This allows an attacker
> to run an independent silent flow in an iframe within the legitimate
> application. This flow relies on the existing cookie-based session with the
> AS to obtain an AT and RT, independent of the tokens of the client
> application. A confidential client does not suffer from this problem (a
> stolen code cannot be exchanged without client authN, and when done through
> the BFF, the RT is not exposed).
>
> *Pragmatic Web Security*
> *Security for developers*

---

From: Philippe De Ryck <[email-masked]>
Date: Mon, 15 Feb 2021 12:09:10 +0100

> 
> On 15 Feb 2021, at 11:50, Neil Madden <[email-masked]> wrote:
> 
>>> On 15 Feb 2021, at 11:14, Neil Madden <[email-masked] <mailto:[email-masked]>> wrote:
>>> 
>>>> On 15 Feb 2021, at 08:32, Philippe De Ryck <[email-masked] <mailto:[email-masked]>> wrote:
>>>> 
>>>> [...]
>>>> 

Getting an AT from the BFF (or a worker) is an “online” attack, which only works as long as the application/malicious code is loaded in the browser of the user. 

Stealing a working refresh token (e.g., with a silent flow) is an “offline” attack, which gives long-term access (lifetime of the RT), independent of the state of the application in the user’s browser.

There is a clear distinction, but whether that matters is a different discussion. It depends on how the application used, and how token lifetimes are configured. FWIW, the DPoP threat model makes the same distinction ("Stolen token (XSS)” vs “XSS (Victim is online)”) here: https://danielfett.de/2020/05/04/dpop-attacker-model/ <https://danielfett.de/2020/05/04/dpop-attacker-model/>

Philippe

---

From: Neil Madden <[email-masked]>
Date: Mon, 15 Feb 2021 11:15:47 +0000

Yes, I’ve argued against this distinction for DPoP too. Since the first days of HttpOnly attackers learnt to proxy requests through the browser (as you know of course). This is not only to bypass the restrictions but it’s also just much better for the attacker because it hides their traffic and origin. People are online all the time now, so this is at best a mild inconvenience. 

— Neil

> On 15 Feb 2021, at 11:09, Philippe De Ryck <[email-masked]> wrote:
> 
> 
>> 
> There is a clear distinction, but whether that matters is a different discussion. It depends on how the application used, and how token lifetimes are configured. FWIW, the DPoP threat model makes the same distinction ("Stolen token (XSS)” vs “XSS (Victim is online)”) here: https://danielfett.de/2020/05/04/dpop-attacker-model/
> 
> Philippe
>  
>

---

From: Stoycho Sleptsov <[email-masked]>
Date: Mon, 15 Feb 2021 15:34:58 +0200

Thank you for the comprehensive answer, Neil.

Initially I said that "I need the client app. to be authenticated at the
AS", and I meant authenticated as by the spec (explicit authentication).
It seems that the reason which I gave as an example to explain why would I
need that (to determine if it is a first-party app.), taken alone, is weak
to justify the decision for such a constraint as an explicit authentication.
And I thank you for that clarification.
But the question why would I (or somebody else) need the client to be
explicitly authenticated as a confidential client at the AS is a
different matter.
It is an important question, of course, and it would be very interesting
for me to understand what is the difference between the set of
architectural properties induced by an explicit authentication (credentials
by the spec), and the properties induced by an implicit (redirect_uri)
authentication, but I am afraid to not abduct the conversation away from
the original intent of the TMI-BFF.

The main point for me was to verify that for a proper (explicit) client
authentication we need to go through the backend, because PKCE doesn't help
for that.
Which means that a document like TMI-BFF could be very helpful while trying
to consider all the BFF options.

Regards,
Stoycho.

On Sun, 14 Feb 2021 at 20:30, Neil Madden <[email-masked]> wrote:

> Within the spec “client authentication” refers to explicit authentication
> of the client using credentials. But you said initially that you wanted
> this to “determine if it is a first-party app, for example”. You can
> determine this based on the redirect_uri and the fact that only the
> legitimate client can receive an authorization code at that redirect_uri
> (if its HTTPS, exact matching of URIs, etc). This is what I refer to as
> implicit authentication - the AS knows at the point of auth code exchange
> that only the legitimate client could have obtained that code.
>
> Note that for both public and confidential clients, the confirmation of
> the client identity happens after the user has gone through the
> authorization flow. PAR fixes this for confidential clients, but not public
> ones. So that is one reason to prefer a BFF pattern and a confidential
> client.
>
> Confidential clients also have an extra layer of defence in depth: they
> need a redirect_uri *and* client credentials. So that is another reason to
> use a confidential client and BFF.
>
> A backend server may also have a more reliable connection to the AS. So
> that may also be a good reason to use a BFF - eg to avoid having to
> reauthorize with the user because an auth code or refresh request timed out
> due to a flaky network connection.
>
> So there may be many good reasons to use a BFF pattern. But if you just
> want a reasonable assurance of client identity at the point of issuing
> tokens, then IMO a public client + PKCE is fine for many cases.
>
> — Neil
>

---

From: Torsten Lodderstedt <[email-masked]>
Date: Mon, 15 Feb 2021 17:48:56 +0100

Thank you again for the explanation. 

I think your assumption about the overall flow should be described in the draft. 

As I understand it now the core contribution of your proposal is to move refresh token management from frontend to backend. Is that correct?  

> Am 14.02.2021 um 21:35 schrieb Vittorio Bertocci <vittorio.bertocci=[email-masked]>:
> 
> Thanks!
>>>  URL:            https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.google.com/url?q%253Dhttps://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.txt%2526source%253Dgmail-imap%2526ust%253D1613767591000000%2526usg%253DAOvVaw3Rb-S0l6cEv0ytjDxtYLAP%26source%3Dgmail-imap%26ust%3D1613935165000000%26usg%3DAOvVaw3p5263a_rEePNbnX7jWFjq&source=gmail-imap&ust=1613939757000000&usg=AOvVaw0jgXsBeXKFC9n31Rg06yE6
>>>  Status:         https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.google.com/url?q%253Dhttps://datatracker.ietf.org/doc/draft-bertocci-oauth2-tmi-bff/%2526source%253Dgmail-imap%2526ust%253D1613767591000000%2526usg%253DAOvVaw3-qg5MDtY7kD1HpR5jR2QY%26source%3Dgmail-imap%26ust%3D1613935165000000%26usg%3DAOvVaw1YZmVHpENHa-bqqtbezRpa&source=gmail-imap&ust=1613939757000000&usg=AOvVaw0UWVw3PhVKKuwdIjaMHfce
>>>  Html:           https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.google.com/url?q%253Dhttps://www.ietf.org/archive/id/draft-bertocci-oauth2-tmi-bff-00.html%2526source%253Dgmail-imap%2526ust%253D1613767591000000%2526usg%253DAOvVaw05WK4GSEKcWjZzNhvb1p5d%26source%3Dgmail-imap%26ust%3D1613935165000000%26usg%3DAOvVaw2HibfQtTYv3talGT379MOu&source=gmail-imap&ust=1613939757000000&usg=AOvVaw3AuwQ6TPoW5MnsGXcMUh_S
>>>  Htmlized:       https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.google.com/url?q%253Dhttps://tools.ietf.org/html/draft-bertocci-oauth2-tmi-bff-00%2526source%253Dgmail-imap%2526ust%253D1613767591000000%2526usg%253DAOvVaw0qm45MWGbZf0zbBjZj3ggz%26source%3Dgmail-imap%26ust%3D1613935165000000%26usg%3DAOvVaw0gZZ0ZU8QVx7OBjxDcG8d-&source=gmail-imap&ust=1613939757000000&usg=AOvVaw2fIy9b1bQxvnk5QK9Nl7QI
>>> 
>>> 
>>>  Abstract:
>>> https://www.google.com/url?q=https://www.google.com/url?q%3Dhttps://www.google.com/url?q%253Dhttps://www.ietf.org/mailman/listinfo/oauth%2526source%253Dgmail-imap%2526ust%253D1613767591000000%2526usg%253DAOvVaw1Bfu9fJ2Fj_BZJ3H9yw7od%26source%3Dgmail-imap%26ust%3D1613935165000000%26usg%3DAOvVaw3a73buBtPOBoDQ3SMH_XJW&source=gmail-imap&ust=1613939757000000&usg=AOvVaw3p0jGqda5qiL2KioFSSZ01
>> 
>> 
>

---

From: Brian Campbell <[email-masked]>
Date: Tue, 16 Feb 2021 13:59:57 -0700

> I think your assumption about the overall flow should be described in the

We did attempt to capture the assumptions in the draft but clearly could
have done a better job with it :)

>
> As I understand it now the core contribution of your proposal is to move
> refresh token management from frontend to backend. Is that correct?
>

 Taking that a bit further - the idea is that the backend takes on the
responsibilities of being a confidential client (client creds, token
acquisition, token management/persistence, etc.) to the external AS(s). And
TMI BFF describes a way for that backend to deliver access tokens to its
own frontend.

-- 
_CONFIDENTIALITY NOTICE: This email may contain confidential and privileged 
material for the sole use of the intended recipient(s). Any review, use, 
distribution or disclosure by others is strictly prohibited.  If you have 
received this communication in error, please notify the sender immediately 
by e-mail and delete the message and any file attachments from your 
computer. Thank you._

---

From: Dominick Baier <[email-masked]>
Date: Wed, 17 Feb 2021 00:27:06 -0800

Hey,

Tbh - I have a bit of a hard time to see why this requires a spec, if that
is all you are aiming at. Wouldn’t that be just an extension to the “OAuth
for web apps BCP?”.

All I can add here is - this approach would not work for any of our
customer. Because their real motivation is to implement a more and more
common security guideline these days - namely: “no JS-accessible tokens in
the browser” - but this document doesn’t cover this.

cheers
———
Dominick Baier

On 16. February 2021 at 22:01:37, Brian Campbell (
bcampbell=[email-masked]) wrote:

*CONFIDENTIALITY NOTICE: This email may contain confidential and privileged
material for the sole use of the intended recipient(s). Any review, use,
distribution or disclosure by others is strictly prohibited.  If you have
received this communication in error, please notify the sender immediately
by e-mail and delete the message and any file attachments from your
computer. Thank you.*_______________________________________________
OAuth mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/oauth

---

From: Vittorio Bertocci <[email-masked]>
Date: Wed, 17 Feb 2021 17:30:19 +0000

Thanks Dominick,
It is indeed a very simple spec, but as you can see from the discussion so far, it doesn’t appear to be trivial- and there might be some considerations we consider obvious (eg scope escalation) that might not be super clear otherwise.
In terms of the guidance, just to make sure I get the scope right- that means that also code+PKCE+rotating RTs in JS would not be acceptable for your customers?

From: Dominick Baier <[email-masked]>
Date: Wednesday, February 17, 2021 at 00:27
To: Brian Campbell <[email-masked]>, Torsten Lodderstedt <[email-masked]>
Cc: Vittorio Bertocci <[email-masked]>, "[email-masked]" <[email-masked]>
Subject: Re: [OAUTH-WG] Token Mediating and session Information Backend For Frontend (TMI BFF)

Hey,

Tbh - I have a bit of a hard time to see why this requires a spec, if that is all you are aiming at. Wouldn’t that be just an extension to the “OAuth for web apps BCP?”.

All I can add here is - this approach would not work for any of our customer. Because their real motivation is to implement a more and more common security guideline these days - namely: “no JS-accessible tokens in the browser” - but this document doesn’t cover this.

cheers
———
Dominick Baier

On 16. February 2021 at 22:01:37, Brian Campbell (bcampbell=[email-masked]<mailto:bcampbell=[email-masked]>) wrote:

On Mon, Feb 15, 2021 at 9:48 AM Torsten Lodderstedt <[email-masked]<mailto:[email-masked]>> wrote:
Thank you again for the explanation.

We did attempt to capture the assumptions in the draft but clearly could have done a better job with it :)

 Taking that a bit further - the idea is that the backend takes on the responsibilities of being a confidential client (client creds, token acquisition, token management/persistence, etc.) to the external AS(s). And TMI BFF describes a way for that backend to deliver access tokens to its own frontend.

CONFIDENTIALITY NOTICE: This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, distribution or disclosure by others is strictly prohibited.  If you have received this communication in error, please notify the sender immediately by e-mail and delete the message and any file attachments from your computer. Thank you._______________________________________________
OAuth mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/oauth

---

From: Hans Zandbelt <[email-masked]>
Date: Wed, 17 Feb 2021 18:58:49 +0100

Thanks Vittorio and Brian for starting this work: I have deployed this
pattern in the field on a number occasions, at security and tech savvy
organizations, on their request.
I'd describe it as a regular OAuth 2.0 web client with the addition of a
well known endpoint meant for in-browser (counterpart) clients.

Enterprise security architects seem to prefer this approach because of the
confidential client involved and the ability to outsource a perceived
cumbersome and security sensitive task to a backend
infrastructure component under direct control of the organization rather
than the end user. Even if there's no proven security advantage by letter
of the OAuth 2 spec, it may still be a preferred way of deployment for some
organizations because of the way they want to structure security sensitive
software, the way they deal with software development, and the way they
deal with application and infrastructure management.

I very much agree with all of the arguments Vittorio brought up before and
I really don't see any reason to reject this approach. It is very useful to
list the considerations about this architectural pattern and to give
guidance about when it can be used and when to avoid it, regardless of the
complexity or length of such a spec.

Hans.

On Tue, Feb 16, 2021 at 10:02 PM Brian Campbell <bcampbell=
[email-masked]> wrote:

>
>
>
> On Mon, Feb 15, 2021 at 9:48 AM Torsten Lodderstedt <
> [email-masked]> wrote:
>
> *CONFIDENTIALITY NOTICE: This email may contain confidential and
> privileged material for the sole use of the intended recipient(s). Any
> review, use, distribution or disclosure by others is strictly prohibited.
> If you have received this communication in error, please notify the sender
> immediately by e-mail and delete the message and any file attachments from
> your computer. Thank you.*_______________________________________________
> OAuth mailing list
> [email-masked]

-- 
[email-masked]
ZmartZone IAM - www.zmartzone.eu

---

From: Dominick Baier <[email-masked]>
Date: Wed, 17 Feb 2021 11:43:20 -0800

Yes - “no OAuth tokens in the browser” ;) They are all kept server-side and
the BFF proxies the API calls if necessary. Also the RT management happens
server-side and is transparent to the SPA.

I see that in lots of industries - finance, health, cloud providers

While someone will always say “but this doesn’t solve the XSS problem” -
this is absolutely correct. But when there are no tokens in the browser -
you can simply eliminate that part of the threat model ;)

———
Dominick Baier

On 17. February 2021 at 18:30:23, Vittorio Bertocci (
[email-masked]) wrote:

Thanks Dominick,

It is indeed a very simple spec, but as you can see from the discussion so
far, it doesn’t appear to be trivial- and there might be some
considerations we consider obvious (eg scope escalation) that might not be
super clear otherwise.

In terms of the guidance, just to make sure I get the scope right- that
means that also code+PKCE+rotating RTs in JS would not be acceptable for
your customers?

*From: *Dominick Baier <[email-masked]>
*Date: *Wednesday, February 17, 2021 at 00:27
*To: *Brian Campbell <[email-masked]>, Torsten Lodderstedt <
[email-masked]>
*Cc: *Vittorio Bertocci <[email-masked]>, "[email-masked]" <
[email-masked]>
*Subject: *Re: [OAUTH-WG] Token Mediating and session Information Backend
For Frontend (TMI BFF)

Hey,

cheers

———

Dominick Baier

I think your assumption about the overall flow should be described in the
draft.

---

From: Warren Parad <[email-masked]>
Date: Wed, 17 Feb 2021 20:46:30 +0100

> you can simply eliminate that part of the threat model ;)

The point was it doesn't eliminate anything, it just changes the
request/response data that is part of the attack. This doesn't increase
security, as a matter of fact, with regard to the RFC, we shouldn't talk
about security at all, since it has zero impact on it.

It is worth talking about that pattern as *one* possible solution to
maintaining sessions, but that's it.

Warren Parad

Founder, CTO

On Wed, Feb 17, 2021 at 8:43 PM Dominick Baier <[email-masked]>
wrote:

> Yes - “no OAuth tokens in the browser” ;) They are all kept server-side
> and the BFF proxies the API calls if necessary. Also the RT management
> happens server-side and is transparent to the SPA.
>

---

From: Dominick Baier <[email-masked]>
Date: Wed, 17 Feb 2021 11:50:26 -0800

Well. Maybe it is at least worth while then to at least mention that you
could also take a slightly different approach and eliminate all tokens in
the browser - with the respective trade offs.

———
Dominick Baier

On 17. February 2021 at 20:46:42, Warren Parad ([email-masked]) wrote:

Warren Parad

Founder, CTO

---

From: Warren Parad <[email-masked]>
Date: Wed, 17 Feb 2021 21:00:29 +0100

You mean all but the access token and authorization code, right?

Warren Parad

Founder, CTO

On Wed, Feb 17, 2021 at 8:50 PM Dominick Baier <[email-masked]>
wrote:

>> It is indeed a very simple spec, but as you can see from the discussion
>> so far, it doesn’t appear to be trivial- and there might be some
>> *Subject: *Re: [OAUTH-WG] Token Mediating and session Information
>> Backend For Frontend (TMI BFF)
>>
>>
>>
>> Hey,
>>
>>
>>
>> Tbh - I have a bit of a hard time to see why this requires a spec, if
>> that is all you are aiming at. Wouldn’t that be just an extension to the
>> “OAuth for web apps BCP?”.
>>
>>
>>

---

From: Neil Madden <[email-masked]>
Date: Wed, 17 Feb 2021 20:08:36 +0000

Do you eliminate the cookies too?

> On 17 Feb 2021, at 19:50, Dominick Baier <[email-masked]> wrote:
> 
> 
> Well. Maybe it is at least worth while then to at least mention that you could also take a slightly different approach and eliminate all tokens in the browser - with the respective trade offs.
> 
> ———
> Dominick Baier
> 
>>> While someone will always say “but this doesn’t solve the XSS problem” - this is absolutely correct. But when there are no tokens in the browser - you can simply eliminate that part of the threat model ;)
>> The point was it doesn't eliminate anything, it just changes the request/response data that is part of the attack. This doesn't increase security, as a matter of fact, with regard to the RFC, we shouldn't talk about security at all, since it has zero impact on it.
>> 
>> It is worth talking about that pattern as one possible solution to maintaining sessions, but that's it.
>> 
>> 
>> Warren Parad
>> Founder, CTO
>> Secure your user data with IAM authorization as a service. Implement Authress.
>> 
>> 
>>> On Wed, Feb 17, 2021 at 8:43 PM Dominick Baier <[email-masked]> wrote:
>>> Yes - “no OAuth tokens in the browser” ;) They are all kept server-side and the BFF proxies the API calls if necessary. Also the RT management happens server-side and is transparent to the SPA.
>>> 
>>> While someone will always say “but this doesn’t solve the XSS problem” - this is absolutely correct. But when there are no tokens in the browser - you can simply eliminate that part of the threat model ;)
>>> 
>>> ———
>>> Dominick Baier
>>> 
>>>> On 17. February 2021 at 18:30:23, Vittorio Bertocci ([email-masked]) wrote:
>>>> 
>>>> Thanks Dominick,
>>>> 
>>>> On 16. February 2021 at 22:01:37, Brian Campbell (bcampbell=[email-masked]) wrote:
>>>> 
>>>>  
>>>> 
>>>>  
>>>> 
>>>>  
>>>> 
>>>> On Mon, Feb 15, 2021 at 9:48 AM Torsten Lodderstedt <[email-masked]> wrote:
>>>>

---

From: Brian Campbell <[email-masked]>
Date: Wed, 17 Feb 2021 15:48:12 -0700

Always appreciate (and often learn from) your insights, Neil. I'd like to
dig into the CSRF thing a bit more though to understand better and
hopefully do the right thing in the draft.

It seems to me that a GET at the bff-token endpoint is "safe" in that it's
effectively just a read. There could be a "cache miss" where the backend
attempts to use a refresh token it has to get a new access token from the
remote AS, which will be more resource intensive but doesn't fundamentally
alter the state of the backend so is still "safe". That in conjunction with
your pointing to Cross-Origin Read Blocking makes me think your concern
isn't so much about traditional CSRF used to take some malicious action but
rather about somehow (speculative side-channel attacks, problems with
javascript interpreters, other similar vectors that are somewhat beyond me)
accessing the data of the response to a forged cross site request. Correct
me if I'm wrong. I don't know if or how much the distinction matters in
terms of mitigation approach but I'm keen to better understand.

It sounds like your preference for only POST rests in an assumption that
the larger app will already have in place some CSRF defenses and by using
POST the bff-token endpoint will basically inherit said defenses. Or is
POST by itself good enough (the CORB writeup seems to suggest that the
context in which a POST could be made is more guarded against side channel
stuff)?  But perhaps then the draft should be more explicit about CSRF
defense? Saying it just has to be done. Or like even mandating a
non-standard header be in the request, "X-Neil-says-beware-CSRF: yuppers"
as a strawman. With such a header it could remain a GET. And I kinda like
GET because it is really a request for data.  Or perhaps the request should
be a POST with built-in CSRF protection by changing it to carry any
parameters as JSON in the body with "{}" for the case of no parameters
specified?  Or just make it a PUT and call it good? Not sure any of these
are good ideas but just trying to hash out the most appropriate thing to
do.

That got a little rambly, sorry. But hopefully it makes some sense.

---

From: Dominick Baier <[email-masked]>
Date: Wed, 17 Feb 2021 23:43:08 -0800

No. But they are CSRF protected (either SameSite or anti-forgery) and
HttpOnly.

———
Dominick Baier

On 17. February 2021 at 21:08:37, Neil Madden ([email-masked])
wrote:

———
Dominick Baier

Warren Parad

Founder, CTO

---

From: Neil Madden <[email-masked]>
Date: Thu, 18 Feb 2021 12:08:55 +0000

Thanks for following up, Brian. Responses below.

> On 17 Feb 2021, at 22:48, Brian Campbell <[email-masked]> wrote:
> 
> Always appreciate (and often learn from) your insights, Neil. I'd like to dig into the CSRF thing a bit more though to understand better and hopefully do the right thing in the draft. 
> 
> It seems to me that a GET at the bff-token endpoint is "safe" in that it's effectively just a read.

Well it’s a read that returns an access token. It’s “safe” in the sense of side-effects, but we absolutely want to preserve the confidentiality of what is returned and only allow it to be accessed by authorized clients (the legitimate frontend). At the moment the only thing keeping that safe is the JSON content type. For example, imagine a world in which the token-bff endpoint instead returned the access token as HTML:

<div id=“accessToken”>abcd</div>

Then as an attacker I can simply embed an iframe on my site that refers to your bff-endpoint and then parse the access token out of the DOM. The browser will happily load that iframe and send along the cookie when it makes the request. If you have CORS enabled on your site (with Access-Control-Allow-Credentials) then any of the allowed CORS origins can directly call the bff-token endpoint and read the access token even in JSON form. There have also been historical same-origin policy bypasses using Flash, Adobe Reader, or other plugins (thankfully now largely eliminated), or by redefining JavaScript prototypes - see https://haacked.com/archive/2009/06/25/json-hijacking.aspx/ <https://haacked.com/archive/2009/06/25/json-hijacking.aspx/> . These are largely fixed, but I wouldn’t bet on there never being another one.

> There could be a "cache miss" where the backend attempts to use a refresh token it has to get a new access token from the remote AS, which will be more resource intensive but doesn't fundamentally alter the state of the backend so is still "safe". That in conjunction with your pointing to Cross-Origin Read Blocking makes me think your concern isn't so much about traditional CSRF used to take some malicious action but rather about somehow (speculative side-channel attacks, problems with javascript interpreters, other similar vectors that are somewhat beyond me) accessing the data of the response to a forged cross site request. Correct me if I'm wrong. I don't know if or how much the distinction matters in terms of mitigation approach but I'm keen to better understand.  

As explained above, because the endpoint returns JSON it _should_ be impossible to directly read the response from a cross-origin read (unless explicitly enabled with CORS). But you may still be able to embed that response in an <img> or similar. Because people are terrible at setting correct Content-Type headers on responses, browsers often ignore them and instead try to sniff what the real content type is: so if the response looks a bit like a valid image format (or PDF or JavaScript or whatever) then it might try and render it. No doubt this will fail, but at that point the data has already been loaded into the address space of the renderer process for the attacker’s site. That means that it is then vulnerable to attacks like Spectre that bypass normal memory protection. The browser vendors consider this to be a real threat, hence CORB.

The most important thing for a cookie-based JSON API to do is to return a correct Content-Type header and to also return X-Content-Type-Options: nosniff to prevent browsers from trying to sniff the real content-type. (I have an example in my book where the failure to do this can actually turn a JSON API into a vector for XSS attacks, even if you have no SPA frontend component at all).

(You should also mark the cookie as HttpOnly because this prevents the cookie ever entering the address space of a renderer process in modern browsers - an actual genuine security benefit of HttpOnly cookies).

But my worry is that this is still basically trusting the client to perform critical security checks, and historically browsers have had plenty of bypasses in this area. So for something as high-value as an access token I’d prefer that any request using cookie-based authentication is protected by proactive CSRF defences to prevent malicious requests being allowed in the first place.

> 
> It sounds like your preference for only POST rests in an assumption that the larger app will already have in place some CSRF defenses and by using POST the bff-token endpoint will basically inherit said defenses. Or is POST by itself good enough (the CORB writeup seems to suggest that the context in which a POST could be made is more guarded against side channel stuff)?  But perhaps then the draft should be more explicit about CSRF defense? Saying it just has to be done. Or like even mandating a non-standard header be in the request, "X-Neil-says-beware-CSRF: yuppers" as a strawman. With such a header it could remain a GET. And I kinda like GET because it is really a request for data.  Or perhaps the request should be a POST with built-in CSRF protection by changing it to carry any parameters as JSON in the body with "{}" for the case of no parameters specified?  Or just make it a PUT and call it good? Not sure any of these are good ideas but just trying to hash out the most appropriate thing to do. 

Right, the preference for POST is because it's more likely to trigger CSRF defences, which often consider GET/HEAD requests to be “safe”. Even before Spectre, there is a whole array of side-channel attacks for extracting information from cross-site responses: https://xsleaks.dev <https://xsleaks.dev/> . Note that even SameSite has a "GET-out clause" in the form of “lax”.

So yes, the real requirement is that the endpoint should have adequate CSRF protection. Requiring a special header has had bypasses in the past (again, mostly using Flash).

So I think we should recommend the following:

1. The response MUST contain a correct Content-Type: application/json header and X-Content-Type-Options: nosniff.
2. The cookie SHOULD be marked as HttpOnly.
3. The endpoint MUST NOT be accessible via CORS.
4. The endpoint SHOULD have adequate CSRF protections in place. At a minimum the cookie should be marked as SameSite. 

We could perhaps add an informational reference to https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html <https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html> given that there is a changing landscape around cookies at the moment. If the browser vendors do eliminate 3rd-party cookies then 1, 3, and 4 become largely unnecessary (although 3 might still be a risk due to sub-domain hijacking, and 1 will always be good practice).

— Neil

> On Sun, Feb 14, 2021 at 1:17 AM Neil Madden <[email-masked] <mailto:[email-masked]>> wrote:
> 
> CONFIDENTIALITY NOTICE: This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, distribution or disclosure by others is strictly prohibited.  If you have received this communication in error, please notify the sender immediately by e-mail and delete the message and any file attachments from your computer. Thank you.

---

From: Philippe De Ryck <[email-masked]>
Date: Thu, 18 Feb 2021 13:25:40 +0100

> On 18 Feb 2021, at 13:08, Neil Madden <[email-masked]> wrote:
> 
>> On 17 Feb 2021, at 22:48, Brian Campbell <[email-masked] <mailto:[email-masked]>> wrote:
>> 
> Then as an attacker I can simply embed an iframe on my site that refers to your bff-endpoint and then parse the access token out of the DOM. The browser will happily load that iframe and send along the cookie when it makes the request.

You are overlooking basic browser security measures like the Same-Origin Policy here. The browser will only allow access to an iframe if it has the same origin as the context accessing the frame. If an attacker embeds this frame in their site, it will be a cross-origin frame, and access will be denied.

FYI, simple CORS requests follow the same security pattern (when headers are missing, browsers do not expose the response). Preflighted CORS requests cover "new features" (i.e., stuff you traditionally could not do with HTML elements) and ask permission before sending a request. 

Also, if you're worried about framing, it's much simpler to require the token endpoint to send "X-Frame-Options: DENY" and "Content-Security-Policy: frame-ancestors 'none'" response headers. This denies framing altogether without going into complicated CORS territory.

Philippe

—
Pragmatic Web Security
Security for developers

---

From: Neil Madden <[email-masked]>
Date: Thu, 18 Feb 2021 14:02:42 +0000

> On 18 Feb 2021, at 12:25, Philippe De Ryck <[email-masked]> wrote:
> 

Right, HTML was a bad example. But again remember that at this point the content is already loaded into the renderer process and so vulnerable to Spectre and other side-channel attacks. 

As MDN says (https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy):

“To prevent cross-origin reads of a resource, ensure that it is not embeddable. It is often necessary to prevent embedding because embedding a resource always leaks some information about it.”

My point is that the server is performing essentially no real security checks and relying on the user-agent for pretty much all security guarantees. This is ok when those mechanisms are robust, but they really aren’t in the case of embeddable resources and browser vendors are still trying to close all the holes. 

> 
> FYI, simple CORS requests follow the same security pattern (when headers are missing, browsers do not expose the response).

But many sites already return those CORS headers to enable cross-origin functionality. On those sites bff-token is completely insecure because cross-origin clients can now use that access to get an access token intended for the first-party SPA and use it to access other APIs! I can’t emphasise enough how much of a security disaster this could be. 

> Preflighted CORS requests cover "new features" (i.e., stuff you traditionally could not do with HTML elements) and ask permission before sending a request. 

But GET requests don’t trigger preflight unless they have custom headers.

> Also, if you're worried about framing, it's much simpler to require the token endpoint to send "X-Frame-Options: DENY" and "Content-Security-Policy: frame-ancestors 'none'" response headers. This d…

You’re pretty much entirely missing the point of my message if you think it’s about framing specifically. Think of all the possible ways there are to embed cross-origin resources: CSS stylesheets, script embedding, images, video, audio, fonts, WebGL textures, objects, etc. If a new endpoint requires setting 15 new CSP policies just to make it not obviously insecure, it’s maybe a clue that it’s not a sensible design. 

To say that we’re not comfortable with tokens in localStorage but to then expose a simple GET endpoint for retrieving access tokens is IMO not a good idea. The SOP protections applied to localStorage are *far* more robust than those applied to GET requests. 

— Neil

---

From: Brian Campbell <[email-masked]>
Date: Fri, 19 Feb 2021 16:17:47 -0700

Thanks Neil,
Appreciate the insight and recommendations. I think we can incorporate
that, more or less, into the next revision.
One point to dig into just a bit more, you said that 'SameSite has a
"GET-out clause" in the form of “lax”'. As I understand it, such a cookie
would still only be sent on a cross-site GET resulting from a top-level
navigation. And in the context of the bff-token endpoint, that
significantly reduces the ways a cross-site request could be initiated and
those ways (pop-up or full page redirection) further limits the likelihood
of the malicious party being able to read response data.

On Thu, Feb 18, 2021 at 5:08 AM Neil Madden <[email-masked]>
wrote:

> effectively just a read.
> Well it’s a read that returns an access token. It’s “safe” in the sense of
> side-effects, but we absolutely want to preserve the confidentiality of
> what is returned and only allow it to be accessed by authorized clients
> (the legitimate frontend). At the moment the only thing keeping that safe
> is the JSON content type. For example, imagine a world in which the
> token-bff endpoint instead returned the access token as HTML:
>
> Then as an attacker I can simply embed an iframe on my site that refers to
> your bff-endpoint and then parse the access token out of the DOM. The
> browser will happily load that iframe and send along the cookie when it
> makes the request. If you have CORS enabled on your site (with
> Access-Control-Allow-Credentials) then any of the allowed CORS origins can
> directly call the bff-token endpoint and read the access token even in JSON
> form. There have also been historical same-origin policy bypasses using
> Flash, Adobe Reader, or other plugins (thankfully now largely eliminated),
> or by redefining JavaScript prototypes - see
> https://haacked.com/archive/2009/06/25/json-hijacking.aspx/ . These are
> largely fixed, but I wouldn’t bet on there never being another one.
>
>
> There could be a "cache miss" where the backend attempts to use a refresh
> token it has to get a new access token from the remote AS, which will be
> more resource intensive but doesn't fundamentally alter the state of the
> backend so is still "safe". That in conjunction with your pointing to
> Cross-Origin Read Blocking makes me think your concern isn't so much about
> traditional CSRF used to take some malicious action but rather about
> somehow (speculative side-channel attacks, problems with javascript
> interpreters, other similar vectors that are somewhat beyond me) accessing
> the data of the response to a forged cross site request. Correct me if I'm
> wrong. I don't know if or how much the distinction matters in terms of
> mitigation approach but I'm keen to better understand.
>
>
> As explained above, because the endpoint returns JSON it _should_ be
> impossible to directly read the response from a cross-origin read (unless
> explicitly enabled with CORS). But you may still be able to embed that
> response in an <img> or similar. Because people are terrible at setting
> correct Content-Type headers on responses, browsers often ignore them and
> instead try to sniff what the real content type is: so if the response
> looks a bit like a valid image format (or PDF or JavaScript or whatever)
> then it might try and render it. No doubt this will fail, but at that point
> the data has already been loaded into the address space of the renderer
> process for the attacker’s site. That means that it is then vulnerable to
> attacks like Spectre that bypass normal memory protection. The browser
> vendors consider this to be a real threat, hence CORB.
>
> The most important thing for a cookie-based JSON API to do is to return a
> correct Content-Type header and to also return X-Content-Type-Options:
> nosniff to prevent browsers from trying to sniff the real content-type. (I
> have an example in my book where the failure to do this can actually turn a
> JSON API into a vector for XSS attacks, even if you have no SPA frontend
> component at all).
>
> (You should also mark the cookie as HttpOnly because this prevents the
> cookie ever entering the address space of a renderer process in modern
> browsers - an actual genuine security benefit of HttpOnly cookies).
>
> But my worry is that this is still basically trusting the client to
> perform critical security checks, and historically browsers have had plenty
> of bypasses in this area. So for something as high-value as an access token
> I’d prefer that any request using cookie-based authentication is protected
> by proactive CSRF defences to prevent malicious requests being allowed in
> the first place.
>
>
> Right, the preference for POST is because it's more likely to trigger CSRF
> defences, which often consider GET/HEAD requests to be “safe”. Even before
> Spectre, there is a whole array of side-channel attacks for extracting
> information from cross-site responses: https://xsleaks.dev . Note that
> even SameSite has a "GET-out clause" in the form of “lax”.
>
> So yes, the real requirement is that the endpoint should have adequate
> CSRF protection. Requiring a special header has had bypasses in the past
> (again, mostly using Flash).
>
> 1. The response MUST contain a correct Content-Type: application/json
> header and X-Content-Type-Options: nosniff.
> 4. The endpoint SHOULD have adequate CSRF protections in place. At a
> minimum the cookie should be marked as SameSite.
>
> We could perhaps add an informational reference to
> https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html given
> that there is a changing landscape around cookies at the moment. If the
> browser vendors do eliminate 3rd-party cookies then 1, 3, and 4 become
> largely unnecessary (although 3 might still be a risk due to sub-domain
> hijacking, and 1 will always be good practice).
>
> — Neil
>
>
> your computer. Thank you.*
>
>
>

---

From: Neil Madden <[email-masked]>
Date: Sat, 20 Feb 2021 09:07:44 +0000

I was mentioning it primarily as another example of the assumption that GET requests are safe. However, the draft rfc6265bis [1] does seem concerned about this, and mentions <link rel=prerender> as a possible attack vector. This would again potentially pull the access token into the renderer’s memory space (until site isolation becomes widespread). 

I also have a general dislike of SameSite cookies as a defence against CSRF. There are CSRF-like attacks that are not strictly cross-*site* but are cross-origin (CORF?). For example, subdomain hijacking is relatively common [2] and completely defeats SameSite. As the draft itself says [3]:

<quote>

   "SameSite" cookies offer a robust defense against CSRF attack when
   deployed in strict mode, and when supported by the client.  It is,
   however, prudent to ensure that this designation is not the extent of
   a site's defense against CSRF, as same-site navigations and
   submissions can certainly be executed in conjunction with other
   attack vectors such as cross-site scripting.

   Developers are strongly encouraged to deploy the usual server-side
   defenses (CSRF tokens, ensuring that "safe" HTTP methods are
   idempotent, etc) to mitigate the risk more fully.
</quote>

If we recommend SameSite for this, IMO we should do so only with the same caveats expressed in the httpbis draft. 

[1]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-07#section-5.3.7.1
[2]: https://www.hackerone.com/blog/Guide-Subdomain-Takeovers#
[3]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-07#section-8.8.1

Cheers,

Neil

> On 19 Feb 2021, at 23:18, Brian Campbell <[email-masked]> wrote:
> 
> 
> Thanks Neil, 
> Appreciate the insight and recommendations. I think we can incorporate that, more or less, into the next revision. 
> One point to dig into just a bit more, you said that 'SameSite has a "GET-out clause" in the form of “lax”'. As I understand it, such a cookie would still only be sent on a cross-site GET resulting from a top-level  navigation. And in the context of the bff-token endpoint, that significantly reduces the ways a cross-site request could be initiated and those ways (pop-up or full page redirection) further limits the likelihood of the malicious party being able to read response data. 
> 
>> On Thu, Feb 18, 2021 at 5:08 AM Neil Madden <[email-masked]> wrote:
>> Then as an attacker I can simply embed an iframe on my site that refers to your bff-endpoint and then parse the access token out of the DOM. The browser will happily load that iframe and send along the cookie when it makes the request. If you have CORS enabled on your site (with Access-Control-Allow-Credentials) then any of the allowed CORS origins can directly call the bff-token endpoint and read the access token even in JSON form. There have also been historical same-origin policy bypasses using Flash, Adobe Reader, or other plugins (thankfully now largely eliminated), or by redefining JavaScript prototypes - see https://haacked.com/archive/2009/06/25/json-hijacking.aspx/ . These are largely fixed, but I wouldn’t bet on there never being another one.
>> 
>> 
>> Right, the preference for POST is because it's more likely to trigger CSRF defences, which often consider GET/HEAD requests to be “safe”. Even before Spectre, there is a whole array of side-channel attacks for extracting information from cross-site responses: https://xsleaks.dev . Note that even SameSite has a "GET-out clause" in the form of “lax”.
>> 
>> We could perhaps add an informational reference to https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html given that there is a changing landscape around cookies at the moment. If the browser vendors do eliminate 3rd-party cookies then 1, 3, and 4 become largely unnecessary (although 3 might still be a risk due to sub-domain hijacking, and 1 will always be good practice).
>> 
>> — Neil
>> 
>>> 
>>>> On Sun, Feb 14, 2021 at 1:17 AM Neil Madden <[email-masked]> wrote:
>>>> 
>> ForgeRock values your Privacy
>

---

From: George Fletcher <[email-masked]>
Date: Tue, 23 Feb 2021 10:20:39 -0500

Unfortunately, in the mobile app world this isn't sufficient. On iOS 
using Universal Links will bind the https redirect_url to your app in a 
secure way but it doesn't work the same way on Android with App Links. 
There is still a problem with "mobile app impersonation". If you have an 
app that you want to ensure is "your" app then the most secure way is to 
look at "app attestation". This is however, way off topic for this thread :)