RFC 8827

WebRTC Security Architecture

πŸ“… published January 2021, from ietf

RFC 8827: WebRTC Security Architecture ✨

Okay bestie, so this is RFC 8827, WebRTC Security Architecture πŸŽ€. It was written by E. Rescorla at Mozilla and published in January 2021. It's a Standards Track document, which means it's an actual Internet standard and not just a suggestion πŸ’…. The IETF is the one that put it out, and the ISSN is 2070-1721. The header doesn't list anything it obsoletes or updates, so this one is doing its own thing πŸ¦‹.

Abstract

This document defines the security architecture for WebRTC, a protocol suite for real-time apps that can run in browsers. It's basically "real-time communication on the Web" 🌸.

Status of This Memo

This is an Internet Standards Track document πŸ’–.

It's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841 ✨.

For the current status, any errata, and how to give feedback, go to https://www.rfc-editor.org/info/rfc8827 🧚.

Copyright (c) 2021 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication. Please read these carefully, because they explain your rights and restrictions for this document 🫢. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they're provided without warranty as described in the Simplified BSD License πŸ’œ.

This document may contain material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The people who control the copyright in some of that material may not have given the IETF Trust permission to allow modifications outside the IETF Standards Process. Unless you get an adequate license from them, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be created outside the IETF Standards Process. The exceptions are formatting it for publication as an RFC or translating it into languages other than English πŸ“œ.

Table of Contents

   1.  Introduction
   2.  Terminology
   3.  Trust Model
     3.1.  Authenticated Entities
     3.2.  Unauthenticated Entities
   4.  Overview
     4.1.  Initial Signaling
     4.2.  Media Consent Verification
     4.3.  DTLS Handshake
     4.4.  Communications and Consent Freshness
   5.  SDP Identity Attribute
     5.1.  Offer/Answer Considerations
       5.1.1.  Generating the Initial SDP Offer
       5.1.2.  Generating an SDP Answer
       5.1.3.  Processing an SDP Offer or Answer
       5.1.4.  Modifying the Session
   6.  Detailed Technical Description
     6.1.  Origin and Web Security Issues
     6.2.  Device Permissions Model
     6.3.  Communications Consent
     6.4.  IP Location Privacy
     6.5.  Communications Security
   7.  Web-Based Peer Authentication
     7.1.  Trust Relationships: IdPs, APs, and RPs
     7.2.  Overview of Operation
     7.3.  Items for Standardization
     7.4.  Binding Identity Assertions to JSEP Offer/Answer
           Transactions
       7.4.1.  Carrying Identity Assertions
     7.5.  Determining the IdP URI
       7.5.1.  Authenticating Party
       7.5.2.  Relying Party
     7.6.  Requesting Assertions
     7.7.  Managing User Login
   8.  Verifying Assertions
     8.1.  Identity Formats
   9.  Security Considerations
     9.1.  Communications Security
     9.2.  Privacy
     9.3.  Denial of Service
     9.4.  IdP Authentication Mechanism
       9.4.1.  PeerConnection Origin Check
       9.4.2.  IdP Well-Known URI
       9.4.3.  Privacy of IdP-Generated Identities and the Hosting
               Site
       9.4.4.  Security of Third-Party IdPs
         9.4.4.1.  Confusable Characters
       9.4.5.  Web Security Feature Interactions
         9.4.5.1.  Popup Blocking
         9.4.5.2.  Third Party Cookies
   10. IANA Considerations
   11. References
     11.1.  Normative References
     11.2.  Informative References
   Acknowledgements
   Author's Address

1. Introduction ✨

The RTCWEB Working Group standardized protocols for real-time communications between web browsers, which everyone calls "WebRTC" [RFC8825] πŸŽ€. The big use cases are real-time audio and/or video calls, web conferencing, and direct data transfer πŸ’–. Most traditional real-time systems are different. SIP-based [RFC3261] softphones, for example, aren't controlled that way. With WebRTC, a web server directly controls the communication through a JavaScript (JS) API, as shown in Figure 1 πŸ¦‹.

                            +----------------+
                            |                |
                            |   Web Server   |
                            |                |
                            +----------------+
                                ^        ^
                               /          \
                       HTTP   /            \   HTTP
                             /              \
                            /                \
                           v                  v
                        JS API              JS API
                  +-----------+            +-----------+
                  |           |    Media   |           |
                  |  Browser  |<---------->|  Browser  |
                  |           |            |           |
                  +-----------+            +-----------+

Figure 1: A Simple WebRTC System

A more complicated setup could do calls between domains, as shown in Figure 2 🌈. WebRTC doesn't standardize the protocol used between the domains. Given the installed base and the shape of the WebRTC API, it'll probably be something SDP-based like SIP, or something like the Extensible Messaging and Presence Protocol (XMPP) [RFC6120] 🧚.

             +--------------+                +--------------+
             |              | SIP, XMPP, ... |              |
             |  Web Server  |<-------------->|  Web Server  |
             |              |                |              |
             +--------------+                +--------------+
                    ^                                ^
                    |                                |
              HTTP  |                                |  HTTP
                    |                                |
                    v                                v
                    JS API                       JS API
              +-----------+                     +-----------+
              |           |        Media        |           |
              |  Browser  |<------------------->|  Browser  |
              |           |                     |           |
              +-----------+                     +-----------+

Figure 2: A Multidomain WebRTC System

This setup brings a bunch of new security challenges, which are analyzed in [RFC8826] 😭. This document describes the security architecture for WebRTC that deals with the threats and requirements from that document πŸ”₯.

2. Terminology πŸ’…

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are interpreted as described in BCP 14 [RFC2119] [RFC8174], but only when they're written in all capitals, like that πŸŽ€.

3. Trust Model πŸ‘‘

The basic idea here is that network resources sit in a hierarchy of trust, rooted in the browser, which is the user's Trusted Computing Base (TCB) 🫢. Any security property the user wants enforced must ultimately be guaranteed by the browser, or transitively by something the browser verifies πŸ”’. It's also the other way around: if the browser is compromised, no security guarantees are possible πŸ’€. Some cases, like Internet kiosks, mean the user can't really trust the browser that much. In those cases, the level of security is limited by how much they trust the browser πŸ™ˆ.

Ideally we wouldn't rely on trust in anything except the browser. Sadly, that isn't possible if we want a functional system 😩. Other network elements fall into two groups. The first group can be authenticated by the browser, so they can be given permission to access sensitive resources. The second group can't be authenticated, so they're untrusted 🌸.

3.1. Authenticated Entities

There are two major classes of authenticated entities in the system ✨:

  • Calling services: Web sites whose origin we can verify. Ideally that's via HTTPS, but sometimes we're on a topologically restricted network, like behind a firewall, and can infer authentication from the firewall's behavior 🧱.
  • Other users: WebRTC peers whose origin we can verify cryptographically. Ideally that's via DTLS-SRTP πŸ”.

Just being authenticated doesn't make these entities trusted, though 🚨. For example, just because we can verify that <https://www.example.org/> belongs to Dr. Evil doesn't mean we can trust Dr. Evil with our camera and microphone 😈. It does give the user a chance to decide whether they want to trust Dr. Evil or not. Say they want to contact Dr. Evil, maybe to arrange a ransom payment. It's safe to give them camera and microphone access temporarily, just for the call. But they don't want Dr. Evil getting into their camera and microphone outside of the call πŸ™…β€β™€οΈ. The point is that we have to identify other elements first before we can figure out whether to trust them, and how much. Sometimes we also need to know who the communicating peer is before we know which policies to apply 🧐.

3.2. Unauthenticated Entities

Anything else isn't something we can generally identify, so we can't trust those network elements either πŸ«₯. That doesn't mean we can't interact with them at all. It does mean we have to assume they'll behave maliciously, and design a system that stays secure even if they do 😀.

Part 1 of 9 is done, bestie! 🫢 More parts are coming, so stay tuned πŸ’œ

4. Overview ✨

okay so this section walks through a typical WebRTC session and shows how all the security pieces work together and what guarantees the user actually gets πŸ”πŸ’–. The example is the "best case" scenario, meaning we give the MOST user authentication and media privacy while trusting the calling service the LEAST 😀🫢. Simpler setups with lower security levels are also possible, and the text points them out where they fit πŸŽ€. It's also super important to remember that security (or performance) and privacy can be in tension πŸ‘€. This example leans toward caring more about secure calling than privacy, but as we'll see, some settings want different tradeoffs, and this architecture still works for those too πŸ’…βœ¨.

For this example, we're using the topology in the figures below πŸ¦‹. It's based on the topology in Figure 1, but it pulls Alice's and Bob's identities out of the signaling process 🧚. So Alice and Bob each have a relationship with some Identity Provider (IdP) that supports a protocol like OpenID Connect, which they can use to prove who they are to other parties πŸͺͺ. Think of it like Alice having an account with a social network that she uses to log into other websites without making a separate account for each one, which is a pretty classic pattern on the Web 🌸. Section 7.1 gives the overview of IdPs and the vocab you need πŸ“š. Alice and Bob can also have relationships with different IdPs, totally valid πŸ’œ. Heads up: the IdP mechanism described here hasn't really caught on yet 😭. Check out Section 7 for the current status of IdP-based authentication πŸ™ˆ.

