Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address gaps in BPoP protocol and feedback #667

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

sameerag
Copy link
Contributor

@sameerag sameerag commented Aug 8, 2023

Added support for the below:

  1. Edited the Explainer to add:

    • refresh-in support for background nonce renewal
    • expires-in support to reduce key verification frequency
    • Added adaptation considerations and key management considerations
  2. Added a new document (similar content but format more friendly for a W3 explainer)

  3. Pending:

    • Sequence diagrams

@sameerag sameerag requested a review from will-bartlett August 8, 2023 19:19
@sameerag sameerag self-assigned this Aug 8, 2023
Copy link

@oldalton oldalton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting it together, added a couple of comments.

BindingContext/BPoP.md Show resolved Hide resolved
BindingContext/BPoP.md Outdated Show resolved Hide resolved
- `refresh-in` is an optional number whose value indicates the number of seconds after which the browser should refresh the BPoP proof. The value MUST be an integer greater than 0.
- `expires-in` is an optional number whose value indicates the number of seconds after which the browser should stop using the BPoP proof. The default is 5 minutes (minimum nonce validity). The value MUST be an integer greater than 0.

A web server may also optionally return a `BPoP-Nonce` header, containing a nonce value to be included in BPoP proofs sent to them. The nonce syntax in ABNF used by [RFC6749](https://www.rfc-editor.org/rfc/rfc6749.html) is `nonce = 1*NQCHAR`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is client expected to do if there's no Nonce returned? Use current local device time?

BindingContext/BPoP.md Outdated Show resolved Hide resolved

The browser only attaches BPoP proofs to "secure" protocols (as defined by the user agent).

The browser maintains one public private key pair per sub entity to the effective top-level domain (eTLD+1). That is, if `a.example.com`, `b.example.com`, and `c.example.com` each activate BPoP, they share a single public private key pair.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note that this behavior only applies if there's no enterprise policy override? Also, should we call out the possibility of an enterprise policy configuring how keys are stored (same as in the explainer)? Otherwise, if someone only reads this document and not the explainer, then this detail would be missed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a caveat. Will work on enterprise section once we reach a consensus on the same.

- Instead of the browser choosing keys for BPoP proofs, the enterprise policy provider chooses the keys.
- The enterprise policy provider may augment the BPoP proof payload with additional claims.

- Instead of the browser choosing keys for BPoP proofs, the enterprise policy provider chooses the keys.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe let's provide a bit more information on what this means in practice to make sure we're aligned on what this means?
For example, I'm thinking that it's important that a mechanism that browsers implement should provide a way for code execution in the native process (e.g. WAM on Windows, SSO extension on Mac, broker service inside Authenticator on Android) and the native process should get sufficient information about the caller to verify it (as opposed to a static configuration driven by the enterprise policy telling browser how to generate keys).

Another aspect is that I'm not sure about is whether we'd want that process to supply/attest keys, or generate the actual BPop proof? Would be great to align and call out as well to drive consistency in browser implementations once we get that far.

BindingContext/BPoP.md Outdated Show resolved Hide resolved
BindingContext/BPoP.md Outdated Show resolved Hide resolved
BindingContext/BPoP.md Outdated Show resolved Hide resolved
BindingContext/BPoP.md Outdated Show resolved Hide resolved

1. Webpage user goes to `example.com`, and initiates login. `example.com` redirects to `login.microsoftonline.com`, using javascript or http headers to active binding for `example.com` cookies.
2. `login.microsoftonline.com`, shows password prompt, javascript or http header activates binding for eSTS cookie
3. enter password, ESTS SHR in http request, response contains bound eSTS cookie, redirect to example.com with auth code
Copy link

@oldalton oldalton Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit confused, who generates SHR in this step? Is it JS running in STS context when it is submitting a request to validate password and issue auth code?

ESTS SHR in http request

Consider expanding/improving wording a bit for clarity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agreed. Sorry, I planned to checkin after expanding this, :). Will get it in the next draft.

@@ -210,6 +227,8 @@ BPoP: enabled, SameSite=None

The latest configuration replaces the previous configuration. Replacement occurs for the entire config, not just for configuration elements who appear in the `BPoP` header.

