Internet-Draft mocha-identity July 2026
Jennings & Nandakumar Expires 7 January 2027 [Page]
Workgroup:
Media Over QUIC
Internet-Draft:
draft-jennings-moq-mocha-identity-00
Published:
Intended Status:
Standards Track
Expires:
Authors:
C. Jennings
Cisco
S. Nandakumar
Cisco

MOCHA Identity: Authentication, Authorization, and Federation

Abstract

This document specifies identity, authentication, authorization, and federation for MOCHA (MoQ Open Communication & Hosting Architecture). It defines how users authenticate with Identity Providers (IdPs), how authorization tokens (C4M and Privacy Pass) are issued and validated at relays, how permissions map to MOQT namespaces, and how users from one Provider obtain access to resources on a federated Provider.

About This Document

This note is to be removed before publishing as an RFC.

Status information for this document may be found at https://datatracker.ietf.org/doc/draft-jennings-moq-mocha-identity/.

Discussion of this document takes place on the Media Over QUIC Working Group mailing list (mailto:moq@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/moq/. Subscribe at https://www.ietf.org/mailman/listinfo/moq/.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 7 January 2027.

Table of Contents

1. Introduction

MOCHA requires participants to prove their identity and obtain authorization before publishing or subscribing to tracks on MOQT relays. This document specifies the identity and authorization architecture, covering:

2. Conventions and Definitions

See BCP 14 [RFC2119] [RFC8174].

This document uses terminology defined in [MOCHA-ARCH], including Provider, Organization, Team, Channel, Device, and DevID.

The following identifiers are defined in this document:

HClientID:

A hashed client identifier derived via HMAC. Used in namespace tuples and track names instead of the raw clientID. See Section 10.

HDevID:

A hashed device identifier derived via HMAC. Used in track names instead of the raw devID. See Section 10.

The following additional terms are used:

Identity Provider (IdP):

A service that authenticates users and asserts their identity. Examples include OIDC-compliant providers, enterprise SSO, and self-hosted identity services. The IdP answers "who is this user?"

Provider Token Service:

The MOCHA component that validates identity assertions from IdPs, determines user permissions, and issues access tokens (C4M) for relay access.

Access Tokens: A C4M (CAT for MOQT) CWT (CBOR Web Token) that encodes a user's identity and MOQT namespace permissions. Defined in [C4M]. When used in Mocha, the token includes a DPoP confirmation claim (cnf) binding it to the client's key.

ID Token: : An OIDC (OpenID Connect) token that provides the authenticated identity of the user.

DPoP (Demonstrating Proof of Possession):

A mechanism that binds a C4M token to the client's asymmetric key pair. The client generates a fresh DPoP proof for each MOQT action, preventing token theft and replay. See Section 5.2.

Authorization Parameter:

The MOQT parameter that carries authentication credentials. It can appear in CLIENT_SETUP, SUBSCRIBE, SUBSCRIBE_NAMESPACE, PUBLISH, PUBLISH_NAMESPACE, and FETCH messages.

Relay:

Validates access tokens and enforces access control for MOQT operations. Relays do not authenticate users directly; they trust tokens signed by known issuers.

3. Architecture Overview

The client does a normal OpenID SSO login flow to authenticate to the Provider Token Service to get an ID Token and an Access Token with DPoP.

For each Org at the Provider, the Provider keeps tracks of: * all of the users in the Org * for each users in its Org, all of their devices * all the teams in its Org, * for each team, all of users (in the Org or other Providers/Orgs) and their roles, * for each team, all of its channels, * for each of the channels, its users (in this Org or other Providers/Orgs) and their roles, * for each of the channels, all of the meetings

TODO: Add support for federation

The Provider Token Service takes an ID Token and generates Access Token(s) with the required scopes for Relays for all the Mocha services. The Provider Token Service coordiates with the CDNs providing the Relays so the relays can validate the Access Tokens.

The exact scopes needed for Access Tokens are defined in the specifications that define the Mocha service.

Clients use the Access Tokens when sending requests to the Relays.

A Client that is acting as User on a different provider can also ask for Access Tokens for this resources in this Provider. This allows federated actions where a Client on Provider A can participated in meetings or channels that are owned by an Org on Provier B.

                   MOCHA Identity Architecture

  +----------+                                    +----------+
  |   IdP    |  (OIDC, Enterprise SSO, etc.)      | PP-Issuer|
  +----+-----+                                    +----+-----+
       |                                               |
       | ID Token                          blind sign  |
       v                                               v
  +----+-----+     (2) AUTHORIZATION param     +------+------+
  |  Client  |  -----------------------------> |    Relay    |
  | (Device) |   (C4M + DPoP )                 | (Validates) |
  +----+-----+                                 +------+------+
       |                                               |
       | (1) authenticate + request token              |
       v                                               |
  +----+-----------------------------------------+     |
  |            Token Service                     |     |
  |  - Validates IdP assertions                  |     |
  |  - Checks membership/permissions             |     |
  |  - Mints C4M tokens with DPoP binding        |     |
  |  - Proxies PP blind token requests           |     |
  +----------------------------------------------+     |
                                                       |
            (3) SUBSCRIBE / PUBLISH granted            |
            <------------------------------------------+
Figure 1: Identity Architecture

4. Identity Provider Authentication

4.1. Overview

Before obtaining authorization tokens, a user must authenticate with an Identity Provider. MOCHA supports pluggable IdPs. The Token Service validates the IdP assertion and establishes a session.

4.2. OIDC Authentication

  Client                   IdP (OIDC)             Token Service
    |                          |                        |
    |  (1) OAuth/OIDC flow     |                        |
    |  (browser redirect or    |                        |
    |   native sign-in)        |                        |
    |------------------------->|                        |
    |                          |                        |
    |  (2) ID Token (JWT)      |                        |
    |<-------------------------|                        |
    |                          |                        |
    |  (3) POST /auth/oidc     |                        |
    |      Authorization: Bearer <ID Token>             |
    |-------------------------------------------------->|
    |                          |                        |
    |                          |  (4) Verify signature  |
    |                          |      via JWKS fetch    |
    |                          |<-----------------------|
    |                          |----------------------->|
    |                          |                        |
    |                          |  (5) Validate claims:  |
    |                          |      iss, aud, exp,    |
    |                          |      email_verified    |
    |                          |                        |
    |  (6) 200 OK                                      |
    |      { user_id, session_token }                  |
    |<--------------------------------------------------|
    |                          |                        |
Figure 2: OIDC Authentication Flow

The Token Service MUST validate the ID Token per [OIDC] Section 3.1.3.7 (issuer, audience, expiry, signature via JWKS).

4.3. Guest Authentication

For deployments allowing pseudonymous access:

  Client                             Token Service
    |                                      |
    |  POST /auth/guest                    |
    |  { "display_name": "Alice" }         |
    |------------------------------------->|
    |                                      |
    |  200 OK                              |
    |  { "user_id": "guest-7a3f",          |
    |    "session_token": "s_..." }        |
    |<-------------------------------------|
    |                                      |
Figure 3: Guest Authentication

Guest users receive a server-assigned pseudonymous identity. Guest sessions MAY have reduced permissions compared to authenticated users.

5. C4M Token Issuance and Validation

5.1. Overview

C4M (CAT for MOQT) [C4M] is the primary authorization mechanism for identified access. MOCHA deployments MUST use DPoP (Demonstrating Proof of Possession) to bind C4M tokens to the client's key pair, preventing token theft and replay.

Token format and CWT claims (Section 2), DPoP claims and proof generation (Section 3.1), and DPoP proof process and token binding flow (Section 3.2) from [C4M] MUST be used for MOCHA authorization.

5.2. Token Request

After authentication, the client requests a C4M token scoped to a specific channel and role. The client provides its public key for DPoP binding. The Token Service validates the session, checks membership, determines role permissions, and mints a C4M token with a cnf claim binding it to the client's key.

The complete HTTP issuance flow is specified in Section 9.1.

The Token Service maps the user's role and channel membership to moq_scopes within the C4M token. The scopes use the MOCHA namespace hierarchy:

  moq_scopes: {
    publish: ["mocha/<provider>/<org>/<team>/<channel>/participant/*"],
    subscribe: ["mocha/<provider>/<org>/<team>/<channel>/*"]
  }

5.3. Scope Enforcement

Scope enforcement follows the positional namespace matching rules defined in [C4M], Section 2.1. The relay evaluates each namespace field against the corresponding match object in the token's moqt claim. Actions not explicitly permitted by the token are denied by default.

For example, a MOCHA participant token might encode scopes that permit publishing under their device prefix within a channel, while allowing subscription to all tracks in that channel:

  Token scope (publish): mocha/provider.example/acme/eng/general/
                         participant/<device-id>/...
  Token scope (subscribe): mocha/provider.example/acme/eng/general/...

  PUBLISH request:  mocha/provider.example/acme/eng/general/
                    participant/device-a3f2/messages/live
  Result: PERMITTED (matches publish scope)

  SUBSCRIBE request: mocha/provider.example/acme/eng/general/
                     moderator/device-b1c4/messages/live
  Result: PERMITTED (matches subscribe scope)

6. Privacy Pass Token Issuance and Validation

6.1. Overview

Privacy Pass [PrivacyPassAuth] provides cryptographic unlinkability: the relay can verify a token was legitimately issued without correlating it to the identity that requested it. This enables anonymous participation in channels. Illustrative call flows are provided in Appendix A.

For scoped access, Partially Blind RSA tokens carry public metadata encoding the permitted MOCHA namespaces without breaking unlinkability. The relay uses these extensions for scope enforcement identical to C4M tokens, but cannot determine which user holds the token.

6.2. MOCHA Token Issuance

Token types, issuance protocol, attester authentication, and token wire format are defined in [PrivacyPassAuth]. The Token Service acts as Attester ([PrivacyPassAuth], Section 3) and authenticates to the PP-Issuer using HTTP Message Signatures [RFC9421].

In the MOCHA context, the Token Service:

  1. Validates the client's session and channel membership (as in the C4M flow).

  2. Determines the namespace scope to encode in the token's public metadata (for PBRS tokens).

  3. Attests to the PP-Issuer that the client is authorized for the requested scope.

The client presents the resulting token in the AUTHORIZATION parameter of any MOQT control message (CLIENT_SETUP, SUBSCRIBE, PUBLISH, etc.).

6.3. Reverse Flow

MOCHA deployments MAY use the Privacy Pass reverse flow [PP-REVERSE] where the relay acts as both attester and issuer. The client bootstraps with a publicly verifiable token from an external issuer, and the relay responds with privately verifiable tokens for subsequent operations.

The reverse flow enables continuous unlinkable authorization without requiring an external issuer after the initial bootstrap. Token replenishment is piggybacked on normal MOQT control message exchanges using batched tokens [PP-BATCH]. The bootstrap, continuous authorization, and batch token encoding are defined in [PrivacyPassAuth] (Sections 4-5) and [PP-REVERSE] (Section 4).

7. Roles and Token Scopes

Roles (Owner, Moderator, Participant, Observer) are defined in [MOCHA-ARCH] and assigned at the Organization, Team, and Channel levels. The permissions associated with each role (publish, subscribe, moderation, management) are application policy specified in [MOCHA-ARCH].

This document defines how the Token Service translates a user's role into C4M token scopes. When a user requests a token, the Token Service determines their role for the target channel and encodes the corresponding namespace permissions:

  User: alice@provider.example
  Team: acme/eng
  Channel: general
  Role: participant

  Resulting C4M scopes:
    publish:   ["mocha/provider.example/acme/eng/general/participant/*"]
    subscribe: ["mocha/provider.example/acme/eng/general/*"]

  User: bob@provider.example
  Role: moderator

  Resulting C4M scopes:
    publish:   ["mocha/provider.example/acme/eng/general/moderator/*",
                "mocha/provider.example/acme/eng/general/moderation/*"]
    subscribe: ["mocha/provider.example/acme/eng/general/*"]

The scope patterns follow the MOCHA namespace hierarchy and are enforced by the relay per [C4M], Section 2.1. The same scopes apply when using Privacy Pass with PBRS tokens — the namespace permissions are encoded in the token's public metadata extensions (see [PrivacyPassAuth]) and enforced identically by the relay.

8. Federation

Federation allows a user authenticated with one Provider to participate in Teams and Channels hosted by a different Provider. The home Provider vouches for the user's identity via a signed assertion, and the remote Provider issues a locally-valid C4M token after verifying trust and applying its federation policies.

8.1. Federation Model

  +------------------+                    +------------------+
  | Provider A       |                    | Provider B       |
  | (home)           |                    | (remote)         |
  |                  |    Federation      |                  |
  | Token Service A  |<------------------>| Token Service B  |
  | Relay A          |    Trust           | Relay B          |
  | Users: Alice     |                    | Users: Bob       |
  +------------------+                    +------------------+

  Alice (home: A) wants to join a Channel on Provider B.
Figure 4: Federated Providers

8.2. Federation Establishment

Providers establish federation trust via mutual discovery and key exchange:

  Provider A                                Provider B
      |                                          |
      | (1) GET /.well-known/mocha-federation    |
      |----------------------------------------->|
      |                                          |
      | (2) { realm, federation_relays,          |
      |       signing_key, policies }            |
      |<-----------------------------------------|
      |                                          |
      | (3) Verify signing_key via DNSSEC/TLS    |
      |                                          |
      | (4) Store Provider B's public key        |
      |     in trusted federation peers          |
      |                                          |
      | (5) Provider B does same for A           |
      |<---------------------------------------->|
      |                                          |
Figure 5: Federation Establishment

The well-known document:

GET https://provider-b.example/.well-known/mocha-federation

{
  "realm": "provider-b.example",
  "federation_relays": ["moqt://relay.provider-b.example:443"],
  "signing_key": "<Ed25519 public key, base64>",
  "token_exchange_endpoint": "https://auth.provider-b.example/federation/exchange",
  "policies": {
    "allow_inbound": true,
    "allowed_providers": ["*"],
    "blocked_providers": []
  }
}

8.3. Federated Token Exchange

When Alice (Provider A) wants to access a Channel on Provider B, a token exchange occurs:

  Alice        Token Service A       Token Service B        Relay B
    |                |                      |                  |
    | (1) Request    |                      |                  |
    |  federated     |                      |                  |
    |  access to     |                      |                  |
    |  provider-b/   |                      |                  |
    |  org/team/ch   |                      |                  |
    |--------------->|                      |                  |
    |                |                      |                  |
    |                | (2) Create signed    |                  |
    |                |  federation assertion|                  |
    |                |  (Ed25519):          |                  |
    |                |  { sub, home_realm,  |                  |
    |                |    target, roles,    |                  |
    |                |    exp }             |                  |
    |                |                      |                  |
    |                | (3) POST /federation/exchange           |
    |                |   { assertion, requested_scope }        |
    |                |--------------------->|                  |
    |                |                      |                  |
    |                |       (4) Verify assertion signature    |
    |                |           against Provider A's          |
    |                |           known public key              |
    |                |                      |                  |
    |                |       (5) Check federation policies:    |
    |                |           - Provider A allowed?         |
    |                |           - Target channel permits      |
    |                |             remote users?               |
    |                |           - Role mapping valid?         |
    |                |                      |                  |
    |                |       (6) Mint C4M token with           |
    |                |           Provider B's signing key      |
    |                |                      |                  |
    |                | (7) { token: <C4M>, expires_at }        |
    |                |<--------------------|                  |
    |                |                      |                  |
    | (8) Federated  |                      |                  |
    |  C4M token     |                      |                  |
    |<---------------|                      |                  |
    |                |                      |                  |
    | (9) CLIENT_SETUP { AUTHORIZATION: <C4M from B> }        |
    |-------------------------------------------------------->|
    |                |                      |                  |
    |                |                      |  (10) Validate   |
    |                |                      |  with B's key    |
    |                |                      |                  |
    | (11) SERVER_SETUP                                       |
    |<--------------------------------------------------------|
    |                |                      |                  |
Figure 6: Federated Token Exchange

The home Provider creates an Ed25519-signed assertion containing the user's identity (issuer, subject), the target Provider and namespace, the user's home roles, a validity window (issued-at and expiry), and a fresh nonce to prevent replay. The assertion is scoped to the remote Provider via an audience claim.

The remote Provider validates the signature against the home Provider's known public key, checks the assertion has not expired, and maps the home roles to local permissions according to its federation policy. The remote Provider MAY downgrade roles (e.g., a home "moderator" becomes a remote "participant").

9. Token Service

The Token Service is the MOCHA component responsible for minting, refreshing, and revoking C4M access tokens.

The Token Service interacts with other components via two mechanisms:

HTTP API:

Clients call the Token Service HTTP endpoint to mint initial C4M tokens (before a MOQT session exists). See Section 9.1.

MOQT Tracks:

The Token Service publishes on MOQT tracks that relays and clients subscribe to:

  • Per-client refresh track: delivers rotated tokens to each client. See Section 9.2.

  • Revocation track: notifies relays and clients of revoked tokens. See Section 9.3.

9.1. HTTP Token Issuance

Before establishing a MOQT session, a client obtains a C4M token from the Token Service via its HTTP API. The client presents its session credentials (obtained after IdP authentication per Section 4) along with its DPoP public key:

  Client                              Token Service
    |                                       |
    |  POST /token                          |
    |  Authorization: Bearer <session_token>|
    |  {                                    |
    |    "org_id": "acme",                  |
    |    "team_id": "engineering",          |
    |    "channel_id": "general",           |
    |    "role": "participant",             |
    |    "dpop_jwk": { <client public key> }|
    |  }                                    |
    |-------------------------------------->|
    |                                       |
    |  (1) Validate session                 |
    |  (2) Check membership and role        |
    |  (3) Mint C4M token with DPoP binding |
    |                                       |
    |  200 OK                               |
    |  { "token": "<base64 CWT>",           |
    |    "expires_at": 1749903600 }         |
    |<--------------------------------------|
    |                                       |
Figure 7: HTTP Token Issuance

The Token Service maps the user's role and channel membership to moq_scopes within the C4M token per Section 7.

9.2. Token Refresh

C4M tokens are intentionally short-lived. To maintain continuous access without requiring the client to re-authenticate via the IdP, MOCHA provides in-session token refresh over MOQT.

Once a MOQT session is active, the client subscribes to a per-user token refresh track. The Token Service proactively publishes a new token before the current one expires:

  Client                Relay              Token Service
    |                     |                      |
    | SUBSCRIBE           |                      |
    | mocha/<provider>/   |                      |
    |   tokens/<user_id>  |                      |
    |-------------------->|                      |
    |                     |--------------------->|
    |                     |                      |
    |                     |      (token nearing  |
    |                     |       expiry)        |
    |                     |                      |
    |                     |  OBJECT: new token   |
    |                     |<---------------------|
    |  new token          |                      |
    |<--------------------|                      |
    |                     |                      |
Figure 8: In-Session Token Refresh

The Token Service SHOULD publish the refreshed token at approximately 75% of the current token's lifetime, providing an overlap window where both the old and new tokens are valid.

9.3. Token Revocation

For immediate access removal (e.g., user banned, role changed, device compromised), the Token Service publishes revocation objects to a dedicated revocation track. Both relays and clients subscribe to this track.

9.3.1. Revocation Track

  Namespace: mocha/<provider>/tokens
  Track: revocations

9.3.2. Revocation Object Format

Each revocation object carries the SHA-256 hash of the revoked token, enabling relays and clients to identify the specific token without exposing its contents:

{
  "token_hash": "<SHA-256 hash of the revoked C4M token>",
  "revoked_at": 1749901500,
  "reason": "role_change",
  "affected_scopes": [
    "mocha/provider.example/acme/eng/private/*"
  ]
}

9.3.3. Revocation Fields

token_hash (REQUIRED):

SHA-256 hash of the C4M token being revoked, hex-encoded. Relays and clients match this against hashes of tokens they hold or have validated.

revoked_at (REQUIRED):

Revocation time in seconds since Unix epoch.

reason (OPTIONAL):

Human-readable reason for the revocation (e.g., "role_change", "ban", "device_compromised").

affected_scopes (OPTIONAL):

List of namespace scope patterns affected by this revocation, for informational purposes.

9.3.4. Relay Enforcement

Relays MUST subscribe to the revocation track of each Token Service whose tokens they accept. Upon receiving a revocation object, the relay:

  1. Computes the SHA-256 hash of each active token it has validated for the affected session(s).

  2. If a match is found, immediately terminates any SUBSCRIBE or PUBLISH operations authorized by that token.

  3. Caches the token_hash for the remainder of the token's original validity period to reject any late-arriving requests using the revoked token.

9.3.5. Client Behavior

Clients SHOULD also subscribe to the revocation track. Upon receiving a revocation matching a token they hold, clients MUST stop using that token and request a new one via HTTP (Section 9.1) or await a refresh on their token track.

  Token Service          Relay              Client
    |                     |                   |
    |  PUBLISH revocation |                   |
    |  (token_hash=0xab..) |                  |
    |-------------------->|                   |
    |                     |                   |
    |                     | (match found:     |
    |                     |  terminate session)|
    |                     |                   |
    |                     | OBJECT: revocation|
    |                     |------------------>|
    |                     |                   |
    |                     |                   | (stop using
    |                     |                   |  revoked token,
    |                     |                   |  request new one)
    |                     |                   |
Figure 9: Token Revocation Flow

10. Identifier Derivation

Both the HClientID and HDevID used in namespace tuples and track names are derived using HMAC with a shared secret K between the client and the provider. The clientID is the identifier for the client participant obtained out of band, and "||" denotes concatenation.

The shared secret K is established during the authentication flow (Section 4) and is unique per client-provider pair.

The HClientID is computed as:

  HClientID = HMAC(K, <namespace-tuple-without-HClientID> ||
                  clientID)

The HDevID is computed as:

  HDevID = HMAC(K, <namespace-tuple-with-HClientID> || devID)

where devID is the device identifier used as the device identity in the MoQ track. The devID MAY be the hash of the client's public key used for DPoP binding (Section 5.2), providing a stable per-device identifier tied to the cryptographic material.

These derived identifiers ensure that:

11. Service Discovery

TODO

12. Security Considerations

TODO

13. IANA Considerations

This document makes no requests of IANA.

14. Normative References

[C4M]
Law, W., Lemmons, C., Simon, G., and S. Nandakumar, "Authorization scheme for MOQT using Common Access Tokens", Work in Progress, Internet-Draft, draft-ietf-moq-c4m-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-c4m-01>.
[MOCHA-ARCH]
"*** BROKEN REFERENCE ***".
[MoQTransport]
Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell, "Media over QUIC Transport", Work in Progress, Internet-Draft, draft-ietf-moq-transport-18, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-18>.
[OIDC]
"OpenID Connect Core 1.0", , <https://openid.net/specs/openid-connect-core-1_0.html>.
[PP-BATCH]
Robert, R., Wood, C. A., and T. Meunier, "Batched Token Issuance Protocol", Work in Progress, Internet-Draft, draft-ietf-privacypass-batched-tokens-08, , <https://datatracker.ietf.org/doc/html/draft-ietf-privacypass-batched-tokens-08>.
[PP-REVERSE]
Meunier, T., "Privacy Pass Reverse Flow", Work in Progress, Internet-Draft, draft-meunier-privacypass-reverse-flow-05, , <https://datatracker.ietf.org/doc/html/draft-meunier-privacypass-reverse-flow-05>.
[PrivacyPassAuth]
Nandakumar, S., Jennings, C. F., and T. Meunier, "Privacy Pass Authentication for Media over QUIC (MoQ)", Work in Progress, Internet-Draft, draft-ietf-moq-privacy-pass-auth-02, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-privacy-pass-auth-02>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[RFC8392]
Jones, M., Wahlstroem, E., Erdtman, S., and H. Tschofenig, "CBOR Web Token (CWT)", RFC 8392, DOI 10.17487/RFC8392, , <https://www.rfc-editor.org/rfc/rfc8392>.
[RFC9421]
Backman, A., Ed., Richer, J., Ed., and M. Sporny, "HTTP Message Signatures", RFC 9421, DOI 10.17487/RFC9421, , <https://www.rfc-editor.org/rfc/rfc9421>.

Appendix A. Privacy Pass Call Flows

This appendix illustrates the Privacy Pass flows for MOCHA. The normative protocol is defined in [PrivacyPassAuth] and [PP-REVERSE].

A.1. External Issuer Flow

The client authenticates with the IdP, then obtains a Privacy Pass token via the Token Service (Attester) and external PP-Issuer, and finally presents it to the relay.

  Client          IdP        Token Service       PP-Issuer       Relay
    |              |          (Attester)              |              |
    |              |               |                  |              |
    | (1) Authenticate             |                  |              |
    |------------->|               |                  |              |
    |              |               |                  |              |
    | (2) ID Token |               |                  |              |
    |<-------------|               |                  |              |
    |              |               |                  |              |
    | (3) POST /auth/oidc          |                  |              |
    |   { ID Token }               |                  |              |
    |----------------------------->|                  |              |
    |              |               |                  |              |
    | (4) session_token            |                  |              |
    |<-----------------------------|                  |              |
    |              |               |                  |              |
    | (5) POST /auth/privacypass/challenge            |              |
    |   { room_id, token_type }    |                  |              |
    |----------------------------->|                  |              |
    |              |               |                  |              |
    |              |               | (6) Fetch issuer |              |
    |              |               |     public key   |              |
    |              |               |----------------->|              |
    |              |               |<-----------------|              |
    |              |               |                  |              |
    | (7) TokenChallenge +         |                  |              |
    |     issuer_pub_key           |                  |              |
    |<-----------------------------|                  |              |
    |              |               |                  |              |
    | (8) Generate nonce,          |                  |              |
    |     blind token_input        |                  |              |
    |              |               |                  |              |
    | (9) POST /auth/privacypass/token-request        |              |
    |   { blinded_element }        |                  |              |
    |----------------------------->|                  |              |
    |              |               |                  |              |
    |              |               | (10) Forward     |              |
    |              |               |   + HTTP sig     |              |
    |              |               |----------------->|              |
    |              |               |                  |              |
    |              |               |  (11) Verify     |              |
    |              |               |  attester sig,   |              |
    |              |               |  sign token      |              |
    |              |               |                  |              |
    |              |               | (12) blind_sig   |              |
    |              |               |<-----------------|              |
    |              |               |                  |              |
    | (13) blind_signature         |                  |              |
    |<-----------------------------|                  |              |
    |              |               |                  |              |
    | (14) Unblind, assemble       |                  |              |
    |      final token             |                  |              |
    |              |               |                  |              |
    | (15) CLIENT_SETUP { AUTHORIZATION: token }                    |
    |-------------------------------------------------------------->|
    |              |               |                  |              |
    |              |               |                  | (16) Verify  |
    |              |               |                  | with issuer  |
    |              |               |                  | public key   |
    |              |               |                  |              |
    | (17) SERVER_SETUP (identity unknown to relay)                 |
    |<--------------------------------------------------------------|
    |              |               |                  |              |
Figure 10: Privacy Pass External Issuer Flow

A.2. Reverse Flow

The reverse flow has three phases: bootstrap, session establishment, and continuous authorization with token replenishment.

A.2.1. Step 1: Bootstrap

The client connects without credentials. The relay challenges the client, who obtains a publicly verifiable token from an external issuer.

  Client              PP-Issuer (external)          Relay
    |                      |                          |
    | (1) CLIENT_SETUP (no auth)                      |
    |------------------------------------------------>|
    |                      |                          |
    | (2) UNAUTHORIZED { TokenChallenge }             |
    |<------------------------------------------------|
    |                      |                          |
    | (3) Blind token      |                          |
    |   request            |                          |
    |--------------------->|                          |
    |                      |                          |
    | (4) blind_signature  |                          |
    |<---------------------|                          |
    |                      |                          |
    | (5) Unblind, assemble publicly                  |
    |     verifiable token (type 0x0002)              |
    |                      |                          |
Figure 11: Reverse Flow Step 1: Bootstrap

A.2.2. Step 2: Token Exchange

The client presents the bootstrap token and requests a batch of privately verifiable tokens from the relay (now acting as issuer).

  Client                                    Relay (Issuer)
    |                                         |
    | (1) CLIENT_SETUP {                      |
    |       AUTHORIZATION: Token (0x0002),    |
    |       GenericBatchTokenRequest           |
    |     }                                   |
    |---------------------------------------->|
    |                                         |
    |     (2) Validate bootstrap token        |
    |     (3) Issue privately verifiable      |
    |         tokens (type 0x0001/0x0005)     |
    |                                         |
    | (4) SERVER_SETUP {                      |
    |       GenericBatchTokenResponse          |
    |     }                                   |
    |<----------------------------------------|
    |                                         |
Figure 12: Reverse Flow Step 2: Token Exchange

A.2.3. Step 3: Continuous Authorization

On each subsequent operation, the client presents a privately verifiable token and piggybacks a new batch request. The relay validates and replenishes tokens.

  Client                                    Relay
    |                                         |
    | (1) SUBSCRIBE {                         |
    |       AUTHORIZATION: PrivateTokenAuth,  |
    |       GenericBatchTokenRequest           |
    |     }                                   |
    |---------------------------------------->|
    |                                         |
    |     (2) Validate private token          |
    |     (3) Issue new batch of tokens       |
    |                                         |
    | (4) GenericBatchTokenResponse            |
    |<----------------------------------------|
    |                                         |
    | (5) PUBLISH {                           |
    |       AUTHORIZATION: PrivateTokenAuth,  |
    |       GenericBatchTokenRequest           |
    |     }                                   |
    |---------------------------------------->|
    |                                         |
    |     (6) Validate, issue new batch       |
    |                                         |
    | (7) GenericBatchTokenResponse            |
    |<----------------------------------------|
    |                                         |
    |     (continues for session lifetime)    |
    |                                         |
Figure 13: Reverse Flow Step 3: Continuous Authorization

Authors' Addresses

Cullen Jennings
Cisco
Suhas Nandakumar
Cisco