Splitting identity provision from signaling doesn't matter much in "closed world" cases, where Alice and Bob are users on the same social network and their identities come from that domain (Figure 3) πŸ“. It DOES matter in settings like federation, which means calls going from one domain to another (see Figure 4), and calling on untrusted sites πŸ‘‘. Like, say two users who know each other through a social network want to call each other on some other untrusted site, such as a poker site πŸƒπŸ”₯.

Oh, and the servers themselves get authenticated too, by an external identity service: the SSL/TLS certificate infrastructure (not shown here) πŸ”’. As is normal on the Web, every identity ultimately traces back to that system 🌈. For example, when an IdP makes an identity assertion, the Relying Party that consumes the assertion can verify it because it's able to connect to the IdP over HTTPS 🫢✨.

                               +----------------+
                               |                |
                               |     Signaling  |
                               |     Server     |
                               |                |
                               +----------------+
                                   ^        ^
                                  /          \
                          HTTPS  /            \   HTTPS
                                /              \
                               /                \
                              v                  v
                           JS API              JS API
                     +-----------+            +-----------+
                     |           |    Media   |           |
               Alice |  Browser  |<---------->|  Browser  | Bob
                     |           | (DTLS+SRTP)|           |
                     +-----------+            +-----------+
                           ^      ^--+     +--^     ^
                           |         |     |        |
                           v         |     |        v
                     +-----------+   |     |  +-----------+
                     |           |<--------+  |           |
                     |   IdP1    |   |        |    IdP2   |
                     |           |   +------->|           |
                     +-----------+            +-----------+

                  Figure 3: A Call with IdP-Based Identity

Figure 4 is basically the same calling scenario, but now the call goes between two separate domains (aka the federated case), like in Figure 2 πŸŒπŸ’«. Like we said before, the domains talk to each other through some unspecified protocol, and keeping signaling and identity separate means calls can be authenticated no matter what the inter-domain protocol looks like πŸ¦‹πŸ’–.

           +----------------+    Unspecified    +----------------+
           |                |      protocol     |                |
           |    Signaling   |<----------------->|    Signaling   |
           |    Server      |  (SIP, XMPP, ...) |    Server      |
           |                |                   |                |
           +----------------+                   +----------------+
                    ^                                   ^
                    |                                   |
              HTTPS |                                   | HTTPS
                    |                                   |
                    |                                   |
                    v                                   v
                 JS API                               JS API
           +-----------+                             +-----------+
           |           |             Media           |           |
     Alice |  Browser  |<--------------------------->|  Browser  | Bob
           |           |           DTLS+SRTP         |           |
           +-----------+                             +-----------+
                 ^      ^--+                      +--^     ^
                 |         |                      |        |
                 v         |                      |        v
           +-----------+   |                      |  +-----------+
           |           |<-------------------------+  |           |
           |   IdP1    |   |                         |    IdP2   |
           |           |   +------------------------>|           |
           +-----------+                             +-----------+

             Figure 4: A Federated Call with IdP-Based Identity

4.1. Initial Signaling ✨

