Subject: Re: [Unbearable] Referred token binding IDs

From: =JeffH <[email-masked]>
Date: Sun, 20 Mar 2016 18:17:15 -0700

>> On 3/7/16, 4:24 PM [email-masked]> wrote:
>>>
>>> If a client receives an "Include-Referer-Token-Binding-ID" header in
>>> response to a request that already had a referred TBID in the
>>> TokenBindingMessage, should it include both of those TBIDs as referred
>>> TBIDs in the next request?
>>>
>>> I.e.
>>> - client sends request to server A w/ provided TBID A
>>> - gets back Include-Referer-Token-Binding-ID header on a redirect to B
>>> - client sends request to B w/ provided TBID B, referred TBID A
>>> - gets back Include-Referer-Token-Binding-ID header on a redirect to C
>>> Possible behaviors:
>>> i) client sends request to C w/ provided TBID C, referred TBID B,
>>> referred TBID A
>>> ii) client sends request to C w/ provided TBID C, referred TBID B
>>>
>>> iii) client sends request to C w/ provided TBID C, referred TBID A,
>>> referred TBID B

On Fri, 11 Mar 2016 Dirk replied:
> The intended semantics in the current spec is  ii).

what you mean that is that the TokenBindingMessage (TBMSG) contains only two 
TokenBindings in this case, and the TBMSG is included in an HTTP request 
from the client to server only when satisfying a redirect that is crossing 
"functional boundaries" as noted below, yes?

[ "current spec" discussed herein = -tokbind-https-02 aka HTTPSTB,
   other specs..
                  -tokbind-negotiation-02 aka TBNEGO
                  -tokbind-protocol-04 aka TBPROTO ]

On Fri, 11 Mar 2016 Dirk further replied:
> I believe that covers all the use cases that you're describing: Let's first
> consider the case where there is one Relying Party, and one Identity
> Provider. The RP might go through a bunch of redirects before ultimately
> handing things off to the IdP, and the IdP might go through a bunch of
> redirects before ultimately handling the RP request. Same on the way back
> from the IdP to the RP.

understood.

> The one redirect where the referred token binding is necessary is the
> redirect that crosses functional boundaries: from the RP to the IdP.

agreed.

> If the
> first endpoint at the IdP isn't the one that is processing the RP request
> (because, say, it's the old one and it's now redirecting to the new one),
> that endpoint needs to encode the information it learns (i.e., what is the
> public key that the client is using with the RP) in some way (which can be
> proprietary to the IdP) and pass that along as the request is handed off.

agreed that the above works in the case where the Token Consumer (RP) that 
redirects to IdP1 is the intended recipient of the eventual token-bound ID 
token.

However, federation protocols have a notion of a 'return address' that's 
typically included in the RP's 'authn request'. E.g., in OIDC it is the 
"redirect_uri" [1], and in SAML the equivalent is the 
"AssertionConsumerServiceURL" [2].

Upon issuance of the security token, the IDP redirects the UA to the 
specified 'return address', which does not necessarily point to the RP 
entity that redirected the UA to the IDP, nor even any of the entities in 
the RP's "redirect chain".

So there needs to be some means for the IDP to receive the _correct_ 
referred TBID to include in the security token it generates and then returns 
-- this is not necessarily the RP entity that redirected to the IDP. A few 
ways to address this in HTTPSTB perhaps are..

We could mandate in HTTPSTB that the receiving RP entity (aka Token 
Consumer) MUST have the same eTLD+1 as the RP entity that redirected (aka 
"handed off") to the IDP. (see below for discussion of TB scoping rules)

Or, we could attempt to devise a means for the RP entities to signal the 
correct referred TBID to the IDP via HTTPSTB/TBPROTO.

Or, we could punt the problem to deployers and say something like "the 
referred TBID in the TBMSG MUST map to the entity specified in the authn 
request's return address -- i.e., the TBID included in the issued security 
token by the IDP needs to match the client's TLS connection with the entity 
who will _receive_ the security token, even if the latter entity is not the 
one to redirect to the IDP" -- it is implementers' and deployers' 
responsibility to get this right.

See [figure 1] at end below.

> On the way back, after the IdP redirects back to the RP, the RP just needs
> to make sure that one of the endpoints in the redirect chain is on the same
> eTLD+1 as the endpoint that did the hand-off to the IdP, so it can process
> the IdP response there.

hm, perhaps there are some issues here..

