The postKey APIThe postKey API could be defined like this (the similarities to postMessage are not accidental):
- otherWindow.postKey(message, targetOrigin)
otherWindow A reference to another window; such a reference may be obtained, for example, using the contentWindow property of an iframe element, the object returned by window.open, or by named or numeric index on window.frames.
message Optional string data to be sent to the other window. This string will be available to the recipient of the message in the data property of the event posted to the recipient.
targetOrigin Specifies what the origin of otherWindow must be for the event to be dispatched. If at the time the event is scheduled to be dispatched the scheme, hostname, or port of otherWindow's document does not match that provided in targetOrigin, the event will not be dispatched; only if all three match will the event be dispatched.
postKey() works like postMessage(), except that the event sent to the receiving message handler also includes properties called cert
(in addition to origin
). Both contain base64-encoded X.509 cerificates. The cert certificate has the sender’s origin as the subject CN, the sender’s origin Token Binding public key
as the certified key, the receiver’s origin as the issuer CN, and is signed by the receiver’s origin Token Binding key
. The crossCert has the roles of subject and issuer reversed (i.e., it contains the receiver’s key, signed by the sender’s key).
Both certificates include an extension (OID TBD) whose value will be the same random number, thus marking the certificates as originating from the same postKey call. Both certificates expire at the same time, which the lesser of the expiration times of the two origin-bound keys
Unlike postMessage, wildcard targetOrigins are not allowed.
Note that the caller does not get to pick the certified keys, rather the browser automatically picks the origin-bound key for the caller and receiver.
The goal of the postKey() message is to get the caller’s public key to the targetOrigin in a way that is resistant to a man-in-the-middle (MITM) between the browser and the targetOrigin. The browser must be communicating with the targetOrigin using an HTTPS channel authenticated with the Token Binding key
used for that origin. At the same time, the caller’s public key will cross-certify the receiver’s public key to prove that both keys belong to the same browser.
Example: Logging into a Relying PartyWe assume that the user is already logged into the Identity Provider (IdP), i.e., that the IdP has reliably associated one of the browser’s Token Binding keys (let’s say Ki) with a user identity (let’s say U). The goal is for the Relying Party (RP) to associate the same user identity U with the origin-bound key the browser uses with RP (let’s say Kr). The user goes to rp.com, which iframes the IdP (idp.com). The protocol is depicted below:
Note a few properties of the above flow:
- The outer frame (to rp.com) uses postKey() to send the cross-certs to the IdP frame. The handler receiving the postKey message on idp.com receives two certificates in which Ki and Kr cross-certify each other.
- The iframe on idp.com sends the cross-certification certs to its server. Since the certs are sent over a channel authenticated with Ki, the server associates the incoming request with user U. Because of the mutual certification contained in the request, it also associates Kr with user U. It extracts the name of the RP (rp.com) from one of the certificates and...
- ...responds with a one-time-use identity assertion that certifies that key Kr belongs to user U, and that user U has demonstrated consent to be logged into rp.com. (idp.com optionally obtains consent from the user before Step 3, which is not depicted above).
- The idp.com iframe passes the identity assertion up to the calling frame (on rp.com).
- The rp.com frame sends the identity assertion to its server (rp.com) which checks that it is sent over a channel authenticated by Kr, hasn’t been used yet, has been properly signed by the IdP, and is intended for its own origin (rp.com). If this is all ok, it associates user U with key Kr (usually by setting a cookie).
- The RP never learns the user’s identifier (Ki) at the IdP (privacy protection).
- Leaking any of the public keys (Ki, Kr, etc.) would not pose a security risk - identity assertions can only be used over channels authenticated by their corresponding private keys.
- Leaking the mapping from Kr to identity U would not pose a security risk, since one needs access to the corresponding private key to invoke the identity U at the RP.
- Leaking the mapping from Kr to identity U would, however, pose a privacy risk - the RP would be able to identify the user. That’s why the IdP only releases this mapping (in form of the auth token) after the user consents to be identified to the RP.