okay so, let's make this easy and assume the setup in Figure 3 πŸŽ€ Alice and Bob are both users of the same calling service, and they've both approved it to make calls (we'll get to device access permissions later πŸ’…). They're each connected to the calling service over HTTPS, so they know where the other end is coming from with some confidence πŸ”’ They also have accounts with some IdP. This kind of identity service is getting super common on the Web (think Federated Google Login, Facebook Connect, OAuth, OpenID, WebFinger πŸ¦‹), and it's often a side perk of your regular account with some other service. In this example, Alice and Bob use a separate identity service, but it could be the same entity as the calling service, or there could be no identity service at all πŸ€·β€β™€οΈ

So Alice is logged into the calling service and decides to call Bob πŸ“ž She can see that he's online, and the calling service shows a JS UI in the form of a "Call" button right next to Bob's name πŸ’– Alice clicks it, which kicks off a JS callback that creates a PeerConnection object. There's no security check for this part: JS from any origin is allowed to get this far ✨

Once the PeerConnection exists, the calling service JS needs to set up some media πŸŽ₯ Since this is an audio/video call, it makes a MediaStream with two MediaStreamTracks, one hooked up to an audio input and one hooked up to a video input. This is where the first security check kicks in 🚨 untrusted origins are NOT allowed to touch the camera and microphone, so the browser prompts Alice for permission. (Okay, it's "required," not "NOT," I'm just hyped 😭 the rule is that untrusted origins are not allowed to access the camera and microphone.)

In the current W3C API, once some streams have been added, Alice's browser + JS generates a signaling message [RFC8829] containing:

  • Media channel information
  • Interactive Connectivity Establishment (ICE) [RFC8445] candidates
  • A "fingerprint" attribute binding the communication to a key pair [RFC5763]. Note that this key may simply be ephemerally generated for this call or specific to this domain, and Alice may have a large number of such keys πŸ”‘

Before the signaling message gets sent, the PeerConnection code checks in with the identity service and gets an assertion that binds Alice's identity to her fingerprint πŸͺͺ The exact details depend on the identity service (though, as Section 7 explains, PeerConnection can be agnostic to them 🧚), but for now it's easiest to think of it as an OAuth token. The assertion can bind other info to the identity too, but at minimum it has to bind the fingerprint.

This message gets sent to the signaling server, for example with fetch() [fetch] or with WebSockets [RFC6455], over TLS [RFC8446] πŸ“¨ The signaling server processes the message from Alice's browser, figures out that it's a call to Bob, and sends a signaling message to Bob's browser (the format is still undefined, so no spoilers πŸ™ˆ). Bob's JS processes it and alerts him to the incoming call and to Alice's identity. Since Alice gave an identity assertion, Bob's browser reaches out to Alice's IdP to verify it (this is done in a generic way, so the browser has zero specific knowledge of the IdP πŸ’…). It's also possible to have IdPs that the browser has a specific trust relationship with, as described in Section 7.1. That lets the browser show a trusted element in the browser chrome saying a call is coming in from Alice πŸ‘‘ If Alice is in Bob's address book, the interface might also show her real name, a picture, etc. The calling site will also show a UI element (like a button) so Bob can answer, but that's most likely NOT part of the trusted UI πŸ™ƒ

If Bob says yes, a PeerConnection gets created using the message from Alice's side. Then the same thing happens as on Alice's browser: Bob's browser prompts him for device permission, the media streams are created, and a return signaling message with media information, ICE candidates, and a fingerprint gets sent back to Alice through the signaling service πŸ” If Bob has a relationship with an IdP, that message comes with an identity assertion too.

At this point, Alice and Bob each know the other one wants a secure call with them 🫢 Based purely on the interface the signaling server gives them, they know the signaling server claims the call is from Alice to Bob. This level of security comes merely from the fingerprint being in the message and that message being received securely from the signaling server πŸ” Because the far end sent an identity assertion along with their message, they know it can be verified with the IdP as well 🧠 Now, if the call is federated (like Figure 4), then Alice can verify Bob's identity in a way that isn't mediated by her signaling server or Bob's. She verifies it directly with Bob's IdP 🌈

Of course, the call still works perfectly well if Alice or Bob doesn't have a relationship with an IdP. They just get a lower level of assurance. Basically, they only have whatever info their calling site claims about the caller or callee's identity 🀭 Also, Alice might want to make an anonymous call through an anonymous calling site. In that case, she just wouldn't provide any identity assertion, and the calling site would mask her identity from Bob πŸ₯·

As described in [RFC8826], Section 4.2, media consent verification is provided via ICE. So Alice and Bob do ICE checks with each other πŸ§šβ€β™€οΈ When those checks finish, they're ready to send non-ICE data.

At this point, Alice knows that (a) Bob (assuming he's verified through his IdP) or someone else the signaling service claims is Bob is willing to exchange traffic with her, and (b) either Bob is at the IP address Alice verified via ICE, or there's an attacker on-path to that IP address detouring the traffic 😬 Note that an attacker who's on-path between Alice and Bob but NOT attached to the signaling service can't spoof these checks, because they don't have the ICE credentials πŸ›‘οΈ Bob has the same security guarantees with respect to Alice.

4.3. DTLS Handshake πŸ”

Once the required ICE checks are done, Alice and Bob can set up a secure channel or channels ✨ This happens via DTLS [RFC6347] and DTLS-SRTP [RFC5763] keying for SRTP [RFC3711] for the media channel, and the Stream Control Transmission Protocol (SCTP) over DTLS [RFC8261] for data channels. Specifically, Alice and Bob do a DTLS handshake on every component that ICE established 🀝 The total number of channels depends on the amount of muxing. In the most likely case, we're using both RTP/RTCP mux and muxing multiple media streams on the same channel, so there's only one DTLS handshake πŸŽ€ Once the handshake is complete, the keys get exported [RFC5705] and used to key SRTP for the media channels πŸ—οΈ

At this point, Alice and Bob know they share a set of secure data and/or media channels with keys that no third-party attacker knows πŸ₯Ή If Alice and Bob authenticated through their IdPs, they also know the signaling service isn't pulling a man-in-the-middle attack on their traffic πŸ‘€ Even if they don't use an IdP, as long as they have minimal trust in the signaling service not to do a man-in-the-middle attack, they know their communications are secure against the signaling service too (meaning the signaling service can't mount a passive attack on the communications) πŸ’…

From a security perspective, everything from here on is a little anticlimactic 😴 Alice and Bob exchange data protected by the keys DTLS negotiated. Because of the security guarantees from the previous sections, they know the communications are encrypted and authenticated πŸ”’

The one remaining security property we need is "consent freshness," which lets Alice verify that Bob is still ready to receive her communications. That way Alice doesn't keep sending large traffic volumes to entities that went abruptly offline πŸ“‰ ICE specifies periodic Session Traversal Utilities for NAT (STUN) keepalives, but only if media isn't flowing. Because consent is trickier here, we require WebRTC implementations to periodically send keepalives using the consent freshness mechanism specified in [RFC7675] πŸ’“ If a keepalive fails and no new ICE channels can be established, the session gets terminated πŸ’€

5. SDP Identity Attribute πŸͺͺ

The SDP "identity" attribute is a session-level attribute that an endpoint uses to convey its identity assertion to its peer πŸ’Œ The identity-assertion value is encoded as base64, as described in Section 4 of [RFC4648].

The procedures in this section are based on the assumption that an endpoint's identity assertion is bound to that endpoint's fingerprints πŸ”— This doesn't rule out defining other ways to bind an assertion to the endpoint, but those ways are outside the scope of this specification.

The semantics of multiple "identity" attributes within an offer or answer are undefined πŸŒ€ Implementations SHOULD only include a single "identity" attribute in an offer or answer, and Relying Parties MAY elect to ignore all but the first "identity" attribute πŸ™Œ

Name:  identity

Value:  identity-assertion

Usage Level:  session

Charset Dependent:  no

Default Value:  N/A

Syntax:

 identity-assertion       = identity-assertion-value
                            *(SP identity-extension)
 identity-assertion-value = base64
 identity-extension       = extension-name [ "=" extension-value ]
 extension-name           = token
 extension-value          = 1*(%x01-09 / %x0b-0c / %x0e-3a / %x3c-ff)
                            ; byte-string from [RFC4566]

 <ALPHA and DIGIT as defined in [RFC4566]>
 <base64 as defined in [RFC4566]>

Example:

a=identity:\
  eyJpZHAiOnsiZG9tYWluIjoiZXhhbXBsZS5vcmciLCJwcm90b2NvbCI6ImJvZ3Vz\
  In0sImFzc2VydGlvbiI6IntcImlkZW50aXR5XCI6XCJib2JAZXhhbXBsZS5vcmdc\
  IixcImNvbnRlbnRzXCI6XCJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3l6XCIsXCJz\
  aWduYXR1cmVcIjpcIjAxMDIwMzA0MDUwNlwifSJ9
Note that long lines in the example are folded to meet the column width constraints of this document; the backslash (\) at the end of a line, the carriage return that follows, and whitespace shall be ignored.

This specification doesn't define any extensions for the attribute 🚫

The identity-assertion value is a JSON encoded string [RFC8259] 🧾 The JSON object has two keys: "assertion" and "idp". The "assertion" key's value is an opaque string that gets consumed by the IdP. The "idp" key's value is a dictionary with one or two further values that identify the IdP. See Section 7.6 for more details πŸ•΅οΈβ€β™€οΈ

5.1. Offer/Answer Considerations πŸŽ€

This section defines the SDP offer/answer [RFC3264] considerations for the SDP "identity" attribute. 🫧

Within this section, 'initial offer' refers to the first offer in the SDP session that contains an SDP "identity" attribute. 🌟

5.1.1. Generating the Initial SDP Offer πŸŽ€

Okay so when an offerer sends an offer πŸ“¨, it wants to hand its identity assertion to the peer, so it adds an "identity" attribute to the offer πŸ¦‹. It also includes one or more SDP "fingerprint" attributes. The "identity" attribute MUST be bound to all the "fingerprint" attributes in the session description. Bestie, that binding is not optional πŸ’…

5.1.2. Generating an SDP Answer ✨

If the answerer decides to include an "identity" attribute, it follows the same steps as in Section 5.1.1 🫢. The answerer can choose to include or omit an "identity" attribute on its own, no matter what the offerer did πŸ’–.

5.1.3. Processing an SDP Offer or Answer πŸ”

When an endpoint gets an offer or answer with an "identity" attribute, the answerer can use that info to contact the IdP and check the peer's identity πŸ•΅οΈβ€β™€οΈ. If the identity needs a third-party IdP, as described in Section 7.1, then that IdP has to have been specifically configured 🌸. If the identity verification fails, the answerer MUST discard the offer or answer as malformed πŸ’€.

5.1.4. Modifying the Session πŸ”„

When you modify a session and the set of fingerprints is unchanged, the sender MAY send the same "identity" attribute πŸ¦‹. In this case, the established identity MUST be applied to existing DTLS connections as well as new connections set up using one of those fingerprints ✨. Note that [RFC8829], Section 5.2.1 requires that each media section use the same set of fingerprints πŸ“. If a new "identity" attribute is received, then the receiver MUST apply that identity to all existing connections πŸ”₯.

If the set of fingerprints changes, then the sender MUST either send a new "identity" attribute or none at all πŸ™ˆ. Because a change in fingerprints also causes a new DTLS connection to be established, the receiver MUST discard all previously established identities 😭.


6. Detailed Technical Description πŸ‘‘

6.1. Origin and Web Security Issues 🌈

The basic unit of permissions for WebRTC is the origin [RFC6454] 🧚. Because the security of the origin depends on being able to authenticate content from that origin, the origin can only be securely established if data is transferred over HTTPS [RFC2818] πŸ”. So clients MUST treat HTTP and HTTPS origins as different permissions domains πŸ™…β€β™€οΈ. Note: This follows directly from the origin security model and is stated here merely for clarity.

Lots of Web browsers currently block active mixed content on HTTPS pages by default 🚫. That means when JavaScript loads from an HTTP origin onto an HTTPS page, an error shows up and the HTTP content doesn't run unless the user overrides the error. Any browser that enforces that policy also won't allow WebRTC functionality from mixed content pages, because they never display mixed content πŸ’…. Browsers which allow active mixed content MUST nevertheless disable WebRTC functionality in mixed content settings πŸ™ˆ.

Also, a page that was not mixed content can become mixed content during the call ⚠️. The major risk here is that the newly arrived insecure JS might redirect media to a location controlled by the attacker 😱. Implementations MUST either choose to terminate the call or display a warning at that point 🚨.

Also note that the security architecture depends on the keying material not being available to move between origins πŸ”‘. However, it is assumed that the identity assertion can be passed to anyone that the page cares to 🫢.

6.2. Device Permissions Model πŸ“·

Implementations MUST obtain explicit user consent before giving access to the camera and/or microphone πŸŽ™οΈ. Implementations MUST at minimum support the following two permissions models for HTTPS origins:

  • Requests for one-time camera/microphone access.
  • Requests for permanent access.

Because HTTP origins cannot be securely established against network attackers, implementations MUST refuse all permissions grants for HTTP origins πŸ™…β€β™€οΈ.

In addition, they SHOULD support requests for access that promise that media from this grant will be sent to a single communicating peer (obviously there could be other requests for other peers), e.g., "Call customerservice@example.org" πŸ“ž. The semantics of this request are that the media stream from the camera and microphone will only be routed through a connection which has been cryptographically verified (through the IdP mechanism or an X.509 certificate in the DTLS-SRTP handshake) as being associated with the stated identity πŸ”’. Note that it is unlikely that browsers would have X.509 certificates, but servers might πŸ€“. Browsers servicing such requests SHOULD clearly indicate that identity to the user when asking for permission πŸ‘€. The idea behind this type of permission is that a user might have a fairly narrow list of peers they are willing to communicate with, e.g., "my mother" rather than "anyone on Facebook" πŸ₯°. Narrow permissions grants allow the browser to do that enforcement πŸ’–.

API Requirement: The API MUST provide a mechanism for the requesting JS to relinquish the ability to see or modify the media (e.g., via MediaStream.record()). Combined with secure authentication of the communicating peer, this allows a user to be sure that the calling site is not accessing or modifying their conversion 🫣.
UI Requirement: The UI MUST clearly indicate when the user's camera and microphone are in use. This indication MUST NOT be suppressible by the JS and MUST clearly indicate how to terminate device access, and provide a UI means to immediately stop camera/microphone input without the JS being able to prevent it πŸ›‘.
UI Requirement: If the UI indication of camera/microphone use is displayed in the browser such that minimizing the browser window would hide the indication, or the JS creating an overlapping window would hide the indication, then the browser SHOULD stop camera and microphone input when the indication is hidden. (Note: This may not be necessary in systems that are non-windows-based but that have good notifications support, such as phones.) πŸ””
  • Browsers MUST NOT permit permanent screen or application sharing permissions to be installed as a response to a JS request for permissions. Instead, they must require some other user action such as a permissions setting or an application install experience to grant permission to a site πŸ™…β€β™€οΈ.
  • Browsers MUST provide a separate dialog request for screen/application sharing permissions even if the media request is made at the same time as the request for camera and microphone permissions πŸͺŸ.
  • The browser MUST indicate any windows which are currently being shared in some unambiguous way. Windows which are not visible MUST NOT be shared even if the application is being shared. If the screen is being shared, then that MUST be indicated πŸ–₯️.

Browsers MAY permit the formation of data channels without any direct user approval πŸ¦‹. Because sites can always tunnel data through the server, further restrictions on the data channel do not provide any additional security πŸ€·β€β™€οΈ. (See Section 6.3 for a related issue.)

Implementations which support some form of direct user authentication SHOULD also provide a policy by which a user can authorize calls only to specific communicating peers πŸ“’. Specifically, the implementation SHOULD provide the following interfaces/controls:

  • Allow future calls to this verified user.
  • Allow future calls to any verified user who is in my system address book (this only works with address book integration, of course).

Implementations SHOULD also provide a different user interface indication when calls are in progress to users whose identities are directly verifiable. Section 6.5 has more on this πŸ’œ.

Browser client implementations of WebRTC MUST implement ICE 🧊. Server gateway implementations which operate only at public IP addresses MUST implement either full ICE or ICE-Lite [RFC8445] 🌐.

Browser implementations MUST verify reachability via ICE prior to sending any non-ICE packets to a given destination πŸ“¬. Implementations MUST NOT provide the ICE transaction ID to JavaScript during the lifetime of the transaction (i.e., during the period when the ICE stack would accept a new response for that transaction) πŸ™ˆ. The JS MUST NOT be permitted to control the local ufrag and password, though it of course knows it πŸ”.

While continuing consent is required, the ICE [RFC8445], Section 11 keepalives use STUN Binding Indications, which are one-way and therefore not sufficient 🫠. The current WG consensus is to use ICE Binding Requests for continuing consent freshness πŸ₯³. ICE already requires that implementations respond to such requests, so this approach is maximally compatible ✨. A separate document will profile the ICE timers to be used; see [RFC7675] πŸ“š.

6.4. IP Location Privacy πŸ¦‹

okay bestie, here's the tea πŸ«–: the default ICE behavior means the peer learns your IP address, and that leaks LOADS of location info 😭. That's a privacy problem in some situations, so the API requirements in this section are there to help. ngl though, these requirements are NOT meant to protect your IP from a sketchy site πŸ’€. Any HTTP transaction tells the site at least your server-reflexive address anyway. The actual goal is letting the site work with you to hide your IP from the other person on the call 🫢. Hiding it from the server needs an explicit privacy mechanism on the client, like Tor Browser (https://www.torproject.org/projects/torbrowser.html.en), and that's out of scope for this spec 🧚.

API Requirement: The API MUST provide a mechanism to allow the JS to suppress ICE negotiation (though perhaps to allow candidate gathering) until the user has decided to answer the call. (Note: Determining when the call has been answered is a question for the JS.) This enables a user to prevent a peer from learning their IP address if they elect not to answer a call and also from learning whether the user is online. πŸ“΅βœ¨

API Requirement: The API MUST provide a mechanism for the calling application JS to indicate that only TURN candidates are to be used. This prevents the peer from learning one's IP address at all. This mechanism MUST also permit suppression of the related address field, since that leaks local addresses. πŸ™ˆ

API Requirement: The API MUST provide a mechanism for the calling application to reconfigure an existing call to add non-TURN candidates. Taken together, this and the previous requirement allow ICE negotiation to start immediately on incoming call notification, thus reducing post-dial delay, but also to avoid disclosing the user's IP address until they have decided to answer. They also allow users to completely hide their IP address for the duration of the call. Finally, they allow a mechanism for the user to optimize performance by reconfiguring to allow non-TURN candidates during an active call if the user decides they no longer need to hide their IP address. this is giving main character energy πŸ‘‘

Note that some enterprises may operate proxies and/or NATs designed to hide internal IP addresses from the outside world. WebRTC provides no explicit mechanism to allow this function. Either such enterprises need to proxy the HTTP/HTTPS and modify the SDP and/or the JS, or there needs to be browser support to set the "TURN-only" policy regardless of the site's preferences. 🏒

Note: These requirements are intended to allow sites to conceal the user's IP address from the peer. For guidance on concealing the user's IP address from the calling site see [RFC8828]. πŸ’œ


6.5. Communications Security πŸ”

Okay the security section is where it gets SERIOUS πŸ˜€πŸ”. Implementations MUST support SRTP [RFC3711]. Implementations MUST support DTLS [RFC6347] and DTLS-SRTP [RFC5763] [RFC5764] for SRTP keying. Implementations MUST support SCTP over DTLS [RFC8261]. no notes, just vibes πŸ’…

All media channels MUST be secured via SRTP and the Secure Real-time Transport Control Protocol (SRTCP). Media traffic MUST NOT be sent over plain (unencrypted) RTP or RTCP; that is, implementations MUST NOT negotiate cipher suites with NULL encryption modes. DTLS-SRTP MUST be offered for every media channel. WebRTC implementations MUST NOT offer SDP security descriptions [RFC4568] or select it if offered. An SRTP Master Key Identifier (MKI) MUST NOT be used. 🚫🫣

All data channels MUST be secured via DTLS. 🌸

All implementations MUST support DTLS 1.2 with the TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 cipher suite and the P-256 curve [FIPS186]. Earlier drafts of this specification required DTLS 1.0 with the cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, and at the time of this writing some implementations do not support DTLS 1.2; endpoints which support only DTLS 1.2 might encounter interoperability issues. The DTLS-SRTP protection profile SRTP_AES128_CM_HMAC_SHA1_80 MUST be supported for SRTP. Implementations MUST favor cipher suites which support Forward Secrecy (FS) over non-FS cipher suites and SHOULD favor Authenticated Encryption with Associated Data (AEAD) over non-AEAD cipher suites. Note: the IETF is in the process of standardizing DTLS 1.3 [TLS-DTLS13]. the future is loading ⏳

Implementations MUST NOT implement DTLS renegotiation and MUST reject it with a "no_renegotiation" alert if offered. πŸ™…β€β™€οΈ

Endpoints MUST NOT implement TLS False Start [RFC7918]. πŸ›‘

API Requirement: The API MUST generate a new authentication key pair for every new call by default. This is intended to allow for unlinkability. πŸ•΅οΈβ€β™€οΈ

API Requirement: The API MUST provide a means to reuse a key pair for calls. This can be used to enable key continuity-based authentication, and could be used to amortize key generation costs. ♻️

API Requirement: Unless the user specifically configures an external key pair, different key pairs MUST be used for each origin. (This avoids creating a super-cookie.) πŸͺ🚫

API Requirement: When DTLS-SRTP is used, the API MUST NOT permit the JS to obtain the negotiated keying material. This requirement preserves the end-to-end security of the media. πŸ”’βœ¨

UI Requirements: A user-oriented client MUST provide an "inspector" interface which allows the user to determine the "security characteristics" of the media.

The following properties SHOULD be displayed "up-front" in the browser chrome, i.e., without requiring the user to ask for them:

  • A client MUST provide a user interface through which a user may determine the "security characteristics" for currently displayed audio and video stream(s). πŸ‘€
  • A client MUST provide a user interface through which a user may determine the "security characteristics" for transmissions of their microphone audio and camera video. πŸŽ™οΈπŸ“Έ
  • If the far endpoint was directly verified, either via a third-party verifiable X.509 certificate or via a Web IdP mechanism (see Section 7), the "security characteristics" MUST include the verified information. X.509 identities and Web IdP identities have similar semantics and should be displayed in a similar way. verified queen behavior πŸ‘‘

The following properties are more likely to require some "drill-down" from the user:

  • The "security characteristics" MUST indicate the cryptographic algorithms in use (for example, "AES-CBC"). πŸ€“
  • The "security characteristics" MUST indicate whether FS is provided. πŸ”
  • The "security characteristics" MUST include some mechanism to allow an out-of-band verification of the peer, such as a certificate fingerprint or a Short Authentication String (SAS). These are compared by the peers to authenticate one another. πŸ«‚πŸ”’

7. Web-Based Peer Authentication 🌐

NOTE: The mechanism described in this section was designed relatively early in the RTCWEB process. In retrospect, the WG was too optimistic about the enthusiasm for this kind of mechanism. At the time of publication, it has not been widely adopted or implemented. It appears in this document as a description of the state of the art as of this writing. πŸ₯²

In a number of cases, it is desirable for the endpoint (i.e., the browser) to be able to directly identify the endpoint on the other side without trusting the signaling service to which they are connected. For instance, users may be making a call via a federated system where they wish to get direct authentication of the other side. Alternately, they may be making a call on a site which they minimally trust (such as a poker site) but to someone who has an identity on a site they do trust (such as a social network). πŸƒ

Recently, a number of Web-based identity technologies (OAuth, Facebook Connect, etc.) have been developed. While the details vary, what these technologies share is that they have a Web-based (i.e., HTTP/HTTPS) IdP which attests to Alice's identity. For instance, if Alice has an account at example.org, Alice could use the example.org IdP to prove to others that Alice is alice@example.org. The development of these technologies allows us to separate calling from identity provision: Alice could call you on a poker site but identify herself as alice@example.org. calling and identity are separate bestie, iykyk 🧚

Whatever the underlying technology, the general principle is that the party which is being authenticated is NOT the signaling site but rather the user (and their browser). Similarly, the Relying Party is the browser and not the signaling site. Thus, the browser MUST generate the input to the IdP assertion process and display the results of the verification process to the user in a way which cannot be imitated by the calling site. πŸš¨πŸ’–

The mechanisms defined 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. 🧩✨

7.1. Trust Relationships: IdPs, APs, and RPs πŸ’…

Okay bestie, every federated identity protocol has three main players 🫢

  • Authenticating Party (AP): the entity trying to establish its identity ✨
  • Identity Provider (IdP): the entity vouching for the AP's identity πŸ¦‹
  • Relying Party (RP): the entity trying to verify the AP's identity πŸ”

The AP and the IdP have an account relationship of some kind. The AP registers with the IdP and can later log in directly to the IdP (like with a password). So the browser has to somehow know which IdP(s) the user has an account with. That can be something the user configures into the browser, or something configured at the calling site and then handed to the PeerConnection by the Web app there. Having it in the browser is useful because the user may "log into" the browser to bind it to some identity, and that's getting super common in new browsers 🌈 But it should also be possible for the calling application to just provide the IdP info itself.

At a high level, there are two kinds of IdPs πŸ‘‘

  • Authoritative: IdPs with verifiable control over some section of the identity space. For example, in email, the operator of "example.com" has complete control of everything ending in "@example.com". So "alice@example.com" is whoever the operator says it is. Systems with authoritative IdPs include DNSSEC, an identity system for SIP (see [RFC8224]), and Facebook Connect (Facebook identities only make sense inside the Facebook system) 🧚
  • Third-Party: IdPs that don't control their section of the identity space, but verify users' identities through some unspecified mechanism and then attest to it. Since the IdP doesn't actually control the namespace, RPs need to trust that the IdP is verifying AP identities correctly, and there can be multiple IdPs attesting to the same section of the identity space. The best-known example is SSL/TLS certificates, where a big pile of certificate authorities (CAs) can all attest to any domain name πŸ™ˆ

If an AP is authenticating via an authoritative IdP, the RP doesn't need to explicitly configure trust in the IdP at all. The identity mechanism can directly verify that the IdP really made the relevant identity assertion (a function provided by the mechanisms in this document), and any assertion it makes about an identity it's authoritative for is directly verifiable. Note that this doesn't mean the IdP could never lie 😭 That's a trustworthiness judgement the user can make at the time they look at the identity.

By contrast, if an AP is authenticating via a third-party IdP, the RP needs to explicitly trust that IdP (this is why PKI-based SSL/TLS clients have an explicit trust anchor list). 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 it means that if third-party IdPs are going to be supported, the potential number needs to be fairly small πŸ“

7.2. Overview of Operation 🌸

Here's the vibe: to provide security without trusting the calling site, the PeerConnection component of the browser has to interact directly with the IdP πŸ” The details live in the W3C API specification, but the general idea is that the PeerConnection component downloads JS from a specific location on the IdP, dictated by the IdP domain name. That JS (the "IdP proxy") runs in an isolated security context within the browser, and the PeerConnection talks to it through a secure message passing channel.

Note that there are two logically separate functions here:

  • Identity assertion generation.
  • Identity assertion verification.

The same IdP JS "endpoint" is used for both functions, but of course a given IdP might behave differently and load new JS to perform one function or the other πŸ’œ

        +--------------------------------------+
        | Browser                              |
        |                                      |
        | +----------------------------------+ |
        | | https://calling-site.example.com | |
        | |                                  | |
        | |        Calling JS Code           | |
        | |               ^                  | |
        | +---------------|------------------+ |
        |                 | API Calls          |
        |                 v                    |
        |          PeerConnection              |
        |                 ^                    |
        |                 | API Calls          |
        |     +-----------|-------------+      |   +---------------+
        |     |           v             |      |   |               |
        |     |       IdP Proxy         |<-------->|   Identity    |
        |     |                         |      |   |   Provider    |
        |     | https://idp.example.org |      |   |               |
        |     +-------------------------+      |   +---------------+
        |                                      |
        +--------------------------------------+

When the PeerConnection object wants to interact with the IdP, the sequence of events goes like this ✨

  1. The browser (the PeerConnection component) instantiates an IdP proxy. This lets the IdP load whatever JS is necessary into the proxy. The resulting code runs in the IdP's security context.
  2. The IdP registers an object with the browser that conforms to the API defined in [webrtc-api].
  3. The browser invokes methods on the object registered by the IdP proxy to create or verify identity assertions.

This approach lets us decouple the browser from any particular IdP πŸ¦‹ The browser only needs to know how to load the IdP's JavaScript (its location is determined by the IdP's identity) and how to call the generic API for requesting and verifying identity assertions. The IdP supplies whatever logic is needed to bridge the generic protocol to its own specific requirements. So a single browser can support any number of identity protocols, including being forward compatible with IdPs that didn't exist when the browser was written πŸŽ€

7.3. Items for Standardization πŸ“

There are two parts to this work:

  • The precise information from the signaling message that must be cryptographically bound to the user's identity, plus a mechanism for carrying assertions in JavaScript Session Establishment Protocol (JSEP) messages. This is specified in Section 7.4.
  • The interface to the IdP, which is defined in the companion W3C WebRTC API specification [webrtc-api].

The WebRTC API specification also defines the JavaScript interfaces the calling application can use to specify which IdP to use. That API also gives access to the assertion-generation capability and the status of the validation process πŸ’…

7.4. Binding Identity Assertions to JSEP Offer/Answer Transactions πŸ”—

An identity assertion binds the user's identity (as asserted by the IdP) to the SDP offer/answer exchange, and specifically to the media 🎢 To make that happen, the PeerConnection must provide the DTLS-SRTP fingerprint to be bound to the identity. This comes as a JavaScript object (also known as a dictionary or hash) with a single "fingerprint" key, like this:

{
  "fingerprint":
    [
      { "algorithm": "sha-256",
        "digest": "4A:AD:B9:B1:3F:...:E5:7C:AB" },
      { "algorithm": "sha-1",
        "digest": "74:E9:76:C8:19:...:F4:45:6B" }
    ]
}

The "fingerprint" value is an array of objects. Each object in the array contains "algorithm" and "digest" values, which line up directly with the algorithm and digest values in the "fingerprint" attribute of the SDP [RFC8122].

This object gets encoded in a JSON [RFC8259] string for passing to the IdP. The identity assertion the IdP returns, which goes in the "identity" attribute, is a JSON object encoded as described in Section 7.4.1 🌈

Here's the best part πŸ™Œ This structure doesn't need to be interpreted by the IdP or the IdP proxy. It's consumed solely by the RP's browser. The IdP just treats it as an opaque value to be attested to, so new parameters can be added to the assertion without modifying the IdP πŸ’–

7.4.1. Carrying Identity Assertions πŸŽ€

Once an IdP has generated an assertion (see Section 7.6), it gets attached to the SDP offer/answer message. This happens by adding a new "identity" attribute to the SDP. The sole contents of that value is the identity assertion. The identity assertion the IdP produces is encoded into a UTF-8 JSON text, then base64-encoded [RFC4648] to make this string. For example:

v=0
o=- 1181923068 1181923196 IN IP4 ua1.example.com
s=example1
c=IN IP4 ua1.example.com
a=fingerprint:sha-1 \
  4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB
a=identity:\
  eyJpZHAiOnsiZG9tYWluIjoiZXhhbXBsZS5vcmciLCJwcm90b2NvbCI6ImJvZ3Vz\
  In0sImFzc2VydGlvbiI6IntcImlkZW50aXR5XCI6XCJib2JAZXhhbXBsZS5vcmdc\
  IixcImNvbnRlbnRzXCI6XCJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3l6XCIsXCJz\
  aWduYXR1cmVcIjpcIjAxMDIwMzA0MDUwNlwifSJ9
a=...
t=0 0
m=audio 6056 RTP/SAVP 0
a=sendrecv
...
⚠️ Quick heads up: long lines in the example are folded so they fit the column width of this document. The backslash (\) at the end of a line, the carriage return that follows it, and any whitespace shall be ignored.

The "identity" attribute attests to all "fingerprint" attributes in the session description, so it's a session-level attribute 🧚

Multiple "fingerprint" values can be used to offer alternative certificates for a peer. The "identity" attribute MUST include all "fingerprint" values that are included in "fingerprint" attributes of the session description. The RP browser MUST verify that the in-use certificate for a DTLS connection is in the set of fingerprints returned from the IdP when verifying an assertion. Non-negotiable, bestie, this is the security core of the whole thing πŸ”₯

7.5. Determining the IdP URI πŸ”—βœ¨

okay so bestie, this part is about keeping things honest 🫢 The IdP's JavaScript has to live at a predictable spot based on the IdP's domain name. Why? So the IdP is actually under the control of the domain owner, and not just some random person who has an account on that domain's server (hi, shared hosting πŸ‘€). Each IdP proxy instance is tied to two values:

  • authority: The authority [RFC3986] at which the IdP's service is hosted.
  • protocol: The specific IdP protocol the IdP is using. It's a completely opaque, IdP-specific string, but it lets an IdP run two protocols in parallel πŸͺ„ This value may be the empty string. If no value for protocol is provided, a value of "default" is used.

Each IdP MUST serve its initial entry page (the one the IdP proxy loads) from a well-known URI [RFC8615]. The well-known URI for an IdP proxy is built from these URI components:

  1. The scheme, https:. An IdP MUST be loaded using HTTPS [RFC2818].
  2. The authority [RFC3986]. As noted above, the authority MAY contain a non-default port number or userinfo sub-component. Both are removed when determining if an asserted identity matches the name of the IdP.
  3. The path, starting with /.well-known/idp-proxy/ and followed by the IdP protocol. The separator characters '/' (%2F) and '\' (%5C) MUST NOT be permitted in the protocol field, lest an attacker be able to direct requests outside of the controlled /.well-known/ prefix 🚫 Query and fragment values MAY be used by including '?' or '#' characters.

For example, for the IdP identity.example.com and the protocol example, the URL would be:

https://identity.example.com/.well-known/idp-proxy/example

The IdP MAY redirect requests to this URL, but they MUST retain the https: scheme. This changes the effective origin of the IdP, but not the domain of the identities that the IdP is permitted to assert and validate. I.e., the IdP is still regarded as authoritative for the original domain πŸ’…

7.5.1. Authenticating Party

How an AP determines the appropriate IdP domain is out of scope of this specification. In general, though, the AP has some actual account relationship with the IdP, since that identity is what the IdP is attesting to. So the AP somehow supplies the IdP information to the browser. Some potential mechanisms include:

  • Provided by the user directly.
  • Selected from some set of IdPs known to the calling site (e.g., a button that shows "Authenticate via Facebook Connect").

7.5.2. Relying Party

Unlike the AP, the RP doesn't need any particular relationship with the IdP πŸ™Œ It just needs to be able to process whatever assertion the AP provides. Because the assertion contains the IdP's identity in the idp field of the JSON-encoded object (see Section 7.6), the URI can be built straight from the assertion. That means the RP can verify the technical validity of the assertion with no user interaction ✨ Authoritative assertions only need to be verifiable. Third-party assertions also MUST be verified against local policy, as described in Section 8.1.

7.6. Requesting Assertions

The input to the identity assertion generation process is the JSON-encoded object described in Section 7.4, which contains the set of certificate fingerprints the browser intends to use. The IdP treats this string as opaque 🫣

The browser also identifies the origin the PeerConnection is running in, which lets the IdP make decisions based on who is asking for the assertion.

An application can optionally provide a user identifier hint when specifying an IdP. This value is a hint the IdP can use to pick between multiple identities, or to avoid providing assertions for identities nobody wants πŸ™ˆ The "username" is a string that means nothing to anyone other than the IdP. It can hold any data the IdP needs in order to generate an assertion correctly.

An identity assertion that the IdP successfully provides consists of the following information:

  • idp: The domain name of an IdP and the protocol string. This MAY identify a different IdP or protocol from the one that generated the assertion.
  • assertion: An opaque value containing the assertion itself. Only the identified IdP, or the IdP code running in the client, can interpret it.

Figure 5 shows an example assertion formatted as JSON. In this case, the message has presumably been digitally signed or MACed in some way that the IdP can later verify, but that's an implementation detail and out of scope for this document πŸ”

{
  "idp":{
    "domain": "example.org",
    "protocol": "bogus"
  },
  "assertion": "{\"identity\":\"bob@example.org\",
                 \"contents\":\"abcdefghijklmnopqrstuvwyz\",
                 \"signature\":\"010203040506\"}"
}

Figure 5: Example Assertion

For use in signaling, the assertion is serialized into JSON, base64-encoded [RFC4648], and used as the value of the "identity" attribute. IdPs SHOULD ensure that any assertions they generate cannot be interpreted in a different context. E.g., they should use a distinct format or have separate cryptographic keys for assertion generation and other purposes. Line breaks are inserted solely for readability 🌸

7.7. Managing User Login

To generate an identity assertion, the IdP needs proof of the user's identity. It's common practice to authenticate users (using passwords or multi-factor authentication), then use cookies [RFC6265] or HTTP authentication [RFC7617] for later exchanges πŸͺ

The IdP proxy can access cookies, HTTP authentication data, or other persistent session data because it operates in the security context of the IdP origin. So if a user is logged in, the IdP could already have everything it needs to generate an assertion πŸ’–

An IdP proxy can't generate an assertion if the user isn't logged in, or if the IdP wants to interact with the user to gather more information before generating it. If the IdP wants to interact with the user before generating an assertion, the IdP proxy can fail to generate one and instead indicate a URL where login should proceed πŸ¦‹

The application can then load the provided URL so the user can enter credentials. The communication between the application and the IdP is described in [webrtc-api].

8. Verifying Assertions

The input to identity validation is the assertion string taken from a decoded "identity" attribute.

The IdP proxy verifies the assertion. Depending on the identity protocol, the proxy might contact the IdP server or other servers. For instance, an OAuth-based protocol will likely require using the IdP as an oracle, whereas with a signature-based scheme it might be able to verify the assertion without contacting the IdP, provided that it has cached the relevant public key πŸ”

Regardless of the mechanism, if verification succeeds, a successful response from the IdP proxy consists of the following information:

  • identity: The identity of the AP from the IdP's perspective. Details of this are provided in Section 8.1.
  • contents: The original, unmodified string the AP provided as input to the assertion generation process.

Figure 6 shows an example response, which is JSON-formatted.

{
  "identity": "bob@example.org",
  "contents": "{\"fingerprint\":[ ... ]}"
}

Figure 6: Example Verification Result

8.1. Identity Formats

The identity the IdP provides to the RP browser MUST consist of a string representing the user's identity. This string takes the form "<user>@<domain>", where "user" can be any character, and domain is an internationalized domain name [RFC5890] encoded as a sequence of U-labels 🌍

The PeerConnection API MUST check this string as follows:

  1. If the "domain" portion 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 βœ… Comparison of domain names is done using the label equivalence rule defined in Section 2.3.2.4 of [RFC5890].
  2. If the "domain" portion of the string is not equal to the domain name of the IdP proxy, then the PeerConnection object MUST reject the assertion unless both:
    1. the IdP domain is trusted as an acceptable third-party IdP; and
    2. local policy is configured to trust this IdP domain for the domain portion of the identity string.

Any '@' or '%' characters in the "user" portion of the identity MUST be escaped according to the "percent-encoding" rules defined in Section 2.1 of [RFC3986]. Characters other than '@' and '%' MUST NOT be percent-encoded. For example, with a "user" of "user@133" and a "domain" of "identity.example.com", the resulting string will be encoded as "user%40133@identity.example.com".

Implementations are cautioned to take care when displaying user identities containing escaped '@' characters. If such characters are unescaped before display, implementations MUST distinguish between the domain of the IdP proxy and any domain that might be implied by the portion of the "<user>" that appears after the escaped "@" sign πŸ‘€βš οΈ

9. Security Considerations

Much of the security analysis of RTCWEB is contained in [RFC8826] or in the discussion of the particular issues above. To avoid repetition, this section focuses on (a) residual threats that aren't addressed by this document and (b) threats produced by failure or misbehavior of one of the components in the system 😀

9.1. Communications Security ✨

Okay bestie, this one is serious 🚨. If HTTPS isn't securing the signaling server AND the identity mechanism from Section 7 isn't being used, then any on-path attacker can swap out the DTLS-SRTP fingerprints during the handshake and pretend to be either endpoint 😱. Not me being dramatic, that's literally the risk.

Even if HTTPS is used, the signaling server can potentially pull a man-in-the-middle move unless implementations have some way to independently verify keys πŸ•΅οΈβ€β™€οΈ. The UI requirements in Section 6.5 are built for motivated, security-conscious users, but they aren't really for general use. The identity service mechanisms in Section 7 are way more suitable for everyday folks 🫢. Heads up though: a malicious signaling service can strip off those identity assertions, but it can't forge new ones. Also, all the third-party security options (X.509 certificates or a third-party IdP) depend on that third party being secure, and that's totally true of your connection to the website itself too 🌐. If users want real peace of mind against a malicious IdP, they can only get it by checking peer credentials directly, like comparing the peer's fingerprint against a value that was delivered out of band πŸ”.

Now the part that's giving main villain energy 😀. To protect against malicious content JavaScript, that JavaScript MUST NOT be allowed to have direct access to -- or perform computations with -- DTLS keys 🚫. Imagine content JS could compute digital signatures. It could grab an identity assertion for a browser's generated key, then use that assertion plus a signature by the key to authenticate a call protected under an ephemeral Diffie-Hellman (DH) key that the content JS controls. Total identity theft of the call, and the security guarantees the IdP mechanism is supposed to give would be gone πŸ’€. It's also not enough to just keep content JS from touching the keys directly, which some people have suggested doing with the WebCrypto API [webcrypto]. The JS also must not be allowed to perform operations that would be valid for a DTLS endpoint. The safest move by far is to block any operation that depends on secret information tied to the key. Operations that only use public information, like exporting the public key, are totally safe πŸ”‘βœ¨.

9.2. Privacy πŸ¦‹

The requirements in this document are meant to allow:

  • Users to join calls without revealing their location πŸ“.
  • Potential callees to keep their location and even their presence status hidden until they agree to answer a call πŸ™ˆ.

Real talk though, these privacy protections come with a performance cost. You're using TURN relays, and in the second case, ICE gets delayed 🐒. Sites SHOULD make users aware of these tradeoffs, so nobody gets surprised.

Also, these protections assume the calling service isn't malicious πŸ‘€. The calling service always knows the user's status and, unless something like Tor is in use, their IP address too, so they can violate the user's privacy whenever they feel like it. If users want privacy from the calling sites they're using, they MUST use separate privacy-enhancing technologies, such as Tor. Hmm, wait, careful: that was a MUST in my head but the original says "must" in lowercase, so I'll keep it lowercase, just as written: they must use separate privacy-enhancing technologies such as Tor πŸ§…. Combined WebRTC/Tor implementations SHOULD arrange to route the media as well as the signaling through Tor. Fair warning, this will currently produce very suboptimal performance πŸ˜….

Another thing: any identifier that sticks around across multiple calls can be a privacy problem, especially for anonymous calling services πŸ₯·. Those services SHOULD instruct the browser to use separate DTLS keys for each call, and to use TURN throughout the call. Otherwise, the other side can learn linkable information that lets them correlate the browser across multiple calls 🧩. And browsers SHOULD implement the privacy-preserving CNAME generation mode of [RFC7022] πŸ’œ.

9.3. Denial of Service 🚨

The consent mechanisms in this document are meant to stop denial-of-service (DoS) attacks, where an attacker uses clients to flood a victim with lots of traffic without the victim's consent 🌊. They're enough to protect victims who haven't implemented WebRTC at all, but WebRTC implementations need to be extra careful 🧐.

Picture a call center that takes calls over WebRTC πŸ“ž. An attacker proxies the call center's front-end and gets multiple clients to start calls to it. This usually needs user consent, but the data channel doesn't need consent, so the attacker can use that directly 😈. Since ICE will complete, browsers can be tricked into sending huge amounts of data to the victim call center, as long as it supports the data channel at all. To prevent this, automated WebRTC implementations need sensible flow control, and they need to be able to triage out calls that are behaving badly (meaning, stop responding to ICE probes on them). They also need to be ready to remotely throttle the data channel when there isn't plausible audio and video, which the attacker can't control πŸ›‘.

A related attack is for the signaling service to swap the ICE candidates for the audio and video streams πŸ”€. That forces a browser to send video to a sink that the other victim expects to contain audio (maybe it's only expecting audio!), which can cause overload. Muxing multiple media flows over a single transport makes it harder to suppress one flow on its own by denying ICE keepalives. So either media-level (RTCP) mechanisms must be used, or the implementation must deny responses entirely, which ends the call πŸ“΄.

Yet another attack, suggested by Magnus Westerlund, is for the attacker to cross-connect offers and answers 🧡. It gets the victim to make a call, then uses its control of other users' browsers to get them to try calling someone. It then translates their offers into apparent answers for the victim, which looks like large-scale parallel forking πŸŒ€. The victim keeps responding to ICE, and now all the browsers try to send media to the victim. Implementations can defend themselves by only responding to ICE Binding Requests for a limited number of remote ufrag values. This is also why the JS must not be able to control the ufrag and password πŸ”’. [RFC8834], Section 13 documents a number of potential RTCP-based DoS attacks and countermeasures πŸ“š.

Also, attacks that confuse one end or the other about consent are possible even with the third-party identity mechanism, as long as major parts of the signaling messages aren't signed ✍️. But signing the entire message severely restricts what the calling application can do, so there are tough tradeoffs here 😬.

9.4. IdP Authentication Mechanism πŸͺͺ

This mechanism relies for its security on the IdP and on the PeerConnection correctly enforcing the security invariants described above πŸ›‘οΈ. Basically, the IdP is vouching that the user identified in the assertion wants to be associated with it. So it must not be possible for random third parties to get assertions tied to a user, or to make assertions that RPs will accept 🚫.

9.4.1. PeerConnection Origin Check πŸ•΅οΈ

Here's the deal: the IdP proxy is just a piece of HTML and JS that the browser loads, so nothing stops a Web attacker from creating their own IFRAME, loading the IdP proxy HTML/JS, and asking for a signature over their own keys instead of the ones generated in the browser 😀. But that proxy would be running in the attacker's origin, not the IdP's origin. Only the browser itself can start a context that (a) is in the IdP's origin and (b) exposes the correct API surface. So the IdP proxy on the sender's side MUST ensure that it is running in the IdP's origin before issuing assertions πŸ™Œ.

This check only shows that the browser (or some other entity with access to the user's authentication data) signs off on the request, and therefore on the fingerprint. It does NOT show that the browser has access to the matching private key πŸ”‘. So an attacker can attach their own identity to someone else's keying material, making a call from Alice look like it's coming from the attacker. See [RFC8844] for defenses against this kind of attack πŸ›‘οΈ.

9.4.2. IdP Well-Known URI 🌟

As described in Section 7.5, the IdP proxy HTML/JS landing page lives at a well-known URI based on the IdP's domain name 🏠. This keeps an attacker who can write some resources at the IdP (e.g., on one's Facebook wall) from impersonating the IdP πŸš«πŸ“.

9.4.3. Privacy of IdP-Generated Identities and the Hosting Site πŸ‘€

Depending on how the IdP's assertions are structured, the calling site may learn the user's identity from the IdP's point of view 🫣. In lots of cases this isn't an issue, because the user is already authenticating to the site through the IdP anyway. For example, someone who logged in with Facebook Connect and then authenticates their call with a Facebook identity πŸ’β€β™€οΈ. But in other cases, the user may not have revealed their identity to the site yet. In general, IdPs SHOULD either verify that the user is willing to have their identity revealed to the site (e.g., through the usual IdP permissions dialog), or arrange for the identity information to be available only to known RPs (e.g., social graph adjacencies) and not to the calling site πŸ§‘β€πŸ€β€πŸ§‘. The "domain" field of the assertion request can be used to check that the user has agreed to disclose their identity to the calling site. Because the PeerConnection supplies it, it can be trusted to be correct βœ….

9.4.4. Security of Third-Party IdPs 🌍

As discussed above, each third-party IdP is a new universal trust point, so the number of these IdPs needs to be pretty limited πŸ”’. Most IdPs, even ones that issue unqualified identities like Facebook, can be recast as authoritative IdPs (e.g., 123456@facebook.com). The catch is that the user interface implications aren't entirely desirable 😬. One middle-ground approach is to have special UI, which could be user configurable, for large authoritative IdPs. That way users can instantly tell the call is being authenticated by Facebook, Google, etc. πŸ‘‘.

9.4.4.1. Confusable Characters πŸ”€

Because a broad range of characters is permitted in identity strings, attackers may be able to craft identities that are confusable with other identities (see [RFC6943] for more on this topic) πŸ‘―. This is a problem with any identifier space of this type, like email addresses πŸ“§. Those minting identifiers should avoid mixed scripts and similar confusable characters. Those showing these identifiers to a user should consider highlighting cases of mixed script usage (see [RFC5890], Section 4.4). Other best practices are still in development πŸ› οΈ.

9.4.5. Web Security Feature Interactions 🧩

A number of optional Web security features have the potential to cause issues for this mechanism, as discussed below ⚠️.

9.4.5.1. Popup Blocking

Okay so when popup blocking is on 🚫, the IdP proxy literally can't make popup windows, dialogs, or any other kind of user interaction πŸ™…β€β™€οΈ. That's the whole point, bestie! It stops the IdP proxy from being used to sneak around user interaction πŸ›‘οΈ. The "LOGINNEEDED" message is how the IdP proxy tells the calling site "hey, the user needs to log in" ✨. The site gets the info it needs without the IdP proxy ever poking the user directly πŸ’…

9.4.5.2. Third Party Cookies

Some browsers let users block third party cookies (cookies tied to origins other than the top-level page) for privacy reasons πŸ™ˆ. Any IdP that uses cookies to keep logins alive will be broken by third-party cookie blocking πŸ’€. One option is to just accept that as a limitation 🀷. Another is to have the PeerConnection object disable third-party cookie blocking for the IdP proxy πŸ“


10. IANA Considerations πŸŽ€

This specification defines the "identity" SDP attribute per the procedures of Section 8.2.4 of [RFC4566] 🧚. Here's the registration info you need, all in one place:

Contact Name:  IESG (iesg@ietf.org)

Attribute Name:  identity

Long Form:  identity

Type of Attribute:  session

Charset Considerations:  This attribute is not subject to the charset
   attribute.

Purpose:  This attribute carries an identity assertion, binding an
   identity to the transport-level security session.

Appropriate Values:  See Section 5 of RFC 8827.

Mux Category:  NORMAL

This section also registers the "idp-proxy" well-known URI from [RFC8615] 🌈. Here's that one:

URI suffix:  idp-proxy

Change controller:  IETF

11. References πŸ“š

11.1. Normative References

[FIPS186]  National Institute of Standards and Technology (NIST),
           "Digital Signature Standard (DSS)", NIST PUB 186-4,
           DOI 10.6028/NIST.FIPS.186-4, July 2013,
           <https://doi.org/10.6028/NIST.FIPS.186-4>.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC2818]  Rescorla, E., "HTTP Over TLS", RFC 2818,
           DOI 10.17487/RFC2818, May 2000,
           <https://www.rfc-editor.org/info/rfc2818>.

[RFC3264]  Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model
           with Session Description Protocol (SDP)", RFC 3264,
           DOI 10.17487/RFC3264, June 2002,
           <https://www.rfc-editor.org/info/rfc3264>.

[RFC3711]  Baugher, M., McGrew, D., Naslund, M., Carrara, E., and K.
           Norrman, "The Secure Real-time Transport Protocol (SRTP)",
           RFC 3711, DOI 10.17487/RFC3711, March 2004,
           <https://www.rfc-editor.org/info/rfc3711>.

[RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66,
           RFC 3986, DOI 10.17487/RFC3986, January 2005,
           <https://www.rfc-editor.org/info/rfc3986>.

[RFC4566]  Handley, M., Jacobson, V., and C. Perkins, "SDP: Session
           Description Protocol", RFC 4566, DOI 10.17487/RFC4566,
           July 2006, <https://www.rfc-editor.org/info/rfc4566>.

[RFC4568]  Andreasen, F., Baugher, M., and D. Wing, "Session
           Description Protocol (SDP) Security Descriptions for Media
           Streams", RFC 4568, DOI 10.17487/RFC4568, July 2006,
           <https://www.rfc-editor.org/info/rfc4568>.

[RFC4648]  Josefsson, S., "The Base16, Base32, and Base64 Data
           Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
           <https://www.rfc-editor.org/info/rfc4648>.

[RFC5763]  Fischl, J., Tschofenig, H., and E. Rescorla, "Framework
           for Establishing a Secure Real-time Transport Protocol
           (SRTP) Security Context Using Datagram Transport Layer
           Security (DTLS)", RFC 5763, DOI 10.17487/RFC5763, May
           2010, <https://www.rfc-editor.org/info/rfc5763>.

[RFC5764]  McGrew, D. and E. Rescorla, "Datagram Transport Layer
           Security (DTLS) Extension to Establish Keys for the Secure
           Real-time Transport Protocol (SRTP)", RFC 5764,
           DOI 10.17487/RFC5764, May 2010,
           <https://www.rfc-editor.org/info/rfc5764>.

[RFC5890]  Klensin, J., "Internationalized Domain Names for
           Applications (IDNA): Definitions and Document Framework",
           RFC 5890, DOI 10.17487/RFC5890, August 2010,
           <https://www.rfc-editor.org/info/rfc5890>.

[RFC6347]  Rescorla, E. and N. Modadugu, "Datagram Transport Layer
           Security Version 1.2", RFC 6347, DOI 10.17487/RFC6347,
           January 2012, <https://www.rfc-editor.org/info/rfc6347>.

[RFC6454]  Barth, A., "The Web Origin Concept", RFC 6454,
           DOI 10.17487/RFC6454, December 2011,
           <https://www.rfc-editor.org/info/rfc6454>.

[RFC7022]  Begen, A., Perkins, C., Wing, D., and E. Rescorla,
           "Guidelines for Choosing RTP Control Protocol (RTCP)
           Canonical Names (CNAMEs)", RFC 7022, DOI 10.17487/RFC7022,
           September 2013, <https://www.rfc-editor.org/info/rfc7022>.

[RFC7675]  Perumal, M., Wing, D., Ravindranath, R., Reddy, T., and M.
           Thomson, "Session Traversal Utilities for NAT (STUN) Usage
           for Consent Freshness", RFC 7675, DOI 10.17487/RFC7675,
           October 2015, <https://www.rfc-editor.org/info/rfc7675>.

[RFC7918]  Langley, A., Modadugu, N., and B. Moeller, "Transport
           Layer Security (TLS) False Start", RFC 7918,
           DOI 10.17487/RFC7918, August 2016,
           <https://www.rfc-editor.org/info/rfc7918>.

[RFC8122]  Lennox, J. and C. Holmberg, "Connection-Oriented Media
           Transport over the Transport Layer Security (TLS) Protocol
           in the Session Description Protocol (SDP)", RFC 8122,
           DOI 10.17487/RFC8122, March 2017,
           <https://www.rfc-editor.org/info/rfc8122>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8259]  Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
           Interchange Format", STD 90, RFC 8259,
           DOI 10.17487/RFC8259, December 2017,
           <https://www.rfc-editor.org/info/rfc8259>.

[RFC8261]  Tuexen, M., Stewart, R., Jesup, R., and S. Loreto,
           "Datagram Transport Layer Security (DTLS) Encapsulation of
           SCTP Packets", RFC 8261, DOI 10.17487/RFC8261, November
           2017, <https://www.rfc-editor.org/info/rfc8261>.

[RFC8445]  Keranen, A., Holmberg, C., and J. Rosenberg, "Interactive
           Connectivity Establishment (ICE): A Protocol for Network
           Address Translator (NAT) Traversal", RFC 8445,
           DOI 10.17487/RFC8445, July 2018,
           <https://www.rfc-editor.org/info/rfc8445>.

[RFC8446]  Rescorla, E., "The Transport Layer Security (TLS) Protocol
           Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
           <https://www.rfc-editor.org/info/rfc8446>.

[RFC8615]  Nottingham, M., "Well-Known Uniform Resource Identifiers
           (URIs)", RFC 8615, DOI 10.17487/RFC8615, May 2019,
           <https://www.rfc-editor.org/info/rfc8615>.

[RFC8825]  Alvestrand, H., "Overview: Real-Time Protocols for
           Browser-Based Applications", RFC 8825,
           DOI 10.17487/RFC8825, January 2021,
           <https://www.rfc-editor.org/info/rfc8825>.

[RFC8826]  Rescorla, E., "Security Considerations for WebRTC",
           RFC 8826, DOI 10.17487/RFC8826, January 2021,
           <https://www.rfc-editor.org/info/rfc8826>.

[RFC8829]  Uberti, J., Jennings, C., and E. Rescorla, Ed.,
           "JavaScript Session Establishment Protocol (JSEP)",
           RFC 8829, DOI 10.17487/RFC8829, January 2021,
           <https://www.rfc-editor.org/info/rfc8829>.

[RFC8834]  Perkins, C., Westerlund, M., and J. Ott, "Media Transport
           and Use of RTP in WebRTC", RFC 8834, DOI 10.17487/RFC8834,
           January 2021, <https://www.rfc-editor.org/info/rfc8834>.

[RFC8844]  Thomson, M. and E. Rescorla, "Unknown Key-Share Attacks on
           Uses of TLS with the Session Description Protocol (SDP)",
           RFC 8844, DOI 10.17487/RFC8844, January 2021,
           <https://www.rfc-editor.org/info/rfc8844>.

[webcrypto]
           Watson, M., "Web Cryptography API", W3C Recommendation, 26
           January 2017,
           <https://www.w3.org/TR/2017/REC-WebCryptoAPI-20170126/>.

[webrtc-api]
           Jennings, C., BostrΓΆm, H., and J-I. Bruaroey, "WebRTC 1.0:
           Real-time Communication Between Browsers", W3C Proposed
           Recommendation, <https://www.w3.org/TR/webrtc/>.

11.2. Informative References

[fetch]    van Kesteren, A., "Fetch",
           <https://fetch.spec.whatwg.org/>.

[RFC3261]  Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston,
           A., Peterson, J., Sparks, R., Handley, M., and E.
           Schooler, "SIP: Session Initiation Protocol", RFC 3261,
           DOI 10.17487/RFC3261, June 2002,
           <https://www.rfc-editor.org/info/rfc3261>.

[RFC5705]  Rescorla, E., "Keying Material Exporters for Transport
           Layer Security (TLS)", RFC 5705, DOI 10.17487/RFC5705,
           March 2010, <https://www.rfc-editor.org/info/rfc5705>.

[RFC6120]  Saint-Andre, P., "Extensible Messaging and Presence
           Protocol (XMPP): Core", RFC 6120, DOI 10.17487/RFC6120,
           March 2011, <https://www.rfc-editor.org/info/rfc6120>.

[RFC6265]  Barth, A., "HTTP State Management Mechanism", RFC 6265,
           DOI 10.17487/RFC6265, April 2011,
           <https://www.rfc-editor.org/info/rfc6265>.

[RFC6455]  Fette, I. and A. Melnikov, "The WebSocket Protocol",
           RFC 6455, DOI 10.17487/RFC6455, December 2011,
           <https://www.rfc-editor.org/info/rfc6455>.

[RFC6943]  Thaler, D., Ed., "Issues in Identifier Comparison for
           Security Purposes", RFC 6943, DOI 10.17487/RFC6943, May
           2013, <https://www.rfc-editor.org/info/rfc6943>.

[RFC7617]  Reschke, J., "The 'Basic' HTTP Authentication Scheme",
           RFC 7617, DOI 10.17487/RFC7617, September 2015,
           <https://www.rfc-editor.org/info/rfc7617>.

[RFC8224]  Peterson, J., Jennings, C., Rescorla, E., and C. Wendt,
           "Authenticated Identity Management in the Session
           Initiation Protocol (SIP)", RFC 8224,
           DOI 10.17487/RFC8224, February 2018,
           <https://www.rfc-editor.org/info/rfc8224>.

[RFC8828]  Uberti, J. and G. Shieh, "WebRTC IP Address Handling
           Requirements", RFC 8828, DOI 10.17487/RFC8828, January
           2021, <https://www.rfc-editor.org/info/rfc8828>.

[TLS-DTLS13]
           Rescorla, E., Tschofenig, H., and N. Modadugu, "The
           Datagram Transport Layer Security (DTLS) Protocol Version
           1.3", Work in Progress, Internet-Draft, draft-ietf-tls-
           dtls13-39, 2 November 2020,
           <https://tools.ietf.org/html/draft-ietf-tls-dtls13-39>.

Acknowledgements 🫢

Huge thanks to Bernard Aboba, Harald Alvestrand, Richard Barnes, Dan Druta, Cullen Jennings, Hadriel Kaplan, Matthew Kaufman, Jim McEachern, Martin Thomson, and Magnus Westerlund πŸ’œ. Matthew Kaufman provided the UI material in Section 6.5 ✨. Christer Holmberg provided the initial version of Section 5.1 πŸ‘‘

Author's Address πŸ¦‹

Eric Rescorla
Mozilla

Email: ekr@rtfm.com
πŸ“¦ where this page comes from