* with regards to processing the IDP response ... is the above-stated eTLD+1 
requirement because the client aka user agent (UA) will use the same 
provided TBID with servers whose hostnames map to the same eTLD+1 ? 
-tokbind-protocol aka TBPROTO says..

    ... In order to prevent cooperating servers from linking user
    identities, different keys SHOULD be used by the client for
    connections to different servers, according to the token scoping
    rules of the application protocol.

..so it seems we are assuming (in HTTPSTB) that HTTPS clients map the 
servers to eTLD+1 when generating their TB key pairs, and afix Token-Binding 
header fields to their HTTP msgs per said mapping, yes?

some thoughts/issues..

  - eTLD and eTLD+1 are not mentioned in HTTPSTB

  - HTTPSTB does not explicitly define which particular "token scoping
    rules" impls must adhere to. Is the client-side TBID storage-and-mapping
    model intended to map only to domain names, and in this case be "domain
    lowered" to eTLD+1 (modulo publicsuffix.org) similarly to how cookies'
    domain-matching works? [3][4]

  - what about servers that are identified by IP address? Note that in HSTS
    we punted on supporting servers identified by IP addresses [5]. Tho, in
    RFC6265 a server addressed by IP address can set cookies, but only for
    itself (i.e., the host-only flag is set to true [6]; i.e., cookie
    "domain lowering" is undefined for IP addresses). Is
    allowing/disallowing a host-only IP address-based TBID mapping
    something  we should consider generally for TBPROTO, or
    just specifically consider for HTTSTB?

> Next, let's consider what happens if there are multiple IdP's involved, say
> something like rp.com -> identity-as-a-service.com -> idp.com. In that
> case, identity-as-a-service.com acts like an IdP to rp.com, and as an RP to
> idp.com, so we play the game described above twice. It wouldn't make sense
> here if idp.com somehow knew what public key the client is using with rp.com
> - it's useless information. In a scenario like this, idp.com needs to
> strongly authenticate the client to identity-as-a-service.com, not to rp.com

Agreed, in this particular, tightly-constrained scenario.

HTH,

=JeffH

[1] https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest

[2] https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf

[3] https://tools.ietf.org/html/rfc6265#section-5.1.3

[4] http://identitymeme.org/http-cookie-processing-algorithm-etlds/

[5] https://tools.ietf.org/html/rfc6797#appendix-A

[6] https://tools.ietf.org/html/rfc6265#section-5.3 - step 6.

[figure 1]

What: Analysis of redirect hops at RP aka TC and at IDP aka TP

Legend:

   EKM:       TLS Exported Keying Material [RFC5705]

   {EKMn}Ksm: EKM for server "n", signed by private key of TBID "m",
              where "n" must represent server receiving the ETBMSG,
              if a conveyed TB's type is provided_token_binding, then
              m = n, else if TB's type is referred_token_binding, then
              m != n. E.g., see step 1b in diagram below.

   ETBMSG:    "Token-Binding" HTTP header field conveying an
              EncodedTokenBindingMessage, in turn conveying
              TokenBinding (TB)struct(s), e.g.:
              ETBMSG[[TB]] or ETBMSG[[TB1],[TB2]]

   ID Token:  the "ID Token" in OIDC, it is the semantic equivalent
              of a SAML "authentication assertion". "ID Token w/TBIDn"
              denotes a "token bound" ID Token containing TBIDn.
   	
   Ks & Kp:   private (aka secret) key, and public key, respectively,
              of client-side Token Binding key pair
	
   OIDC:      Open ID Connect

   TB:        TokenBinding struct containing signed EKM, TBID, and
              TB type, e.g.: [{EKM1}Ks1,TBID1,provided_token_binding]
	
   TBIDn:     Token Binding ID for client and server n's token-bound
              TLS association. TBIDn contains Kpn.

                                Token Consumer,        Token Provider,
                                aka:                   aka:
                                OpenID Client,         OpenID Provider,
Client,                        OIDC Relying Party,    OIDC Provider,
aka:                           SAML Relying Party     SAML Identity Provider
User Agent                     [ servers "1", "2" ]   [ servers "3", "4" ]
+--------+                       +-----+  +-----+     +-----+   +-----+
| Client |                       | TC1 |  | TC2 |     | TP3 |   | TP4 |
+--------+                       +-----+  +-----+     +-----+   +-----+
     |                               |        |           |         |
     |                               |        |           |         |
     | 0. Client interacts w/TC1                          |         |
     | over HTTPS, establishes Ks1 & Kp1, TBID1           |         |
     | ETBMSG[[{EKM1}Ks1,TBID1,provided_token_binding]]   |         |
     |------------------------------>|        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |
     | 1a. redirect to TC2 for TC-specific reasons        |         |
     | any security-relevant cookies should contain TBID1 |         |
   +<- - - - - - - - - - - - - - - - |        |           |         |
   . |                               |        |           |         |
   +----------------------------------------->|           |         |
     | 1b. establishes Ks2 & Kp2, TBID2       |           |         |
     | ETBMSG[[{EKM2}Ks2,TBID2,provided_token_binding]]   |         |
     |                               |        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |
     | 2a. OIDC ID Token request,    |        |           |         |
     | aka "Authentication Request" w/ redirect_uri=TC1;  <-- note well
     | conveyed w/ HTTP response header field of:
     |   Include-Referer-Token-Binding-ID:true            |         |
     | any security-relevant cookies should contain TBID2 |         |
   +<- - - - - - - - - - - - - - - - - - - - -|           |         |
   . | (redirect to TP via 301, 302, |        |           |         |
   . |  303, 307, or 308)            |        |           |         |
   . |                               |        |           |         |
   +----------------------------------------------------->|         |
     | 2b. client opens HTTPS w/ TP3,         |           |         |
     | establishes Ks3, Kp3, TBID3;           |           |         |
     | sends GET or POST with                 |           |         |
     | ID Token request w/ redirect_uri=TC1,  |           |         |
     | ETBMSG[[{EKM3}Ks3,TBID3,provided_token_binding],             |
     |       [{EKM3}Ks2,TBID2,referred_token_binding]] <-- but ID Tok request
     |                               |        |        <-- is for TC1
     |                               |        |
     |                               |        |           |         |
     |                               |        |           |         |
     | 3a. redirect to TP4 for TP-specific reasons        |         |
     | any security-relevant cookies should contain TBID3 |         |
   +<- - - - - - - - - - - - - - - - - - - - - - - - - - -|         |
   . |                               |        |           |         |
   +--------------------------------------------------------------->|
     | 3b. client opens HTTPS w/ TP4,         |           |         |
     | establishes Ks4 & Kp4, TBID4           |           |         |
     | ETBMSG[[{EKM4}Ks4,TBID4,provided_token_binding]]   |         |
     |         *** as well as the ID Token request w/ redirect_uri=TC1;
     |         *** also, somehow conveys TBID2 to TP4 ?
     |                               |        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |
     | 4. user authentication (if applicable,             |         |
     |    methods vary, particulars are out of scope)     |         |
     |<============================================================>|
     | (TP generates ID Token for TC1 containing TBID1 - TP4 has only TBID2
     |  also set cookie(s) containing TBID4 and/or TBID3
     |  details vary)                |        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |
     | 5a. ID Token issued for TC1, containing TBID1, <-- how do this if
     |    conveyed via OIDC "Authentication Response" <-- don't have TBID1?
   +<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
   . |   (redirect to TC1)           |        |           |         |
   . |                               |        |           |         |
   +-------------------------------->|        |           |         |
     | 5b. HTTPS GET or POST with    |        |           |         |
     | ETBMSG[[{EKM1}Ks1,TBID1,provided_token_binding]]   |         |
     | conveying Authn Reponse containing ID Token w/TBID1,         |
     |                                    issued for TC1            |
     |                               |        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |
     | 6. user is signed-on, any security-relevant cookie(s)        |
     | that are set SHOULD contain TBID1      |           |         |
     |<------------------------------|        |           |         |
     |                               |        |           |         |
     |                               |        |           |         |

end

---

From: Dirk Balfanz <[email-masked]>
Date: Mon, 21 Mar 2016 06:03:59 +0000

>     domain-matching works? [3][4]

Just added language to that effect in a new "Privacy Considerations"
section in -03. Take a look and see whether you like it / have some ideas
to improve on it.

>     just specifically consider for HTTSTB?

I'd say that servers identified by IP addresses will get keys scoped to
that exact IP address - just like cookies. I think it belongs in HTTPSTB as
a SHOULD for web browsers.

Dirk.

---

From: Nick Harper <[email-masked]>
Date: Mon, 21 Mar 2016 13:40:57 -0700

My understanding of the problem in figure 1 is that 1) in the redirect from
TC2 to TP3, the referred TBID is is TBID2, while the redirect uri is to
TC1, and 2) when TP3 redirects to TP4, somehow TBID2 needs to be relayed.
Please correct me if that is wrong or incomplete.

One way to solve problem 2 is to treat the TP3->TP4 redirect like the
"identity-as-a-service" scenario that Dirk mentioned. Instead of TP4
redirecting to TC1, it can create a token to be consumed by TP3, and
redirect to TP3, which will then create a token to send back to TC1.