Please note that this behavior applies only when there is no enterprise policy override. In case if enterprise policy enabled by the browser config, the BPoP behaves as configured by the policy. More details on key management and storage for enterprise use cases are covered later in this document.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my learning, do you know what specific enterprise policy mechanism we'd want to use? Whatever is built into the browser? I was reading about Chrome's policies here, and didn't see a reference to mobile, I think mobile isn't supported: https://support.google.com/chrome/a/answer/9037717?hl=en

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can find out, I am not very familiar with it either. Will check with the google engineer and get back.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://chromeenterprise.google/policies/#PasswordManagerEnabled - This has an example for mobile. A policy set should reflect at chrome://policy/ as per google. Hope this helps.

@alextok
Copy link

alextok commented Sep 27, 2023

A server may also return a new BPoP nonce on any 200 response.

why only 200? why it cannot be any response. We get first nonce via 401


Refers to: BindingContext/explainer.md:173 in bec12c8. [](commit_id = bec12c8, deletion_comment = False)

@sameerag
Copy link
Contributor Author

sameerag commented Sep 27, 2023

A server may also return a new BPoP nonce on any 200 response.

why only 200? why it cannot be any response. We get first nonce via 401

Refers to: BindingContext/explainer.md:173 in bec12c8. [](commit_id = bec12c8, deletion_comment = False)

I think it is in-reference to piggy backing on regular oath flows, that BPoP-Nonce can be attached to any successful oauth response, and not specifically requested. @will-bartlett can clarify more.

2. `login.microsoftonline.com`, shows password prompt, javascript or http header activates binding for the cookie.
3. After the user enters the password, SHR in http request, response contains bound eSTS cookie, redirect to example.com with auth code
4. `example.com` SHR in http request, response from `example.com` contains bound `example.com` cookie

Copy link

@peterzenz peterzenz Oct 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sequence diagram here might be useful? Should we generalize the domain names here so it's less Microsoft specific? example.com & loginservice.com

BPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v
```

Such a response header indicates to a browser client that it SHOULD generate a proof of possession key and attach a BPoP proof to future requests. If a browser client does not support any of the algorithms in `algs`, or for any other reason, the browser may skip BPoP. If the browser skips BPoP, the web server SHOULD continue to issue cookies without binding, unless forbidden by the web server's security policy.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BPoP: enabled 
...
unless forbidden by the web server's security policy.

Maybe: "BPoP" needs an additional states? none|disabled == disabled, enabled = optional, and required for server will enforce BPoP

BPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v
```

In such a case, the browser should update the BPoP proof and retry the request immediately. Servers SHALL not ask for more than one retry this way.
Copy link

@jbenallen jbenallen Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the same client sends multiple concurrent requests in flight with the same BPoP proof before it receives a 401 and WWW-Authenticate: BPoP... response from the server, how should the server respond to the other requests that were already sent with the same invalid BPoP proof?

The comparable DBSC proposal attempts to solve this by client-side logic in the protocol that holds and queues requests when its proof has expired until it can refresh it (it uses an auxiliary cookie as its proof).

expires-in: 300
```

The client SHOULD start using the new nonce on the next request.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the server expected to provide rotation semantics for the nonce by supporting multiple nonces with overlapping windows? If so, should the server start sending a new BPoP nonce back even while it continues to accept a previous one for some period of time?

BPoP: enabled, SameSite=None
```

The latest configuration replaces the previous configuration. Replacement occurs for the entire config, not just for configuration elements who appear in the `BPoP` header.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this BPoP per-origin data also be covered by Clear-Site-Data? It's not clear to which of the individual site data types it belongs. BPoP may be used to bind other data from both storage and cookies, so it doesn't seem to fit neatly in either of them alone.


#### BPoP background refresh

The server response should also include a `refresh-in` parameter, that enables the app to refresh the nonce in a certain interval. This should help the APIs dependent on BPoP to proactively refresh the nonce in the background avoiding the need to refresh the nonce on demand.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does the client execute a refresh? It needs a new nonce from the server, but the protocol only indicates that a nonce is provided in a server-generated response to any arbitrary request at the same origin. This implies the client has to send a request after the refresh timer elapses, but where does it send it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants