One document matched: draft-rescorla-rtcweb-generic-idp-01.xml
<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY RFC2119 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC3552 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3552.xml">
<!ENTITY RFC2818 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2818.xml">
<!ENTITY RFC3261 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3261.xml">
<!ENTITY RFC5479 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5479.xml">
<!ENTITY RFC4347 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4347.xml">
<!ENTITY RFC4568 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4568.xml">
<!ENTITY RFC5763 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5763.xml">
<!ENTITY RFC4251 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4251.xml">
<!ENTITY RFC3760 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3760.xml">
<!ENTITY RFC6189 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6189.xml">
<!ENTITY RFC5245 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5245.xml">
<!ENTITY RFC6454 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6454.xml">
<!ENTITY RFC4627 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4627.xml">
<!ENTITY I-D.ietf-rtcweb-security-arch SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-rtcweb-security-arch">
<!ENTITY I-D.ietf-hybi-thewebsocketprotocol SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-hybi-thewebsocketprotocol">
<!ENTITY I-D.kaufman-rtcweb-security-ui SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.kaufman-rtcweb-security-ui">
<!ENTITY I-D.ietf-rtcweb-security SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-rtcweb-security">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<?rfc toc="yes" ?>
<?rfc symrefs="yes" ?>
<?rfc strict="yes" ?>
<?rfc compact="yes" ?>
<?rfc sortrefs="yes" ?>
<?rfc colonspace="yes" ?>
<?rfc rfcedstyle="no" ?>
<!-- Don't change this. It breaks stuff -->
<?rfc tocdepth="4"?>
<rfc category="std" docName="draft-rescorla-rtcweb-generic-idp-01"
ipr="pre5378Trust200902">
<front>
<title abbrev="RTCWEB IdP">RTCWEB Generic Identity Provider Interface</title>
<author fullname="Eric Rescorla" initials="E.K." surname="Rescorla">
<organization>RTFM, Inc.</organization>
<address>
<postal>
<street>2064 Edgewood Drive</street>
<city>Palo Alto</city>
<region>CA</region>
<code>94303</code>
<country>USA</country>
</postal>
<phone>+1 650 678 2350</phone>
<email>ekr@rtfm.com</email>
</address>
</author>
<date day="12" month="March" year="2012" />
<area>RAI</area>
<workgroup>RTCWEB</workgroup>
<abstract>
<t>
Security for RTCWEB communications requires that the
communicating endpoints be able to authenticate each
other. While authentication may be mediated by the
calling service, there are settings in which this is
undesirable. This document describes a generic mechanism
for leveraging existing identity providers
(IdPs) such as BrowserID or OAuth to provide this
authentication service.
</t>
</abstract>
<note title="Legal">
<t>THIS DOCUMENT AND THE INFORMATION CONTAINED THEREIN ARE PROVIDED ON
AN “AS IS” BASIS AND THE CONTRIBUTOR, THE ORGANIZATION
HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE
IETF TRUST, AND THE INTERNET ENGINEERING TASK FORCE, DISCLAIM ALL
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY
WARRANTY THAT THE USE OF THE INFORMATION THEREIN WILL NOT INFRINGE ANY
RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
PARTICULAR PURPOSE.</t>
</note>
</front>
<middle>
<section title="Introduction" anchor="sec.introduction">
<t>
Security for RTCWEB communications requires that the
communicating endpoints be able to authenticate each other. While
authentication may be mediated by the calling service, there are
settings in which this is undesirable. This document describes a
mechanism for leveraging existing identity providers (IdPs) such as
BrowserID or OAuth to provide this authentication service.
</t>
<t>
Specifically, Alice and Bob have relationships with some
Identity Provider (IdP) that supports a protocol such OpenID or
BrowserID) that can be used to attest to their identity. While
they are making calls through the signaling service, their
identities (and the cryptographic keying material used to make
the call) is authenticated via the IdP.
This separation isn't particularly important in "closed world"
cases where Alice and Bob are users on the same social network, have
identities based on that network, and are calling using that
network's signaling service. However, there are important
settings where that is not the case, such as
federation (calls from one network to another) and
calling on untrusted sites, such as where two users who have
a relationship via a given social network want to call each
other on another, untrusted, site, such as a poker site.
</t>
<figure title="A call with IdP-based identity" anchor="fig.proposal.idp">
<artwork><![CDATA[
+----------------+
| |
| Signaling |
| Server |
| |
+----------------+
^ ^
/ \
HTTPS / \ HTTPS
/ \
/ \
v v
JS API JS API
+-----------+ +-----------+
| | Media | |
Alice | Browser |<---------->| Browser | Bob
| | (DTLS-SRTP)| |
+-----------+ +-----------+
^ ^--+ +--^ ^
| | | |
v | | v
+-----------+ | | +-----------+
| |<--------+ | |
| IdP A | | | IdP B |
| | +------->| |
+-----------+ +-----------+
]]></artwork>
</figure>
<t>
<xref target="fig.proposal.idp"/> shows the basic topology. Alice
and Bob are on the same signaling server, but they additionally
have relationships with their own IdPs. Alice has registered with
IdP A and Bob has registered with IdP B. Note that nothing
stops these IdPs from being the same, or indeed from being
the same as the signaling server, but they can also be totally
distinct. In particular, Alice and Bob need not have
identities from the same IdP.
</t>
<t>
Starting from this point, the mechanisms described in this
document allow Alice and Bob to establish a mutually authenticated
phone call. In the interest of clarity the remainder of
this section provides a brief overview of how these mechanisms
fit into the bigger RTCWEB calling picture. For a detailed description of the relevant protocol elements
and their interaction with the larger signaling protocol
see <xref target="I-D.ietf-rtcweb-security"/>.
When Alice goes to call Bob, her browser (specifically
her PeerConnection object) contacts her IdP on her behalf and
obtains an assertion of her identity bound to her certificate
fingerprint. This assertion is carried with her signaling
messages to the signaling server and then down to Bob.
Bob's browser verifies the assertion, possibly with the
cooperation of the IdP, and can then display Alice's
identity to Bob in a trusted user interface element.
If Alice is in Bob's address book,
then this interface might also include her real name, a picture, etc.
</t>
<t>
When/If Bob agrees to answer the call, his browser contacts his
IdP and gets a similar assertion. This assertion is sent to
the signaling server as part of Bob's answer which is then
forwarded to Alice. Alice's browser verifies
Bob's identity and can display the result in a trusted
UI element. At this point Alice and Bob know each other's
fingerprints and so they can transitively verify the
keys used to authenticate the DTLS-SRTP handshake and
hence the security of the media.
</t>
<t>
The mechanisms in this
document do not require the browser to implement any
particular identity protocol or to support any particular
IdP. Instead, this document provides a generic interface
which any IdP can implement. Thus, new IdPs and protocols
can be introduced without change to either the browser or the
calling service. This avoids the need to make a commitment
to any particular identity protocol, although browsers
may opt to directly implement some identity protocols in
order to provide superior performance or UI properties.
</t>
</section>
<section anchor="sec-term" title="Terminology">
<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in <xref
target="RFC2119">RFC 2119</xref>.</t>
</section>
<section title="Trust Relationships: IdPs, APs, and RPs" anchor="sec.trust-relationships">
<t>
Any authentication protocol has three major participants:
</t>
<t>
<list style="hanging">
<t hangText="Authenticating Party (AP):">The entity which is
trying to establish its identity.</t>
<t></t>
<t hangText="Identity Provider (IdP):">The entity which is
vouching for the AP's identity.</t>
<t></t>
<t hangText="Relying Party (RP):">The entity which is trying
to verify the AP's identity.</t>
</list>
</t>
<t>
The AP and the IdP have an account relationship of some kind: the
AP registers with the IdP and is able to subsequently authenticate
directly to the IdP (e.g., with a password). This means that the
browser must somehow know which IdP(s) the user has
an account relationship with.
This can either be something that the user configures into
the browser or that is configured at the calling site and
then provided to the PeerConnection by the calling site.
</t>
<t>
At a high level there are two kinds of IdPs:
</t>
<t>
<list style="hanging">
<t hangText="Authoritative: ">IdPs which have verifiable control
of some section of the identity space. For instance, in the
realm of e-mail, the operator of "example.com" has complete control of the
namespace ending in "@example.com". Thus, "alice@example.com"
is whoever the operator says it is. Examples of systems with
authoritative identity providers include DNSSEC,
RFC 4474, and Facebook Connect (Facebook identities only
make sense within the context of the Facebook system).
</t>
<t></t>
<t hangText="Third-Party: ">IdPs which don't have control of
their section of the identity space but instead verify
user's identities via some unspecified mechanism and then
attest to it. Because the IdP doesn't actually control
the namespace, RPs need to trust that the
IdP is correctly verifying AP identities, and there
can potentially be multiple IdPs attesting to the same
section of the identity space. Probably the best-known example
of a third-party identity provider is SSL certificates,
where there are a large number of CAs all of whom can
attest to any domain name.
</t>
</list>
</t>
<t>
If an AP is authenticating via an authoritative IdP, then
the RP does not need to explicitly trust the IdP at all:
as long as the RP knows how to verify that the IdP
indeed made the relevant identity assertion (a function
provided by the mechanisms in this document), then
any assertion it makes about an identity for which
it is authoritative is directly verifiable.
</t>
<t>
By contrast, if an AP is authenticating via a third-party
IdP, the RP needs to explicitly trust that IdP
(hence the need for an explicit trust anchor list
in PKI-based SSL/TLS clients). The list of trustable
IdPs needs to be configured directly into the
browser, either by the user or potentially by the
browser manufacturer. This is a significant advantage
of authoritative IdPs and implies that if third-party
IdPs are to be supported, the potential number needs
to be fairly small.
</t>
</section>
<section title="Overview of Operation" anchor="sec.overview">
<t>
In order to provide security without trusting the calling
site, the PeerConnection component of the browser must
interact directly with the IdP. In this section, we
describe a standalone mechanism based on IFRAMEs
and postMessage(), however, most likely this will
eventually be superceded by WebIntents
<eref target="http://www.webintents.com/"/>.
[[
OPEN ISSUE:
I've been looking at WebIntents and I believe that it
can be made to work but may require some modifications.
I am currently studying the problem.
More analysis to come.]]
]].
</t>
<figure>
<artwork><![CDATA[
+------------------------------------+
| https://calling-site.example.com |
| |
| |
| |
| Calling JS Code |
| ^ |
| | API Calls |
| v |
| PeerConnection |
| ^ |
| | postMessage() |
| v |
| +-------------------------+ | +---------------+
| | https://idp.example.org | | | |
| | |<--------->| Identity |
| | IdP JS | | | Provider |
| | | | | |
| +-------------------------+ | +---------------+
| |
+------------------------------------+
]]></artwork>
</figure>
<t>
When the PeerConnection object wants to interact with the
IdP, the sequence of events is as follows:
</t>
<t>
<list style="numbers">
<t>The browser (the PeerConnection component)
instantiates an IdP proxy (typically a hidden
IFRAME) with its source at the IdP. This allows the
IdP to load whatever JS is necessary into the
proxy, which runs in the IdP's security context.</t>
<t>If the user is not already logged in, the
IdP does whatever is required to log them in,
such as soliciting a username and password.</t>
<t>Once the user is logged in, the IdP proxy
notifies the browser (via postMessage()) that
it is ready.</t>
<t>The browser and the IdP proxy communicate
via a standardized series of messages
delivered via postMessage. For instance,
the browser might request the IdP proxy to
sign or verify a given identity assertion.</t>
</list>
</t>
<t>
This approach allows us to decouple the browser from
any particular identity provider; the browser need
only know how to load the IdP's JavaScript--which
is deterministic from the IdP's identity--and
the generic protocol for requesting and verifying
assertions. The IdP provides whatever logic
is necessary to bridge the generic protocol to
the IdP's specific requirements. Thus, a single
browser can support any number of identity protocols,
including being forward compatible with IdPs which
did not exist at the time the browser was written.
</t>
</section>
<section title="Protocol Details" anchor="sec.protocol-details">
<section title="General Message Structure">
<t>
Messages between the PeerConnection object and the
IdP proxy are formatted using JSON <xref target="RFC4627"/>.
For instance, the PeerConnection would request a
signature with the following "SIGN" message:
</t>
<figure>
<artwork><![CDATA[
{
"type":"SIGN",
"id": "1",
"message":"012345678abcdefghijkl"
}
]]></artwork>
</figure>
<t>
All messages MUST contain a "type" field which indicates
the general meaning of the message.
</t>
<t>
All requests from the PeerConnection object MUST contain
an "id" field which MUST be unique for that PeerConnection
object. Any responses from the IdP proxy MUST contain
the same id in response, which allows the PeerConnection
to correlate requests and responses.
</t>
<t>
Any message-specific data is carried in a "message"
field. Depending on the message type, this may
either be a string or a richer JSON object.
</t>
<section title="Errors">
<t>
If an error occurs, the IdP sends a message of
type "ERROR". The message MAY have an
"error" field containing freeform
text data which containing additional
information about what happened. For instance:
</t>
<figure title="Example error" anchor="fig.example-error">
<artwork><![CDATA[
{
"type":"ERROR",
"error":"Signature verification failed"
}
]]></artwork>
</figure>
</section>
</section>
<section title="IdP Proxy Setup" anchor="sec.iframe-setup">
<t>
In order to perform an identity transaction, the PeerConnection
must first create the IdP proxy. While the specific technical
mechanism used is left up to the implementation, the
following requirements MUST be met for security and
interoperability.
</t>
<t>
<list style="symbols">
<t>Any JS MUST run in the IdP's security context.</t>
<t>The usual browser sandbox isolation mechanisms MUST
be enforced with respect to the IdP proxy.</t>
<t>JS running in the IdP proxy MUST be able to
send and receive messages to the PeerConnection
object using postMessage.</t>
<t>Either window.parent or window.opener MUST
be set such that messages sent with postMessage()
arrive at the PeerConnection object. If both
variables are set, they MUST be the same.</t>
<t>Messages sent by the PeerConnection object
MUST have their .origin value set to "rtcweb:://idp-interface".
[TBD]</t>
</list>
</t>
<t>
One mechanism for implementing the IdP proxy is as a hidden
(CSS "display=none") IFRAME with a URI as determined in <xref
target="sec.idp-uri"/>. The PeerConnection component
will of course need to specially arrange for the
origin value to be set correctly; as dicussed in
<xref target="sec.sec-cons"/>, the fact that ordinary
Web pages cannot set their origins to "rtcweb://..."
is an essential security feature.
</t>
<t>
Initially the IdP proxy is in an unready state; the
IdP JS must be loaded and there may be several round
trips to the IdP server, for instance to log the user
in. Thus, the IFRAME's "onready" property is not a reliable
indicator of when the IdP IFRAME is ready to receive commands.
Instead, when the IdP proxy is ready to receive commands,
it delivers a "ready" message via postMessage(). As this
message is unsolicited, it simply contains:
</t>
<figure>
<artwork><![CDATA[
{ "type":"READY" }
]]></artwork>
</figure>
<t>
Once the PeerConnection object receives the ready message,
it can send commands to the IdP proxy.
</t>
<section title="Determining the IdP URI" anchor="sec.idp-uri">
<t>
Each IdP proxy instance is associated with two values:
</t>
<t>
<list style="hanging">
<t hangText="domain name:">The IdP's domain name</t>
<t hangText="protocol:">The specific IdP protocol
which the IdP is using. This is a completely IdP-specific
string, but allows an IdP to implement two protocols
in parallel. This value may be the empty string.</t>
</list>
</t>
<t>
Each IdP MUST serve its initial entry page
(i.e., the one loaded by the IdP proxy) from
the well-known URI specified in
"/.well-known/idp-proxy/<protocol>" on
the IdP's web site. This URI MUST be loaded
via HTTPS <xref target="RFC2818"/>.
For example, for the IdP "identity.example.com"
and the protocol "example", the URL
would be:
</t>
<figure>
<artwork><![CDATA[
https://example.com/.well-known/idp-proxy/example
]]></artwork>
</figure>
<section title="Authenticating Party">
<t>
How an AP determines the appropriate IdP domain is
out of scope of this specification. In general,
however, the AP has some actual account relationship
with the IdP, as this identity is what the IdP is
attesting to. Thus, the AP somehow supplies the
IdP information to the browser. Some potential
mechanisms include:
</t>
<t>
<list style="symbols">
<t>Provided by the user directly.</t>
<t>Selected from some set of IdPs known to the calling site.
E.g., a button that shows "Authenticate via Facebook Connect"</t>
</list>
</t>
</section>
<section title="Relying Party">
<t>
Unlike the AP, the RP need not have any particular
relationship with the IdP. Rather, it needs to be able
to process whatever assertion is provided by the AP.
As the assertion contains the IdP's identity,
the URI can be constructed directly from the
assertion, and thus the RP can directly verify
the technical validity of the assertion with no user
interaction. Authoritative assertions need only
be verifiable. Third-party assertions also MUST be
verified against local policy, as described in
<xref target="sec.id-format"/>.
</t>
</section>
</section>
</section>
<section title="Requesting Assertions" anchor="sec.request-assert">
<t>
In order to request an assertion, the PeerConnection
sends a "SIGN" message. Aside from the mandatory fields,
this message has a "message" field containing a string.
The contents of this string are defined in
<xref target="I-D.ietf-rtcweb-security"/>, but are
opaque from the perspective of this protocol.
</t>
<t>
A successful response to a "SIGN" message contains
a message field which is a JS dictionary
dictionary consisting of two fields:
</t>
<t>
<list style="hanging">
<t hangText="idp:">A dictionary containing the domain name of the provider
and the protocol string</t>
<t hangText="assertion:">An opaque field containing the
assertion itself. This is only interpretable by the
idp or its proxy.</t>
</list>
</t>
<t>
<xref target="fig.assert-request"/> shows an
example transaction, with the message
"abcde..." being signed and bound to identity
"ekr@example.org". In this case, the message has presumably
been
digitally signed/MACed in some way that the IdP can
later verify it, but this is an implementation detail
and out of scope of this document. Line breaks are inserted
solely for readability.
</t>
<figure title="Example assertion request" anchor="fig.assert-request">
<artwork><![CDATA[
PeerConnection -> IdP proxy:
{
"type":"SIGN",
"id":1,
"message":"abcdefghijklmnopqrstuvwyz"
}
IdPProxy -> PeerConnection:
{
"type":"SUCCESS",
"id":1,
"message": {
"idp":{
"domain": "example.org"
"protocol": "bogus"
},
"assertion":\"{\"identity\":\"bob@example.org\",
\"contents\":\"abcdefghijklmnopqrstuvwyz\",
\"signature\":\"010203040506\"}"
}
}
]]>
</artwork>
</figure>
</section>
<section title="Verifying Assertions" anchor="sec.verify-assert">
<t>
In order to verify an assertion, an RP sends a "VERIFY"
message to the IdP proxy containing the assertion
supplied by the AP in the "message" field.
</t>
<t>
The IdP proxy verifies the assertion. Depending on the
identity protocol, this may require one or more round
trips to the IdP. For instance, an OAuth-based protocol
will likely require using the IdP as an oracle,
whereas with BrowserID the IdP proxy can likely
verify the signature on the assertion without
contacting the IdP, provided that it has cached
the IdP's public key.
</t>
<t>
Regardless of the mechanism,
if verification succeeds, a successful response from
the IdP proxy MUST contain a message field consisting
of a dictionary/hash with the following fields:
</t>
<t>
<list style="hanging">
<t hangText="identity">The identity of the AP from the
IdP's perspective. Details of this are provided in
<xref target="sec.id-format"/></t>
<t hangText="contents">The original unmodified string
provided by the AP in the original SIGN request.
</t>
</list>
</t>
<t>
<xref target="fig.verify-request"/> shows
an example transaction. Line breaks are inserted
solely for readability.
</t>
<figure title="Example assertion request" anchor="fig.verify-request">
<artwork><![CDATA[
PeerConnection -> IdP Proxy:
{
"type":"VERIFY",
"id":2,
"message":\"{\"identity\":\"bob@example.org\",
\"contents\":\"abcdefghijklmnopqrstuvwyz\",
\"signature\":\"010203040506\"}"
}
IdP Proxy -> PeerConnection:
{
"type":"SUCCESS",
"id":2,
"message": {
"identity" : {
"name" : "bob@example.org",
"displayname" : "Bob"
},
"contents":"abcdefghijklmnopqrstuvwyz"
}
}
]]>
</artwork>
</figure>
<section title="Identity Formats" anchor="sec.id-format">
<t>
Identities passed from the IdP proxy to the PeerConnection
are structured as JSON dictionaries with one mandatory
field: "name". This field MUST consist of an
RFC822-formatted string representing the user's identity.
[[ OPEN ISSUE: Would it be better to have a typed field? ]]
The PeerConnection API MUST check this string as
follows:
</t>
<t>
<list style="numbers">
<t>If the RHS of the string is equal to the domain name
of the IdP proxy, then the assertion is valid,
as the IdP is authoritative for this domain.</t>
<t>If the RHS of the string is not equal to the domain
name of the IdP proxy, then the PeerConnection object
MUST reject the assertion unless (a) the
IdP domain is listed as an acceptable third-party
IdP and (b) local policy is configured to trust
this IdP domain for the RHS of the identity string.
</t>
</list>
</t>
<t>
Sites which have identities that do not fit
into the RFC822 style (for instance, Facebook
ids are simple numeric values) SHOULD
convert them to this form by appending their
IdP domain (e.g., 12345@identity.facebook.com),
thus ensuring that they are authoritative for
the identity.
</t>
<t>
The IdP proxy MAY also include a "displayname" field
which contains a more user-friendly identity assertion.
Browsers SHOULD take care in the UI to distinguish the
"name" assertion which is verifiable directly from the
"displayname" which cannot be verified and thus
relies on trust in the IdP. In future,
we may define other fields to allow the IdP to
provide more information to the browser.
</t>
</section>
<section title="PostMessage Checks" anchor="sec.postmessage">
<t>
Because the PeerConnect object and the IdP proxy communicate
via postMessage(), it is essential to verify that the
origin of any message (contained in the event.origin
property) and source (contained in the event.source)
property are as expected:
</t>
<t>
<list style="symbols">
<t>
For messages from the PeerConnection object, the
IdP proxy MUST verify that the origin is
"rtcweb://idp-interface" and that the source
matches either window.opener or window.parent.
If both are non-falsey, they MUST be equal.
If any of these checks fail, the message MUST
be rejected.
[[ OPEN ISSUE: An alternate (more generic) design would be to not
check the origin here but rather to include the origin
in the assertion and have it checked at the RP. Comments? ]]
</t>
<t>
For messages from the IdP proxy, the PeerConnection
object MUST verify that the origin matches
the IdP's origin and that the source matches
the window/IFRAME opened for the IdP proxy.
</t>
</list>
</t>
<t>
If any of these checks fail, the message MUST
be rejected. In general, mismatches SHOULD NOT
cause transaction failure, since malicious
JS might use bogus messages as a form of DoS
attack.
</t>
</section>
<section title="PeerConnection API Extensions" anchor="sec.pc-api">
<section title="Authenticating Party">
<t>
As discussed in <xref target="sec.trust-relationships"/>,
the AP's IdP can either be configured directly into the
browser or selected from a list known to the calling
site. We anticipate that some browsers will allow
configuration of IdPs in the browser UI but allow the
calling application to provide new candidate IdPs or
to direct the selection of a known one. Thus, one
model would be:
</t>
<t>
<list style="symbols">
<t>If a IdP is provided by the calling application use that.</t>
<t>If no IdP is provided, and one is configured, use that.</t>
<t>If no IdP is provided or configured, do nothing.</t>
</list>
</t>
<t>
Implementations MAY also wish to have configuration settings
override the calling application's preferences.
</t>
<t>
APIs for PeerConnection configuration are as-yet unsettled, but
it MUST be possible to specify the following parameters to the
PeerConnection.
</t>
<t>
<list style="symbols">
<t>The IdP domain.</t>
<t>The users expected identity (if known) [this allows selection
between multiple candidate identities with the same IdP.]</t>
</list>
</t>
</section>
<section title="Relying Party">
<t>
Because the browser UI must be responsible for displaying
the user's identity, it isn't strictly necessary to
have new JS interfaces on the relying party side. However,
two new interfaces are RECOMMENDED.
</t>
<t>
When a message is provided to the PeerConnection API with
processSignalingMessage() with an assertion that cannot
be verified, there is a need for some sort of error
indicating verification failure. [Note: I don't
see an interface for any other kind of parse error,
so I'm not sure what to imitate here.]
</t>
<t>
A new attribute should be added to indicate the verification
status. For instance:
<figure>
<artwork><![CDATA[
readonly attribute DOMString verifiedIdentity;
]]>
</artwork>
</figure>
The attribute value should be a JS dictionary indicating the identity
and the domain name of the IdP, such as:
</t>
<figure>
<artwork><![CDATA[
{
"identity" : "ekr@example.org",
"idp": "example.org"
}
]]>
</artwork>
</figure>
</section>
</section>
</section>
<section title="Example Bindings to Specific Protocols">
<t>
This section provides some examples of how the
mechanisms described in this document could be used
with existing authentication protocols such as
BrowserID or OAuth. Note that this does not
require browser-level support for either protocol.
Rather, the protocols can be fit into the generic
framework. (Though BrowserID in particular works
better with some client side support).
</t>
<section title="BrowserID">
<t>
BrowserID [https://browserid.org/] is a technology which
allows a user with a verified email address to generate
an assertion (authenticated by their identity provider)
attesting to their identity (phrased as an email address).
The way that this is used in practice is that the relying
party embeds JS in their site which talks to the BrowserID
code (either hosted on a trusted intermediary or embedded
in the browser). That code generates the assertion which is
passed back to the relying party for verification.
The assertion can be verified directly or with a Web
service provided by the identity provider.
It's relatively easy to extend this functionality to
authenticate RTCWEB calls, as shown below.
</t>
<figure>
<artwork><![CDATA[
+----------------------+ +----------------------+
| | | |
| Alice's Browser | | Bob's Browser |
| | OFFER ------------> | |
| Calling JS Code | | Calling JS Code |
| ^ | | ^ |
| | | | | |
| v | | v |
| PeerConnection | | PeerConnection |
| | ^ | | | ^ |
| Finger| |Signed | |Signed | | |
| print | |Finger | |Finger | |"Alice"|
| | |print | |print | | |
| v | | | v | |
| +--------------+ | | +---------------+ |
| | IdP Proxy | | | | IdP Proxy | |
| | to | | | | to | |
| | BrowserID | | | | BrowserID | |
| | Signer | | | | Verifier | |
| +--------------+ | | +---------------+ |
| ^ | | ^ |
+-----------|----------+ +----------|-----------+
| |
| Get certificate |
v | Check
+----------------------+ | certificate
| | |
| Identity |/-------------------------------+
| Provider |
| |
+----------------------+
]]></artwork>
</figure>
<t>
The way this mechanism works is as follows. On Alice's side, Alice
goes to initiate a call.
</t>
<t><list style="numbers">
<t>The calling JS instantiates a PeerConnection
and tells it that it is interested in having it authenticated
via BrowserID (i.e., it provides "browserid.org" as the
IdP name.)</t>
<t>The PeerConnection instantiates the BrowserID signer in
the IdP proxy
</t>
<t>The BrowserID signer contacts Alice's identity provider,
authenticating as Alice (likely via a cookie).</t>
<t>The identity provider returns a short-term certificate
attesting to Alice's identity and her short-term public key.</t>
<t>The Browser-ID code signs the fingerprint and returns the
signed assertion + certificate to the PeerConnection. </t>
<t>The PeerConnection returns the signed information to the
calling JS code.</t>
<t>The signed assertion gets sent over the wire to Bob's
browser (via the signaling service) as part of the call setup.</t>
</list>
</t>
<t>
Obviously, the format of the signed assertion varies depending
on what signaling style the WG ultimately adopts. However, for
concreteness, if something like ROAP were adopted, then the
entire message might look like:
</t>
<figure>
<artwork><![CDATA[
{
"messageType":"OFFER",
"callerSessionId":"13456789ABCDEF",
"seq": 1
"sdp":"
v=0\n
o=- 2890844526 2890842807 IN IP4 192.0.2.1\n
s= \n
c=IN IP4 192.0.2.1\n
t=2873397496 2873404696\n
m=audio 49170 RTP/AVP 0\n
a=fingerprint: SHA-1 \
4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\n",
"identity":{
"idp":{ // Standardized
"domain":"browserid.org",
"method":"default"
},
"assertion": // Contents are browserid-specific
"\"assertion\": {
\"digest\":\"<hash of the contents from the browser>\",
\"audience\": \"[TBD]\"
\"valid-until\": 1308859352261,
},
\"certificate\": {
\"email\": \"rescorla@example.org\",
\"public-key\": \"<ekrs-public-key>\",
\"valid-until\": 1308860561861,
}" // certificate is signed by example.org
}
}
]]></artwork>
</figure>
<t>
<!-- [TODO: Need to talk about Audience a bit.] -->
Note that while the IdP here is specified as "browserid.org",
the actual certificate is signed by example.org. This is because
BrowserID is a combined authoritative/third-party system in
which browserid.org delegates the right to be authoritative
(what BrowserID calls primary) to individual domains.
</t>
<t>
On Bob's side, he receives the signed assertion as part of the call
setup message and a similar procedure happens to verify it.
</t>
<t><list style="numbers">
<t>The calling JS instantiates a PeerConnection
and provides it the relevant signaling information, including the
signed assertion.</t>
<t>The PeerConnection instantiates the IdP proxy which examines
the IdP name and brings up the BrowserID verification code.</t>
<t>The BrowserID verifier contacts the identity provider to
verify the certificate and then uses the key to verify the
signed fingerprint.</t>
<t>Alice's verified identity is returned to the PeerConnection
(it already has the fingerprint).</t>
<t>At this point, Bob's browser can display a trusted UI indication
that Alice is on the other end of the call.</t>
</list>
</t>
<t>
When Bob returns his answer, he follows the converse procedure, which
provides Alice with a signed assertion of Bob's identity and keying
material.
</t>
</section>
<section title="OAuth">
<t>
While OAuth is not directly designed for user-to-user authentication,
with a little lateral thinking it can be made to serve. We use the
following mapping of OAuth concepts to RTCWEB concepts:
</t>
<texttable anchor="oauth-rtcweb">
<ttcol align="left">OAuth</ttcol>
<ttcol align="left">RTCWEB</ttcol>
<c>Client</c><c>Relying party</c>
<c>Resource owner</c><c>Authenticating party</c>
<c>Authorization server</c><c>Identity service</c>
<c>Resource server</c><c>Identity service</c>
</texttable>
<t>
The idea here is that when Alice wants to authenticate to Bob (i.e., for
Bob to be aware that she is calling). In order to do this, she allows
Bob to see a resource on the identity provider that is bound to the
call, her identity, and her public key. Then Bob retrieves the resource
from the identity provider, thus verifying the binding between Alice
and the call.
</t>
<figure>
<artwork><![CDATA[
Alice IdP Bob
---------------------------------------------------------
Call-Id, Fingerprint ------->
<------------------- Auth Code
Auth Code ---------------------------------------------->
<----- Get Token + Auth Code
Token --------------------->
<------------- Get call-info
Call-Id, Fingerprint ------>
]]></artwork>
</figure>
<t>
This is a modified version of a common OAuth flow, but
omits the redirects required to have the client point the
resource owner to the IdP, which is acting as both
the resource server and the authorization server, since
Alice already has a handle to the IdP.
</t>
<t>
Above, we have referred to "Alice", but really what we mean
is the PeerConnection. Specifically, the PeerConnection will
instantiate an IFRAME with JS from the IdP and will use
that IFRAME to communicate with the IdP, authenticating
with Alice's identity (e.g., cookie). Similarly, Bob's
PeerConnection instantiates an IFRAME to talk to the IdP.
</t>
</section>
</section>
<section title="Security Considerations" anchor="sec.sec-cons">
<t>
This mechanism relies for its security on the IdP and on
the PeerConnection correctly enforcing the security
invariants described above. At a high level, the IdP
is attesting that the user identified in the assertion
wishes to be associated with the assertion. Thus,
it must not be possible for arbitrary third parties to
get assertions tied to a user or to produce assertions
that RPs will accept.
</t>
<section title="PeerConnection Origin Check" anchor="sec.pc-origin">
<t>
Fundamentally, the IdP proxy is just a piece of HTML and JS
loaded by the browser, so nothing stops a Web attacker o
from creating their own IFRAME, loading the IdP proxy HTML/JS,
and requesting a signature. In order to prevent this attack,
we require that all signatures be tied to a specific
origin ("rtcweb://...") which cannot be produced by
a page tied to a Web attacker. Thus, while an attacker
can instantiate the IdP proxy, they cannot send messages
from an appropriate origin and so cannot create acceptable
assertions. [[OPEN ISSUE: Where is this enforced? ]]
</t>
</section>
<section title="IdP Well-known URI" anchor="sec.sec-idp-uri">
<t>
As described in <xref target="sec.idp-uri"/> the IdP proxy
HTML/JS landing page is located at a well-known URI based on
the IdP's domain name. This requirement prevents an attacker
who can write some resources at the IdP (e.g., on one's
Facebook wall) from being able to impersonate the IdP.
</t>
</section>
<section title="Security of Third-Party IdPs" anchor="sec.sec-third-party">
<t>
As discussed above, each third-party IdP represents a new universal trust
point and therefore the number of these IdPs needs to be
quite limited. Most IdPs, even those which issue unqualified
identities such as Facebook, can be recast as authoritative
IdPs (e.g., 123456@facebook.com). However, in such cases,
the user interface implications are not entirely desirable.
One intermediate approach is to have special (potentially user
configurable) UI for large authoritative IdPs, thus allowing
the user to instantly grasp that the call is being authenticated
by Facebook, Google, etc.
</t>
</section>
</section>
<section title="Web Security Feature Interactions">
<t>
A number of optional Web security features have the potential
to cause issues for this mechanism, as discussed below.
</t>
<section title="Popup Blocking" anchor="sec.popup-blocking">
<t>
If the user is not already logged into the IdP, the
IdP proxy may need to pop up a top level window in order
to prompt the user for their authentication information
(it is bad practice to do this in an IFRAME inside the
window because then users have no way to determine the
destination for their password). If the user's browser
is configured to prevent popups, this may fail
(depending on the exact algorithm that the popup blocker
uses to suppress popups). It may be necessary to provide
a standardized mechanism to allow the IdP proxy to
request popping of a login window. Note that
care must be taken here to avoid PeerConnection becoming
a general escape hatch from popup blocking. One possibility
would be to only allow popups when the user has explicitly
registered a given IdP as one of theirs (this is only relevant
at the AP side in any case). This is what WebIntents does, and
the problem would go away if WebIntents is used.
</t>
</section>
<section title="Third Party Cookies" anchor="sec.3rd-party-cookies">
<t>
Some browsers allow users to block third party cookies (cookies associated
with origins other than the top level page) for privacy reasons.
Any IdP which uses cookies to persist logins will be broken
by third-party cookie blocking. One option is to accept this
as a limitation; another is to have the PeerConnection object
disable third-party cookie blocking for the IdP proxy.
</t>
</section>
</section>
</section>
</middle>
<back>
<references title="Normative References">
&RFC2119;
&RFC2818;
&I-D.ietf-rtcweb-security;
&I-D.ietf-rtcweb-security-arch;
&RFC4627;
</references>
<references title="Informative References">
&RFC6454;
</references>
</back>
</rfc>
| PAFTECH AB 2003-2026 | 2026-04-23 05:26:00 |