For problem 1, I am going to assume that TC1 and TC2 are cooperating. The
easiest way to fix this is to have TC2 transmit to TC1 out-of-band what
TBID2 is so that TC1 can verify it.

Here's another solution (for both problems) that I think could work (credit
to David Benjamin for initially proposing it). I'm going to use OpenID
Connect terminology here, but I imagine this could be adapted for other
federated protocols. When the clients makes the OIDC authentication
request, it includes the TBID in the nonce query param. Regardless of what
happens in terms of redirects from TP3->TP4 (or anything else), the token
that the client sends back to the token consumer will have the TBID in the
nonce claim. For the case of TC1 redirects to TC2 which then does the
redirect for the authentication request, TC1 can pass the TBID to TC2 in a
query param.

By moving the referred Token Binding ID from the tbproto (and tbhttps) to
the federation protocol, it simplifies the setup and implementation of
both. User-agents no longer have to handle the
Include-Referer-Token-Binding-ID header; identity providers don't have to
do anything additional with creating a new claim and plumbing the TBID from
the Sec-Token-Binding header into the new claim; the token consumer doesn't
have to worry about whether the token provider supports token binding (or
the same key params), as it will always get back a bound token.

The only downside I see (so far) to this approach is that the token
provider has no way to verify that the client has possession of the private
key for the referred Token Binding ID. What security benefits are provided
by the token provider verifying proof of possession? As far as I could
tell, it could open up a token injection attack, but that would be thwarted
by the federation protocol's CSRF protection.

On Sun, Mar 20, 2016 at 11:03 PM, Dirk Balfanz <[email-masked]> wrote:

> _______________________________________________
> Unbearable mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/unbearable
>
>

---

From: Nick Harper <[email-masked]>
Date: Thu, 24 Mar 2016 15:15:49 -0700

TL;DR: Use Include-Referer-Token-Binding-ID. Binding a token to an ID that
hasn't been verified can result in a MitM getting control of a bound token.

Dirk and I chatted about my/David's proposal, and how it applies to Jeff's
scenario. In steps 3a and 3b from figure 1, TBID3 needs to be referred to
TP4 (in addition to conveying TBID2). The problem with the current setup of
figure 1 is when there is an attacker MitMing connections to TP3. In step
2b, the TokenBindingMessage contains TBID3' and TBID2', both under attacker
control. Then, in step 3b, when the client follows the redirect from (the
MitM'd) TP3 to TP4, it includes TBID4, but not TBID3, in the
TokenBindingMessage. When TP4 authenticates the user, TBID4 is correct, and
then TP4 creates a token for the user's identity with an
attacker-controlled TBID. Even if TP3 and TP4 are somehow cooperating, and
the provided and referred token bindings from the request in step 2b are
passed from TP3 to TP4 out-of-band, the token still has an attacker
controlled TBID, since the token bindings sent in step 2b are attacker
controlled.

I think the takeaway from this is when a federated token is created and
bound to a referred TBID, the provided TBID (that the user's identity is
bound to) and the referred TBID must both be verified as being possessed by
the *same* client. The easiest way to do this is to have the provided TBID
and the referred TBID in the same TokenBindingMessage.

On Mon, Mar 21, 2016 at 1:40 PM, Nick Harper <[email-masked]> wrote:

> My understanding of the problem in figure 1 is that 1) in the redirect
> from TC2 to TP3, the referred TBID is is TBID2, while the redirect uri is
> to TC1, and 2) when TP3 redirects to TP4, somehow TBID2 needs to be
> relayed. Please correct me if that is wrong or incomplete.
>
> Here's another solution (for both problems) that I think could work
> (credit to David Benjamin for initially proposing it). I'm going to use
> OpenID Connect terminology here, but I imagine this could be adapted for
> other federated protocols. When the clients makes the OIDC authentication

---

From: Dirk Balfanz <[email-masked]>
Date: Fri, 25 Mar 2016 17:49:44 +0000

Agreed. Bottom line is that I still believe that a single referred token
binding (even on repeated redirects) gives us all we need. Having said
that, it probably is a good idea to document best practices (as Nick has
done here) to make sure IdPs and RPs don't shoot themselves in the foot.
For example, when I first responded (on the other thread) and explained why
I think that a single referred token binding is enough, I didn't realize
that you have to redirect with Include-Referer-Token-Binding-ID *twice*,
from RP to IdP, and also within the IdP (as Nick explains here).

Dirk.