- From: Mike West <notifications@github.com>
- Date: Mon, 05 Mar 2018 14:54:14 -0800
- To: whatwg/fetch <fetch@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/fetch/pull/325/review/98842249@github.com>
mikewest commented on this pull request. Talked in person, here are some comments. > @@ -1034,6 +1057,35 @@ for other values. If <cite>HTML</cite> changes here, this standard will need cor <dfn export for=request id=concept-request-use-url-credentials-flag>use-URL-credentials flag</dfn>. Unless stated otherwise, it is unset. +<p>A <a for=/>request</a> has an associated +<dfn export for=request id=concept-request-use-token-binding>use-token-binding flag</dfn>. +Unless stated otherwise, it is unset. + +<p class="note no-backref"><a for=/>Request</a>'s <a for=request>use-token-binding flag</a> +controls whether the user agent will send the <a for=/>token binding ID</a> for the +<a for=request>origin</a> of the <a for=/>request</a>'s url when it transmits the +<a for=/>request</a> to the server. The <a for=/>token binding ID</a> can be used by the server to, +e.g., bind HTTP cookies or OAuth tokens that it issues to the user agent. + +<p>A <a for=/>request</a> has an associated +<dfn export for=request id=concept-request-referred-token-binding-origin>referred-token-binding origin</dfn>, +which is an <a for=/>origin</a>. Nit: "which is an origin or null," > @@ -1519,6 +1572,16 @@ for each associated <a for="fetch group">fetch record</a> whose <a>connection</a> is identified by an <b>origin</b> (an <a for=/>origin</a>) and <b>credentials</b> (a boolean). +<p>A <a>connection</a> has associated +<dfn export for=connection id=concept-tls-connection-metadata>TLS connection metadata</dfn> that consists of: +<ul class=brief> + <li><a for=/>token-binding protocol version</a>, initially null. + <li><a for=/>token-binding key parameters</a>, initially null. + <li><a for=/>token-binding Exported Keying Material</a>, initially null. I think this is clearer if you make these properties of "connection", rather than defining a metadata struct thing. That is, I'd suggest rewriting the connection pool paragraph along the lines of: ``` A <dfn>connection</dfn> is a communication channel between the user agent and an origin. A <a>connection</a> has an associated <dfn for=connection>origin</dfn>, which is an <a for=/>origin</a>. A <a>connection</a> has an associated <dfn for=connection>credential</dfn>, which is a boolean. Its value is `false` unless otherwise specified. A <a>connection</a> has an associated <dfn for=connection>token-binding protocol version</dfn>, which is a string(?) or null. Its value is null unless otherwise specified. ... A user agent has an associated <dfn>connection pool</dfn>, which is a set of <a>connections</a>. ``` Each of the "token-binding XXX" bits can link to the more detailed description in the "At a very high level" section below to describe their values. > @@ -1538,6 +1601,27 @@ for each associated <a for="fetch group">fetch record</a> whose <var>origin</var>. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] [[!TLS]] + <p>If <var>credentials</var> is true and the user agent supports <a for=/>Token Binding</a>, + send <a for=/>token-binding protocol version</a> and Perhaps this is a little clearer if it reads more like "If whatever and whatever, then send X and Y while establishing the HTTP connection (as described in section 2 of whatever). In this case, if token binding negotiation succeeds, set A and B to Q and C to R." > @@ -1538,6 +1601,27 @@ for each associated <a for="fetch group">fetch record</a> whose <var>origin</var>. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] [[!TLS]] + <p>If <var>credentials</var> is true and the user agent supports <a for=/>Token Binding</a>, + send <a for=/>token-binding protocol version</a> and + <a for=/>token-binding key parameters</a> in a + <code>token_binding</code> Client Hello Extension, as described in + <a href="https://tools.ietf.org/html/draft-ietf-tokbind-negotiation#section-2">section 2</a> + of the Token Binding Negotiation spec [[!TOKBIND-NEGOTIATION]]. + If Token Binding negotiation succeeds, set + <a for=/>token-binding protocol version</a> and + <a for=/>token-binding key parameters</a> + in <var>connection</var>'s <a for=connection>TLS connection metadata</a> + to the negotiated values, + and <a for=/>token-binding Exported Keying Material</a> to the computed value. This bit is still pretty hand-wavey (What are "the negotiated values"? What is "the computed value"?). Does the negotiation spec expose more explicit algorithms we could link to to clarify the expectations? > +using the user agent's <a for=/>token-binding key</a> store, by running these substeps: + +<ol> + <li><p>Let <var>keyDomainName</var> be null. + + <li><p>If <var>tokenBindingOrigin</var>'s host is an IP address, set <var>keyDomainName</var> to + <var>tokenBindingOrigin</var>'s host. + + <p>Otherwise, set <var>keyDomainName</var> to the registrable domain of + <var>tokenBindingOrigin</var>'s host, determined by running the steps in the Algorithm section of + <a href=https://publicsuffix.org/list/>Public Suffix List</a> + [[PUBLIC-SUFFIX]] + + <li><p>Let <var>tokenBindingKeyPair</var> be null. + + <li><p>Set <var>tokenBindingKeyPair</var> to the result of looking up the Can you add a note to that effect? > + <li><p>If <var>tokenBindingKeyPair</var> is null, create a new key pair for + <var>keyDomainName</var> using <var>tokenBindingKeyParameters</var>, save it in the + <a for=/>token-binding key store</a>, and set <var>tokenBindingKeyPair</var> to that new key pair. + + <li><p>Return <var>tokenBindingKeyPair</var>. +</ol> + + +<h4 id=computing-token-binding-header-value>Computing a Token Binding Header Value</h4> + +<p><dfn abstract-op export id=concept-compute-token-binding-header-value>Compute a Token Binding header value</dfn> +that can be passed in a `<a http-header><code>Sec-Token-Binding</code></a>` +<a for=/>header</a> for a <a for=/>request</a> +<var>httpRequest</var> and a <a>connection</a> <var>tlsConnection</var>, +using the <a for=/>token-binding key store</a> and the +<a for=connection>connection pool</a>, by running these substeps: Can you update this to `for=/`, here and elsewhere? The pool isn't a property of the connection. > @@ -1246,6 +1298,7 @@ or "<code>worker</code>". </ol> <li><p>If the ongoing fetch is <a for=fetch>terminated</a>, then abort these in-parallel steps. + Nit: Stray `\n`? > @@ -1538,6 +1601,27 @@ for each associated <a for="fetch group">fetch record</a> whose <var>origin</var>. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] [[!TLS]] + <p>If <var>credentials</var> is true and the user agent supports <a for=/>Token Binding</a>, + send <a for=/>token-binding protocol version</a> and (Also, I think we decided to drop the "supports Token Binding" bit in an earlier iteration of this review?) > @@ -2325,6 +2409,251 @@ X-Content-Type-Options = "nosniff" ; case-insensitive</pre> <a for=request/destination>script-like</a> or "<code>style</code>" are considered as any exploits pertain to them. Also, considering "<code>image</code>" was not compatible with deployed content. +<h3 id=token-binding>Token Binding</h3> + +<p>In order to protect security tokens like HTTP cookies and OAuth tokens, user agents and servers +can use a technique known as <dfn export id=concept-token-binding>Token Binding</dfn> to +cryptographically associate a given token with a secret +(a <dfn export id=concept-token-binding-key>token-binding key</dfn>) known only to a specific Nit: I'd move the parenthetical after "specific user agent". > @@ -2325,6 +2409,251 @@ X-Content-Type-Options = "nosniff" ; case-insensitive</pre> <a for=request/destination>script-like</a> or "<code>style</code>" are considered as any exploits pertain to them. Also, considering "<code>image</code>" was not compatible with deployed content. +<h3 id=token-binding>Token Binding</h3> + +<p>In order to protect security tokens like HTTP cookies and OAuth tokens, user agents and servers +can use a technique known as <dfn export id=concept-token-binding>Token Binding</dfn> to +cryptographically associate a given token with a secret +(a <dfn export id=concept-token-binding-key>token-binding key</dfn>) known only to a specific +user agent. This association mitigates the risk that attackers can steal the token and use it +themselves, as they will not be able to easily replicate the user agent's secret, +and therefore will be unable to replicate the cryptographic binding of the token. + +<p>Details are described in TOKBIND-NEGOTIATION, TOKBIND-PROTOCOL and +TOKBIND-HTTPS and integration is defined here. +[[TOKBIND-NEGOTIATION]], [[TOKBIND-PROTOCOL]], and [[TOKBIND-HTTPS]]. I'd move the `[[TOKBIND-NEGOTIATION]]`, etc. into the sentence, rather than repeating them. > + <a href="https://tools.ietf.org/html/draft-ietf-tokbind-negotiation#section-2">section 2</a> + of the Token Binding Negotiation spec [[!TOKBIND-NEGOTIATION]]. + If Token Binding negotiation succeeds, set + <a for=/>token-binding protocol version</a> and + <a for=/>token-binding key parameters</a> + in <var>connection</var>'s <a for=connection>TLS connection metadata</a> + to the negotiated values, + and <a for=/>token-binding Exported Keying Material</a> to the computed value. + + <p class="note no-backref"> + The user agent will use <a for=/>Token Binding</a> for any + <a for=/>request</a> sent over a TLS connection for which Token Binding + negotiation was successful. + <a for=/>Token Binding</a> is only proposed when <var>credentials</var> + is true, so connections which successfully negotiate a binding will never be + pooled with connections that do not include credentials. I think we also need to note something about the coalescing behavior for H/2 connections to distinct origins. Do we use a single binding for `google.com` and `youtube.com`, for example? I think we do, given the request-specific nature of the actual key, and the connection-level nature of the version metadata, but it's worth spelling out somewhere. > +of [[TOKBIND-PROTOCOL]]. + +<p>At a very high level, a user agent negotiates the use of Token Binding with +a server when it sets up a TLS connection to the server. +It sends its highest supported +<dfn export id=concept-token-binding-protocol-version>token-binding protocol version</dfn> +and supported cryptographic algorithms and parameters (the +<dfn export id=concept-token-binding-key-parameters>token-binding key parameters</dfn>) +in a <code>token_binding</code> Client Hello Extension, as described in +<a href="https://tools.ietf.org/html/draft-ietf-tokbind-negotiation#section-2">section 2</a> +of the Token Binding Negotiation spec [[!TOKBIND-NEGOTIATION]]. +The user agent saves the values of the <a for=/>token-binding protocol version</a> and +<a for=/>token-binding key parameters</a> that were negotiated for the +TLS connection in metadata for that connection. + +<p>The user agent uses a `<dfn http-header><code>Sec-Token-Binding</code></dfn>` Perhaps this could be rephrased to draw out the distinction between the connection-level version/parameters, and the request-level metadata? "This connection-level metadata is used to populate a `Sec-Token-Binding` header on each HTTP request using a given connection, which contains a request-specific proof-of-possession for a given origin's token-binding key." Or something? > +<p>In order to protect security tokens like HTTP cookies and OAuth tokens, user agents and servers +can use a technique known as <dfn export id=concept-token-binding>Token Binding</dfn> to +cryptographically associate a given token with a secret +(a <dfn export id=concept-token-binding-key>token-binding key</dfn>) known only to a specific +user agent. This association mitigates the risk that attackers can steal the token and use it +themselves, as they will not be able to easily replicate the user agent's secret, +and therefore will be unable to replicate the cryptographic binding of the token. + +<p>Details are described in TOKBIND-NEGOTIATION, TOKBIND-PROTOCOL and +TOKBIND-HTTPS and integration is defined here. +[[TOKBIND-NEGOTIATION]], [[TOKBIND-PROTOCOL]], and [[TOKBIND-HTTPS]]. + +<p>A <dfn export id=token-binding-id>token binding ID</dfn> is the non-secret representation +of a <a for=/>token-binding key</a>, as described in +<a href="https://tools.ietf.org/html/draft-ietf-tokbind-protocol#section-3.2">section 3.2</a> +of [[TOKBIND-PROTOCOL]]. Is it worth noting that the key is site-specific? (The key is site-specific, right?) > @@ -3237,6 +3566,31 @@ in addition to <a>HTTP fetch</a> above. nullity has already been checked. The <a lt=extract for=BodyInit>extracting</a> operation cannot throw as it was called for the same <a for=body>source</a> before. + <li><p>Let <var>useReferredTokenBinding</var> be the result of + <a for=header>parsing</a> `<a http-header><code>Include-Referred-Token-Binding-ID</code></a>` Nit: "extracting header list values given `Header-Name` and response’s header list." > @@ -3237,6 +3566,31 @@ in addition to <a>HTTP fetch</a> above. nullity has already been checked. The <a lt=extract for=BodyInit>extracting</a> operation cannot throw as it was called for the same <a for=body>source</a> before. + <li><p>Let <var>useReferredTokenBinding</var> be the result of + <a for=header>parsing</a> `<a http-header><code>Include-Referred-Token-Binding-ID</code></a>` + in <var>actualResponse</var>'s <a for=response>header list</a>. + + <li><p>Set the <var>request</var>'s <a for=request>referred-token-binding origin</a> to null. + + <li><p>If <var>useReferredTokenBinding</var> is `<code>true</code>` "extracting header list values" returns a list, which allows you to define the behavior if multiple values are returned. Do we reject the response? Use the first/last value? > @@ -3237,6 +3566,31 @@ in addition to <a>HTTP fetch</a> above. nullity has already been checked. The <a lt=extract for=BodyInit>extracting</a> operation cannot throw as it was called for the same <a for=body>source</a> before. + <li><p>Let <var>useReferredTokenBinding</var> be the result of + <a for=header>parsing</a> `<a http-header><code>Include-Referred-Token-Binding-ID</code></a>` + in <var>actualResponse</var>'s <a for=response>header list</a>. + + <li><p>Set the <var>request</var>'s <a for=request>referred-token-binding origin</a> to null. + + <li><p>If <var>useReferredTokenBinding</var> is `<code>true</code>` + and the <var>request</var>'s <a for=request>use-token-binding flag</a> is set, + then set the <var>request</var>'s <a for=request>referred-token-binding origin</a> to + <var>request</var>'s <a for=request>origin</a>. I'm not sure this works the way you want it to; perhaps the origin of the request's current URL? Need to trace this down, as the redirect behavior for the requests' origin is complicated. > @@ -3237,6 +3566,31 @@ in addition to <a>HTTP fetch</a> above. nullity has already been checked. The <a lt=extract for=BodyInit>extracting</a> operation cannot throw as it was called for the same <a for=body>source</a> before. + <li><p>Let <var>useReferredTokenBinding</var> be the result of + <a for=header>parsing</a> `<a http-header><code>Include-Referred-Token-Binding-ID</code></a>` + in <var>actualResponse</var>'s <a for=response>header list</a>. + + <li><p>Set the <var>request</var>'s <a for=request>referred-token-binding origin</a> to null. + + <li><p>If <var>useReferredTokenBinding</var> is `<code>true</code>` + and the <var>request</var>'s <a for=request>use-token-binding flag</a> is set, + then set the <var>request</var>'s <a for=request>referred-token-binding origin</a> to + <var>request</var>'s <a for=request>origin</a>. Also: how does this work with `sandbox`? Or, worse, `Content-Security-Policy: sandbox`? We don't yet have a document when processing this header so the current spec text won't modify the relevant origin. Is that reasonable? > +The <a for=/>token-binding key store</a> is typically maintained alongside +the user agent's cookie store. + +<h4 id=getting-token-binding-key>Getting a Token Binding Key</h4> + +<p><dfn abstract-op export id=concept-get-token-binding-key>Get the token-binding key</dfn> +for an <a for=/>origin</a> <var>tokenBindingOrigin</var> and +<a for=/>token-binding key parameters</a> <var>tokenBindingKeyParameters</var>, +using the user agent's <a for=/>token-binding key store</a>, +by running these substeps: + +<ol> + <li><p>Let <var>keyDomainName</var> be null. + + <li><p>If <var>tokenBindingOrigin</var>'s <a for=origin>host</a> is an <a>IPv4 address</a> or an <a>IPv6 address</a>, + set <var>keyDomainName</var> to <var>tokenBindingOrigin</var>'s <a for=origin>host</a>. Do we actually need to support IP addresses? Or could we punt on them, preferring hostnames instead? > + +<h4 id=federated-token-binding>Federated Token Binding</h4> + +<p>In the scenario described above, servers bind tokens to be used by user agents +with those servers. +To enable existing web authorization protocols to use bound credentials, +there is a need to support scenarios where bound credentials issued by one server +(e.g., an identity provider) are presented by the user agent to a different server +(e.g., a relying party). +[[TOKBIND-PROTOCOL]] and [[TOKBIND-HTTPS]] describe support for Federated Token Binding. + +<p>A <dfn export id=referred-token-binding-id>referred-token-binding ID</dfn> is the +<a for=/>token binding ID</a> for a server other than the server to which the +<a for=/>request</a> is being sent. + +Script code from an <a for=/>origin</a> can set a <a for=/>request</a>'s It would be helpful to point to the script you're talking about here. Either via an example, or at least a pointer to the requestinit property. > + + <li><p><a for=/>token-binding protocol version</a> in <var>tlsConnection</var>'s + <a for=connection>TLS connection metadata</a> is null. + </ol> + + <li><p>Let <var>providedTokenBindingKeyPair</var> be the result of + <a abstract-op lt="Get the token-binding key">getting the token-binding key</a> + for the <a for=/>origin</a> of <var>httpRequest</var>'s <a for=request>current url</a> + and the <a for=/>token-binding key parameters</a> in <var>tlsConnection</var>'s + <a for=connection>TLS connection metadata</a>. + + <li><p>Let <var>providedTokenBindingId</var> be the result of computing a + <a for=/>token binding ID</a> from <var>providedTokenBindingKeyPair</var>, + as described in + <a href="https://tools.ietf.org/html/draft-ietf-tokbind-protocol#section-3.2">section 3.2</a> + of [[!TOKBIND-PROTOCOL]]. As discussed in person, this reference doesn't clearly describe to me what I need to be doing to compute the token binding ID from the key pair I have access to here. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/whatwg/fetch/pull/325#pullrequestreview-98842249
Received on Monday, 5 March 2018 22:54:38 UTC