<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.4.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-meunier-privacypass-reverse-flow-01" category="info" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.29.0 -->
  <front>
    <title abbrev="Privacy Pass Reverse Flow">Privacy Pass Reverse Flow</title>
    <seriesInfo name="Internet-Draft" value="draft-meunier-privacypass-reverse-flow-01"/>
    <author fullname="Thibault Meunier">
      <organization>Cloudflare Inc.</organization>
      <address>
        <email>ot-ietf@thibault.uk</email>
      </address>
    </author>
    <date year="2025" month="June" day="21"/>
    <area>Security</area>
    <workgroup>Privacy Pass</workgroup>
    <abstract>
      <?line 43?>

<t>This document specifies an instantiation of Privacy Pass Architecture <xref target="RFC9576"/>
that allows for a "reverse" flow from the Origin to the Client.
It describes a method for an Origin to issue new tokens in response to a request in
which a token is redeemed.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://thibmeu.github.io/draft-meunier-privacypass-reverse-flow-informational/draft-meunier-privacypass-reverse-flow.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-meunier-privacypass-reverse-flow/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Privacy Pass Working Group mailing list (<eref target="mailto:privacy-pass@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/privacy-pass/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/privacy-pass/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/thibmeu/draft-meunier-privacypass-reverse-flow-informational"/>.</t>
    </note>
  </front>
  <middle>
    <?line 50?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>This document specifies an instantiation of Privacy Pass Architecture <xref target="RFC9576"/>
that allows for a reverse flow from the Origin to the Client.</t>
      <t>In other words, it specifies a way for an Origin to act as an Attester + Issuer.</t>
    </section>
    <section anchor="motivation">
      <name>Motivation</name>
      <t>With Privacy Pass issuance as described in <xref target="RFC9576"/>, once a token is sent by a Client,
it is considered spent and cannot be reused in order to guarantee unlinkability. If a token
were to be spent twice, the two requests would be linkable by the Origin.</t>
      <t>However, requiring that all tokens are spent only once means that Clients might need
to request more tokens for new requests, even if the request that included the original
token doesn't need to "spend" that token from the Origin's perspective (due to the
request ending up being insignificant to the Origin).
This draft provides a mechanism for an Origin to provide tokens, allowing reuse without
reaching out to the initial Attester and Issuer.</t>
      <section anchor="refunding-tokens">
        <name>Refunding tokens</name>
        <t>Certain Origin use Privacy Pass tokens to rate-limit requests they receive over a certain
time window because of resource constraints. If a Client sends a request that can
be served without utilising that resource, the Origin would like to authorise them
to do a second request. This is the case for request requiring compute and the compute is low,
or when the request leads to a redirection instead of content generation for instance.</t>
        <t>With a reverse flow,
a Client that has already been authorised by an Origin can maintain that authorization,
without losing the unlinkability property provided by Privacy Pass.</t>
      </section>
      <section anchor="bootstraping-issuer">
        <name>Bootstraping issuer</name>
        <t>An Origin wants to grant 30 access for Clients that solved a
CAPTCHA. To do so, it consumes a type 0x0002 public veriable token from an initial issuer that guarantees
a CAPTCHA has been solved,
and use it to issue 30 type 0x0001 private tokens.
Without a reverse flow, the Origin would have to require 30 0x0002 issuer tokens, which
have lower performance and a higher number of requests going to the issuer.</t>
      </section>
      <section anchor="attester-feedback-loop">
        <name>Attester feedback loop</name>
        <t>In <xref target="RFC9576"/>, a Client gets a token from an Issuer and redeems it at an Origin.
However, if the Client's request is deemed unwanted by the Origin at redemption
time, there is no mechanism that prevents the Client from going back to
the initial Issuer to get a new token and be authorized again.</t>
        <t>With a reverse flow, the initial Issuer may require Clients to present an
Origin-issued token before providing them with a second token.
This allows for a feedback loop between the Origin and the initial Issuer,
without breaking Client unlinkability.</t>
      </section>
    </section>
    <section anchor="terminology">
      <name>Terminology</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

<t>We reuse terminology from <xref target="RFC9576"/>.</t>
      <t>The following terms are used throughout this document:</t>
      <dl>
        <dt><strong>Flow:</strong></dt>
        <dd>
          <t>Direction from PrivateToken issuance to its redemption. The entity starting
the flow acts as an Issuer, while the end of the flow acts as an Origin. The
Client is always included, as it finalises the TokenResponse, and coordinate
interactions.</t>
        </dd>
        <dt><strong>Initial Flow:</strong></dt>
        <dd>
          <t>Issuer -&gt; Attester -&gt; Client -&gt; Origin. This flow produces a PrivateToken that
is used by the Origin to kickstart a Reverse Flow.</t>
        </dd>
        <dt><strong>Reverse Flow:</strong></dt>
        <dd>
          <t>Issuer &lt;- Attester &lt;- Client &lt;- Origin. This flow allows Origin to issues
PrivateToken. In the reverse flow, the Origin operates one or more Issuer, and
the Client <bcp14>MAY</bcp14> provide these tokens either to the Initial Attester/Issuer, or
use them against the Origin</t>
        </dd>
        <dt><strong>Initial Attester/Issuer:</strong></dt>
        <dd>
          <t>Attester/Issuer part of the Initial Flow</t>
        </dd>
        <dt><strong>Origin Issuer:</strong></dt>
        <dd>
          <t>Issuer operated by the Origin</t>
        </dd>
        <dt><strong>Origin PrivateToken:</strong></dt>
        <dd>
          <t>PrivateToken issued by the Origin</t>
        </dd>
        <dt><strong>Reverse Origin:</strong></dt>
        <dd>
          <t>An entity that consumes the Origin PrivateToken. It can be the Origin, or the
Initial Attester/Issuer</t>
        </dd>
      </dl>
    </section>
    <section anchor="architecture">
      <name>Architecture overview</name>
      <t>Along with sending their PrivateToken for authentication (as specified in <xref target="RFC9576"/>), Client
sends TokenRequest</t>
      <artset>
        <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="272" width="904" viewBox="0 0 904 272" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
            <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
            <path d="M 40,64 L 40,256" fill="none" stroke="black"/>
            <path d="M 136,32 L 136,64" fill="none" stroke="black"/>
            <path d="M 176,32 L 176,64" fill="none" stroke="black"/>
            <path d="M 208,64 L 208,256" fill="none" stroke="black"/>
            <path d="M 248,32 L 248,64" fill="none" stroke="black"/>
            <path d="M 568,32 L 568,64" fill="none" stroke="black"/>
            <path d="M 600,64 L 600,256" fill="none" stroke="black"/>
            <path d="M 640,32 L 640,64" fill="none" stroke="black"/>
            <path d="M 720,32 L 720,64" fill="none" stroke="black"/>
            <path d="M 760,64 L 760,144" fill="none" stroke="black"/>
            <path d="M 760,192 L 760,256" fill="none" stroke="black"/>
            <path d="M 808,32 L 808,64" fill="none" stroke="black"/>
            <path d="M 824,32 L 824,64" fill="none" stroke="black"/>
            <path d="M 856,64 L 856,256" fill="none" stroke="black"/>
            <path d="M 896,32 L 896,64" fill="none" stroke="black"/>
            <path d="M 8,32 L 136,32" fill="none" stroke="black"/>
            <path d="M 176,32 L 248,32" fill="none" stroke="black"/>
            <path d="M 568,32 L 640,32" fill="none" stroke="black"/>
            <path d="M 720,32 L 808,32" fill="none" stroke="black"/>
            <path d="M 824,32 L 896,32" fill="none" stroke="black"/>
            <path d="M 8,64 L 136,64" fill="none" stroke="black"/>
            <path d="M 176,64 L 248,64" fill="none" stroke="black"/>
            <path d="M 568,64 L 640,64" fill="none" stroke="black"/>
            <path d="M 720,64 L 808,64" fill="none" stroke="black"/>
            <path d="M 824,64 L 896,64" fill="none" stroke="black"/>
            <path d="M 216,96 L 256,96" fill="none" stroke="black"/>
            <path d="M 336,96 L 600,96" fill="none" stroke="black"/>
            <path d="M 208,112 L 224,112" fill="none" stroke="black"/>
            <path d="M 432,112 L 592,112" fill="none" stroke="black"/>
            <path d="M 608,126 L 624,126" fill="none" stroke="black"/>
            <path d="M 608,130 L 624,130" fill="none" stroke="black"/>
            <path d="M 736,126 L 752,126" fill="none" stroke="black"/>
            <path d="M 736,130 L 752,130" fill="none" stroke="black"/>
            <path d="M 600,160 L 672,160" fill="none" stroke="black"/>
            <path d="M 792,160 L 848,160" fill="none" stroke="black"/>
            <path d="M 608,176 L 672,176" fill="none" stroke="black"/>
            <path d="M 800,176 L 856,176" fill="none" stroke="black"/>
            <path d="M 216,192 L 232,192" fill="none" stroke="black"/>
            <path d="M 584,192 L 600,192" fill="none" stroke="black"/>
            <path d="M 48,208 L 64,208" fill="none" stroke="black"/>
            <path d="M 184,208 L 208,208" fill="none" stroke="black"/>
            <path d="M 40,224 L 56,224" fill="none" stroke="black"/>
            <path d="M 184,224 L 200,224" fill="none" stroke="black"/>
            <path d="M 216,240 L 232,240" fill="none" stroke="black"/>
            <path d="M 552,240 L 592,240" fill="none" stroke="black"/>
            <polygon class="arrowhead" points="856,160 844,154.4 844,165.6" fill="black" transform="rotate(0,848,160)"/>
            <polygon class="arrowhead" points="760,128 748,122.4 748,133.6" fill="black" transform="rotate(0,752,128)"/>
            <polygon class="arrowhead" points="616,176 604,170.4 604,181.6" fill="black" transform="rotate(180,608,176)"/>
            <polygon class="arrowhead" points="616,128 604,122.4 604,133.6" fill="black" transform="rotate(180,608,128)"/>
            <polygon class="arrowhead" points="600,240 588,234.4 588,245.6" fill="black" transform="rotate(0,592,240)"/>
            <polygon class="arrowhead" points="600,112 588,106.4 588,117.6" fill="black" transform="rotate(0,592,112)"/>
            <polygon class="arrowhead" points="224,192 212,186.4 212,197.6" fill="black" transform="rotate(180,216,192)"/>
            <polygon class="arrowhead" points="224,96 212,90.4 212,101.6" fill="black" transform="rotate(180,216,96)"/>
            <polygon class="arrowhead" points="208,224 196,218.4 196,229.6" fill="black" transform="rotate(0,200,224)"/>
            <polygon class="arrowhead" points="56,208 44,202.4 44,213.6" fill="black" transform="rotate(180,48,208)"/>
            <g class="text">
              <text x="44" y="52">Origin</text>
              <text x="100" y="52">Issuer</text>
              <text x="212" y="52">Origin</text>
              <text x="604" y="52">Client</text>
              <text x="764" y="52">Attester</text>
              <text x="860" y="52">Issuer</text>
              <text x="296" y="100">Request</text>
              <text x="292" y="116">TokenChallenge</text>
              <text x="388" y="116">(Issuer)</text>
              <text x="680" y="132">Attestation</text>
              <text x="732" y="164">TokenRequest</text>
              <text x="736" y="180">TokenResponse</text>
              <text x="376" y="196">Request+Token+TokenRequest(Origin</text>
              <text x="544" y="196">Issuer)</text>
              <text x="124" y="212">TokenRequest</text>
              <text x="120" y="228">TokenResponse</text>
              <text x="360" y="244">Response+TokenResponse(Origin</text>
              <text x="512" y="244">Issuer)</text>
            </g>
          </svg>
        </artwork>
        <artwork type="ascii-art"><![CDATA[
+---------------+    +--------+                                       +--------+         +----------+ +--------+
| Origin Issuer |    | Origin |                                       | Client |         | Attester | | Issuer |
+---+-----------+    +---+----+                                       +---+----+         +----+-----+ +---+----+
    |                    |                                                |                   |           |
    |                    |<----- Request ---------------------------------+                   |           |
    |                    +-- TokenChallenge (Issuer) -------------------->|                   |           |
    |                    |                                                |<== Attestation ==>|           |
    |                    |                                                |                   |           |
    |                    |                                                +--------- TokenRequest ------->|
    |                    |                                                |<-------- TokenResponse -------+
    |                    |<-- Request+Token+TokenRequest(Origin Issuer) --+                   |           |
    |<-- TokenRequest ---+                                                |                   |           |
    +-- TokenResponse -->|                                                |                   |           |
    |                    |--- Response+TokenResponse(Origin Issuer) ----->|                   |           |
    |                    |                                                |                   |           |
]]></artwork>
      </artset>
      <t>The initial flow matches the one defined by <xref target="RFC9576"/>. A Client gets challenged when
accessing a resource on an Origin. The Client goes to the Attester to get issue a Token.</t>
      <t>Through configuration mechanism not defined in this document, the Client is aware the Origin
acts as a Reverse Flow issuer.</t>
      <t>This is an extension of <xref target="RFC9576"/>. The redemption flow of a Privacy Pass token is defined in
<xref section="3.6.4" sectionFormat="of" target="RFC9576"/>. Reverse flow extends this so that redemption flow is interleaved with
the issuance flow described in <xref section="3.6.3" sectionFormat="of" target="RFC9576"/>.
This is denoted in the diagram above by the Client sending <tt>Request</tt>+<tt>Token</tt>+<tt>TokenRequest(Origin Issuer)</tt>.
The Origin runs the issuance protocol, and returns <tt>Response</tt>+<tt>TokenResponse(Origin Issuer)</tt>.</t>
      <t>Such flow can be performed through various means. This document introduces one to serve as example and
first basis.</t>
    </section>
    <section anchor="reverse-flow-with-an-http-header">
      <name>Reverse flow with an HTTP header</name>
      <t>This section defines a Reverse Flow, as presented in <xref target="architecture"/>, leveraging a new HTTP headers.</t>
      <t><tt>TokenRequest(Origin Issuer)</tt> and <tt>TokenResponse(Origin Issuer)</tt> happen through a new HTTP Header <tt>PrivacyPass-Reverse</tt>.
<tt>PrivacyPass-Reverse</tt> is a base64url (<xref target="RFC4648"/>) encoded <tt>GenericBatchTokenRequest</tt> as defined in <xref section="6" sectionFormat="of" target="BATCHED-TOKENS"/>.</t>
      <ul empty="true">
        <li>
          <t>The use of generic batch tokens as defined in <xref section="6" sectionFormat="of" target="BATCHED-TOKENS"/> is
because this already provides encoding for request and response, error wrapping, and
a concise format. One could use binary http or a new format</t>
        </li>
      </ul>
      <section anchor="client-behaviour">
        <name>Client behaviour</name>
        <t>Along with sending PrivateToken from the Initial Issuer to the Origin, the
Client sends a TokenRequest as defined in <xref target="RFC9578"/> or
<xref target="BATCHED-TOKENS"/>, and wraps them as a generic batch token request.
The Client <bcp14>SHOULD</bcp14> consider Privacy Pass Reverse Flow like the initial flow.
The Client is responsible to coordinate between the different entities.
Specifically, if the Reverse Origin is the Initial Attester/Issuer, the Client
<bcp14>SHOULD</bcp14> account for possible privacy leakage.</t>
      </section>
      <section anchor="originissuerattester-deployment">
        <name>Origin/Issuer/Attester deployment</name>
        <t>In this model, the Origin, Attester, and Issuer are all operated by the same
entity, as shown in <xref target="fig-deploy-shared"/>. The Reverse Flow is the same as
the Initial Flow, except for the request/response encapsulation.
The Origin is the Reverse Origin.</t>
        <figure anchor="fig-deploy-shared">
          <name>Shared Deployment Model</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="272" width="528" viewBox="0 0 528 272" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,48 L 8,80" fill="none" stroke="black"/>
                <path d="M 40,80 L 40,256" fill="none" stroke="black"/>
                <path d="M 80,48 L 80,80" fill="none" stroke="black"/>
                <path d="M 144,32 L 144,80" fill="none" stroke="black"/>
                <path d="M 168,48 L 168,80" fill="none" stroke="black"/>
                <path d="M 216,80 L 216,104" fill="none" stroke="black"/>
                <path d="M 216,120 L 216,160" fill="none" stroke="black"/>
                <path d="M 256,48 L 256,80" fill="none" stroke="black"/>
                <path d="M 304,48 L 304,80" fill="none" stroke="black"/>
                <path d="M 344,80 L 344,96" fill="none" stroke="black"/>
                <path d="M 344,128 L 344,192" fill="none" stroke="black"/>
                <path d="M 376,48 L 376,80" fill="none" stroke="black"/>
                <path d="M 424,48 L 424,80" fill="none" stroke="black"/>
                <path d="M 456,80 L 456,256" fill="none" stroke="black"/>
                <path d="M 496,48 L 496,80" fill="none" stroke="black"/>
                <path d="M 520,48 L 520,80" fill="none" stroke="black"/>
                <path d="M 144,32 L 504,32" fill="none" stroke="black"/>
                <path d="M 8,48 L 80,48" fill="none" stroke="black"/>
                <path d="M 168,48 L 256,48" fill="none" stroke="black"/>
                <path d="M 304,48 L 376,48" fill="none" stroke="black"/>
                <path d="M 424,48 L 496,48" fill="none" stroke="black"/>
                <path d="M 8,80 L 80,80" fill="none" stroke="black"/>
                <path d="M 168,80 L 256,80" fill="none" stroke="black"/>
                <path d="M 304,80 L 376,80" fill="none" stroke="black"/>
                <path d="M 424,80 L 496,80" fill="none" stroke="black"/>
                <path d="M 160,96 L 208,96" fill="none" stroke="black"/>
                <path d="M 224,96 L 336,96" fill="none" stroke="black"/>
                <path d="M 352,96 L 448,96" fill="none" stroke="black"/>
                <path d="M 464,96 L 504,96" fill="none" stroke="black"/>
                <path d="M 48,112 L 232,112" fill="none" stroke="black"/>
                <path d="M 440,112 L 456,112" fill="none" stroke="black"/>
                <path d="M 48,142 L 72,142" fill="none" stroke="black"/>
                <path d="M 48,146 L 72,146" fill="none" stroke="black"/>
                <path d="M 184,142 L 208,142" fill="none" stroke="black"/>
                <path d="M 184,146 L 208,146" fill="none" stroke="black"/>
                <path d="M 40,176 L 128,176" fill="none" stroke="black"/>
                <path d="M 248,176 L 336,176" fill="none" stroke="black"/>
                <path d="M 48,192 L 128,192" fill="none" stroke="black"/>
                <path d="M 256,192 L 344,192" fill="none" stroke="black"/>
                <path d="M 40,224 L 96,224" fill="none" stroke="black"/>
                <path d="M 384,224 L 448,224" fill="none" stroke="black"/>
                <path d="M 48,240 L 120,240" fill="none" stroke="black"/>
                <path d="M 368,240 L 448,240" fill="none" stroke="black"/>
                <path d="M 504,32 C 512.83064,32 520,39.16936 520,48" fill="none" stroke="black"/>
                <path d="M 160,96 C 151.16936,96 144,88.83064 144,80" fill="none" stroke="black"/>
                <path d="M 504,96 C 512.83064,96 520,88.83064 520,80" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="456,224 444,218.4 444,229.6" fill="black" transform="rotate(0,448,224)"/>
                <polygon class="arrowhead" points="344,176 332,170.4 332,181.6" fill="black" transform="rotate(0,336,176)"/>
                <polygon class="arrowhead" points="216,144 204,138.4 204,149.6" fill="black" transform="rotate(0,208,144)"/>
                <polygon class="arrowhead" points="56,240 44,234.4 44,245.6" fill="black" transform="rotate(180,48,240)"/>
                <polygon class="arrowhead" points="56,192 44,186.4 44,197.6" fill="black" transform="rotate(180,48,192)"/>
                <polygon class="arrowhead" points="56,144 44,138.4 44,149.6" fill="black" transform="rotate(180,48,144)"/>
                <polygon class="arrowhead" points="56,112 44,106.4 44,117.6" fill="black" transform="rotate(180,48,112)"/>
                <g class="text">
                  <text x="44" y="68">Client</text>
                  <text x="212" y="68">Attester</text>
                  <text x="340" y="68">Issuer</text>
                  <text x="460" y="68">Origin</text>
                  <text x="300" y="116">TokenChallenge</text>
                  <text x="396" y="116">(Issuer)</text>
                  <text x="128" y="148">Attestation</text>
                  <text x="188" y="180">TokenRequest</text>
                  <text x="192" y="196">TokenResponse</text>
                  <text x="208" y="228">Token+TokenRequest(Origin</text>
                  <text x="344" y="228">Issuer)</text>
                  <text x="212" y="244">TokenResponse(Origin</text>
                  <text x="328" y="244">Issuer)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                 +---------------------------------------------.
+--------+       |  +----------+     +--------+     +--------+  |
| Client |       |  | Attester |     | Issuer |     | Origin |  |
+---+----+       |  +-----+----+     +----+---+     +---+----+  |
    |             `-------|---------------|-------------|------'
    |<----------------------- TokenChallenge (Issuer) --+
    |                     |               |             |
    |<=== Attestation ===>|               |             |
    |                     |               |             |
    +----------- TokenRequest ----------->|             |
    |<---------- TokenResponse -----------+             |
    |                                                   |
    +------- Token+TokenRequest(Origin Issuer) -------->+
    |<--------- TokenResponse(Origin Issuer) -----------|
    |                                                   |
]]></artwork>
          </artset>
        </figure>
        <t>Similar to the original Shared Deployment Model, the Attester,
Issuer, and Origin share the attestation, issuance, and redemption
contexts. Even if this context changes between the Initial and
Reverse Flow, attestation mechanism that can uniquely identify
a Client are not appropriate as they could lead to unlinkability violations.</t>
        <ul empty="true">
          <li>
            <t>These models allow for fully private verifiability. Even though no optimised
scheme is available at the time of writting, the author recommends to follow
advances of anonymous credential within the Privacy Pass group.</t>
            <t>Specifically</t>
            <ol spacing="normal" type="1"><li>
                <t><xref target="PRIVACYPASS-ARC"/></t>
              </li>
              <li>
                <t><xref target="PRIVACYPASS-BBS"/></t>
              </li>
              <li>
                <t><xref target="ANONYMOUS-CREDIT-TOKENS"/></t>
              </li>
            </ol>
            <t>These scheme allow to mimic a reverse flow to some extent.</t>
          </li>
        </ul>
      </section>
      <section anchor="split-origin-attester-deployment">
        <name>Split Origin-Attester deployment</name>
        <t>In this model, the Attester and Issuer are operated by the same entity
that is separate from the Origin. The Origin trusts the joint Attester
and Issuer to perform attestation and issue Tokens.
Origin Tokens can then be sent by Client on new requests, as long as the
Reverse Origin trusts the Origin to perform attestation and issue Tokens.</t>
        <figure anchor="fig-deploy-joint-issuer">
          <name>Joint Attester and Issuer Deployment Model</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="272" width="920" viewBox="0 0 920 272" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,48 L 8,80" fill="none" stroke="black"/>
                <path d="M 40,80 L 40,256" fill="none" stroke="black"/>
                <path d="M 136,48 L 136,80" fill="none" stroke="black"/>
                <path d="M 176,48 L 176,80" fill="none" stroke="black"/>
                <path d="M 208,80 L 208,256" fill="none" stroke="black"/>
                <path d="M 248,48 L 248,80" fill="none" stroke="black"/>
                <path d="M 568,48 L 568,80" fill="none" stroke="black"/>
                <path d="M 600,80 L 600,256" fill="none" stroke="black"/>
                <path d="M 640,48 L 640,80" fill="none" stroke="black"/>
                <path d="M 688,32 L 688,80" fill="none" stroke="black"/>
                <path d="M 712,48 L 712,80" fill="none" stroke="black"/>
                <path d="M 760,80 L 760,144" fill="none" stroke="black"/>
                <path d="M 760,192 L 760,256" fill="none" stroke="black"/>
                <path d="M 800,48 L 800,80" fill="none" stroke="black"/>
                <path d="M 816,48 L 816,80" fill="none" stroke="black"/>
                <path d="M 856,80 L 856,256" fill="none" stroke="black"/>
                <path d="M 888,48 L 888,80" fill="none" stroke="black"/>
                <path d="M 912,48 L 912,80" fill="none" stroke="black"/>
                <path d="M 688,32 L 896,32" fill="none" stroke="black"/>
                <path d="M 8,48 L 136,48" fill="none" stroke="black"/>
                <path d="M 176,48 L 248,48" fill="none" stroke="black"/>
                <path d="M 568,48 L 640,48" fill="none" stroke="black"/>
                <path d="M 712,48 L 800,48" fill="none" stroke="black"/>
                <path d="M 816,48 L 888,48" fill="none" stroke="black"/>
                <path d="M 8,80 L 136,80" fill="none" stroke="black"/>
                <path d="M 176,80 L 248,80" fill="none" stroke="black"/>
                <path d="M 568,80 L 640,80" fill="none" stroke="black"/>
                <path d="M 712,80 L 800,80" fill="none" stroke="black"/>
                <path d="M 816,80 L 888,80" fill="none" stroke="black"/>
                <path d="M 704,96 L 752,96" fill="none" stroke="black"/>
                <path d="M 768,96 L 848,96" fill="none" stroke="black"/>
                <path d="M 864,96 L 896,96" fill="none" stroke="black"/>
                <path d="M 208,112 L 224,112" fill="none" stroke="black"/>
                <path d="M 432,112 L 592,112" fill="none" stroke="black"/>
                <path d="M 608,126 L 624,126" fill="none" stroke="black"/>
                <path d="M 608,130 L 624,130" fill="none" stroke="black"/>
                <path d="M 736,126 L 752,126" fill="none" stroke="black"/>
                <path d="M 736,130 L 752,130" fill="none" stroke="black"/>
                <path d="M 600,160 L 672,160" fill="none" stroke="black"/>
                <path d="M 792,160 L 848,160" fill="none" stroke="black"/>
                <path d="M 608,176 L 672,176" fill="none" stroke="black"/>
                <path d="M 800,176 L 856,176" fill="none" stroke="black"/>
                <path d="M 216,192 L 232,192" fill="none" stroke="black"/>
                <path d="M 584,192 L 600,192" fill="none" stroke="black"/>
                <path d="M 48,208 L 64,208" fill="none" stroke="black"/>
                <path d="M 184,208 L 208,208" fill="none" stroke="black"/>
                <path d="M 40,224 L 56,224" fill="none" stroke="black"/>
                <path d="M 184,224 L 200,224" fill="none" stroke="black"/>
                <path d="M 216,240 L 232,240" fill="none" stroke="black"/>
                <path d="M 552,240 L 592,240" fill="none" stroke="black"/>
                <path d="M 896,32 C 904.83064,32 912,39.16936 912,48" fill="none" stroke="black"/>
                <path d="M 704,96 C 695.16936,96 688,88.83064 688,80" fill="none" stroke="black"/>
                <path d="M 896,96 C 904.83064,96 912,88.83064 912,80" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="856,160 844,154.4 844,165.6" fill="black" transform="rotate(0,848,160)"/>
                <polygon class="arrowhead" points="760,128 748,122.4 748,133.6" fill="black" transform="rotate(0,752,128)"/>
                <polygon class="arrowhead" points="616,176 604,170.4 604,181.6" fill="black" transform="rotate(180,608,176)"/>
                <polygon class="arrowhead" points="616,128 604,122.4 604,133.6" fill="black" transform="rotate(180,608,128)"/>
                <polygon class="arrowhead" points="600,240 588,234.4 588,245.6" fill="black" transform="rotate(0,592,240)"/>
                <polygon class="arrowhead" points="600,112 588,106.4 588,117.6" fill="black" transform="rotate(0,592,112)"/>
                <polygon class="arrowhead" points="224,192 212,186.4 212,197.6" fill="black" transform="rotate(180,216,192)"/>
                <polygon class="arrowhead" points="208,224 196,218.4 196,229.6" fill="black" transform="rotate(0,200,224)"/>
                <polygon class="arrowhead" points="56,208 44,202.4 44,213.6" fill="black" transform="rotate(180,48,208)"/>
                <g class="text">
                  <text x="44" y="68">Origin</text>
                  <text x="100" y="68">Issuer</text>
                  <text x="212" y="68">Origin</text>
                  <text x="604" y="68">Client</text>
                  <text x="756" y="68">Attester</text>
                  <text x="852" y="68">Issuer</text>
                  <text x="292" y="116">TokenChallenge</text>
                  <text x="388" y="116">(Issuer)</text>
                  <text x="680" y="132">Attestation</text>
                  <text x="732" y="164">TokenRequest</text>
                  <text x="736" y="180">TokenResponse</text>
                  <text x="376" y="196">Request+Token+TokenRequest(Origin</text>
                  <text x="544" y="196">Issuer)</text>
                  <text x="124" y="212">TokenRequest</text>
                  <text x="120" y="228">TokenResponse</text>
                  <text x="360" y="244">Response+TokenResponse(Origin</text>
                  <text x="512" y="244">Issuer)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                                                                                     +--------------------------.
+---------------+    +--------+                                       +--------+     |  +----------+ +--------+  |
| Origin Issuer |    | Origin |                                       | Client |     |  | Attester | | Issuer |  |
+---+-----------+    +---+----+                                       +---+----+     |  +-----+----+ +----+---+  |
    |                    |                                                |           `-------|-----------|-----'
    |                    +-- TokenChallenge (Issuer) -------------------->|                   |           |
    |                    |                                                |<== Attestation ==>|           |
    |                    |                                                |                   |           |
    |                    |                                                +--------- TokenRequest ------->|
    |                    |                                                |<-------- TokenResponse -------+
    |                    |<-- Request+Token+TokenRequest(Origin Issuer) --+                   |           |
    |<-- TokenRequest ---+                                                |                   |           |
    +-- TokenResponse -->|                                                |                   |           |
    |                    |--- Response+TokenResponse(Origin Issuer) ----->|                   |           |
    |                    |                                                |                   |           |
]]></artwork>
          </artset>
        </figure>
        <t>The Origin Issuer <bcp14>MUST NOT</bcp14> issue privately verifiable tokens, as this would
lead to secret material being shared between the Origin and the Reverse Origin.</t>
        <t>A particular deployment model is when the Reverse Origin is the Attester/Issuer.
This model is described in <xref target="fig-deploy-joint-issuer-reserve"/></t>
        <figure anchor="fig-deploy-joint-issuer-reserve">
          <name>Joint Attester and Issuer Deployment Model with reverse</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="288" width="920" viewBox="0 0 920 288" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,48 L 8,80" fill="none" stroke="black"/>
                <path d="M 40,80 L 40,272" fill="none" stroke="black"/>
                <path d="M 136,48 L 136,80" fill="none" stroke="black"/>
                <path d="M 176,48 L 176,80" fill="none" stroke="black"/>
                <path d="M 208,80 L 208,272" fill="none" stroke="black"/>
                <path d="M 248,48 L 248,80" fill="none" stroke="black"/>
                <path d="M 568,48 L 568,80" fill="none" stroke="black"/>
                <path d="M 600,80 L 600,272" fill="none" stroke="black"/>
                <path d="M 640,48 L 640,80" fill="none" stroke="black"/>
                <path d="M 688,32 L 688,80" fill="none" stroke="black"/>
                <path d="M 712,48 L 712,80" fill="none" stroke="black"/>
                <path d="M 760,80 L 760,144" fill="none" stroke="black"/>
                <path d="M 760,192 L 760,248" fill="none" stroke="black"/>
                <path d="M 800,48 L 800,80" fill="none" stroke="black"/>
                <path d="M 816,48 L 816,80" fill="none" stroke="black"/>
                <path d="M 856,80 L 856,272" fill="none" stroke="black"/>
                <path d="M 888,48 L 888,80" fill="none" stroke="black"/>
                <path d="M 912,48 L 912,80" fill="none" stroke="black"/>
                <path d="M 688,32 L 896,32" fill="none" stroke="black"/>
                <path d="M 8,48 L 136,48" fill="none" stroke="black"/>
                <path d="M 176,48 L 248,48" fill="none" stroke="black"/>
                <path d="M 568,48 L 640,48" fill="none" stroke="black"/>
                <path d="M 712,48 L 800,48" fill="none" stroke="black"/>
                <path d="M 816,48 L 888,48" fill="none" stroke="black"/>
                <path d="M 8,80 L 136,80" fill="none" stroke="black"/>
                <path d="M 176,80 L 248,80" fill="none" stroke="black"/>
                <path d="M 568,80 L 640,80" fill="none" stroke="black"/>
                <path d="M 712,80 L 800,80" fill="none" stroke="black"/>
                <path d="M 816,80 L 888,80" fill="none" stroke="black"/>
                <path d="M 704,96 L 752,96" fill="none" stroke="black"/>
                <path d="M 768,96 L 848,96" fill="none" stroke="black"/>
                <path d="M 864,96 L 896,96" fill="none" stroke="black"/>
                <path d="M 208,112 L 224,112" fill="none" stroke="black"/>
                <path d="M 432,112 L 592,112" fill="none" stroke="black"/>
                <path d="M 608,126 L 624,126" fill="none" stroke="black"/>
                <path d="M 608,130 L 624,130" fill="none" stroke="black"/>
                <path d="M 736,126 L 752,126" fill="none" stroke="black"/>
                <path d="M 736,130 L 752,130" fill="none" stroke="black"/>
                <path d="M 600,160 L 672,160" fill="none" stroke="black"/>
                <path d="M 792,160 L 848,160" fill="none" stroke="black"/>
                <path d="M 608,176 L 672,176" fill="none" stroke="black"/>
                <path d="M 800,176 L 856,176" fill="none" stroke="black"/>
                <path d="M 216,192 L 232,192" fill="none" stroke="black"/>
                <path d="M 584,192 L 600,192" fill="none" stroke="black"/>
                <path d="M 48,208 L 64,208" fill="none" stroke="black"/>
                <path d="M 184,208 L 208,208" fill="none" stroke="black"/>
                <path d="M 40,224 L 56,224" fill="none" stroke="black"/>
                <path d="M 184,224 L 200,224" fill="none" stroke="black"/>
                <path d="M 216,240 L 232,240" fill="none" stroke="black"/>
                <path d="M 552,240 L 592,240" fill="none" stroke="black"/>
                <path d="M 600,256 L 696,256" fill="none" stroke="black"/>
                <path d="M 760,256 L 848,256" fill="none" stroke="black"/>
                <path d="M 896,32 C 904.83064,32 912,39.16936 912,48" fill="none" stroke="black"/>
                <path d="M 704,96 C 695.16936,96 688,88.83064 688,80" fill="none" stroke="black"/>
                <path d="M 896,96 C 904.83064,96 912,88.83064 912,80" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="856,256 844,250.4 844,261.6" fill="black" transform="rotate(0,848,256)"/>
                <polygon class="arrowhead" points="856,160 844,154.4 844,165.6" fill="black" transform="rotate(0,848,160)"/>
                <polygon class="arrowhead" points="760,128 748,122.4 748,133.6" fill="black" transform="rotate(0,752,128)"/>
                <polygon class="arrowhead" points="616,176 604,170.4 604,181.6" fill="black" transform="rotate(180,608,176)"/>
                <polygon class="arrowhead" points="616,128 604,122.4 604,133.6" fill="black" transform="rotate(180,608,128)"/>
                <polygon class="arrowhead" points="600,240 588,234.4 588,245.6" fill="black" transform="rotate(0,592,240)"/>
                <polygon class="arrowhead" points="600,112 588,106.4 588,117.6" fill="black" transform="rotate(0,592,112)"/>
                <polygon class="arrowhead" points="224,192 212,186.4 212,197.6" fill="black" transform="rotate(180,216,192)"/>
                <polygon class="arrowhead" points="208,224 196,218.4 196,229.6" fill="black" transform="rotate(0,200,224)"/>
                <polygon class="arrowhead" points="56,208 44,202.4 44,213.6" fill="black" transform="rotate(180,48,208)"/>
                <g class="text">
                  <text x="44" y="68">Origin</text>
                  <text x="100" y="68">Issuer</text>
                  <text x="212" y="68">Origin</text>
                  <text x="604" y="68">Client</text>
                  <text x="756" y="68">Attester</text>
                  <text x="852" y="68">Issuer</text>
                  <text x="292" y="116">TokenChallenge</text>
                  <text x="388" y="116">(Issuer)</text>
                  <text x="680" y="132">Attestation</text>
                  <text x="732" y="164">TokenRequest</text>
                  <text x="736" y="180">TokenResponse</text>
                  <text x="376" y="196">Request+Token+TokenRequest(Origin</text>
                  <text x="544" y="196">Issuer)</text>
                  <text x="124" y="212">TokenRequest</text>
                  <text x="120" y="228">TokenResponse</text>
                  <text x="360" y="244">Response+TokenResponse(Origin</text>
                  <text x="512" y="244">Issuer)</text>
                  <text x="728" y="260">Token</text>
                  <text x="760" y="276">|</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                                                                                     +--------------------------.
+---------------+    +--------+                                       +--------+     |  +----------+ +--------+  |
| Origin Issuer |    | Origin |                                       | Client |     |  | Attester | | Issuer |  |
+---+-----------+    +---+----+                                       +---+----+     |  +-----+----+ +----+---+  |
    |                    |                                                |           `-------|-----------|-----'
    |                    +-- TokenChallenge (Issuer) -------------------->|                   |           |
    |                    |                                                |<== Attestation ==>|           |
    |                    |                                                |                   |           |
    |                    |                                                +--------- TokenRequest ------->|
    |                    |                                                |<-------- TokenResponse -------+
    |                    |<-- Request+Token+TokenRequest(Origin Issuer) --+                   |           |
    |<-- TokenRequest ---+                                                |                   |           |
    +-- TokenResponse -->|                                                |                   |           |
    |                    |--- Response+TokenResponse(Origin Issuer) ----->|                   |           |
    |                    |                                                +------------ Token ----------->|
    |                    |                                                |                   |           |
]]></artwork>
          </artset>
        </figure>
        <t>This deployment <bcp14>SHOULD</bcp14> not allow the Reverse Origin to infer the request made
to the Origin, as it would break unlinkability.</t>
      </section>
    </section>
    <section anchor="privacy-considerations">
      <name>Privacy Considerations</name>
      <t>Privacy Pass <xref target="RFC9576"/> states</t>
      <ul empty="true">
        <li>
          <t>In general, limiting the amount of metadata permitted helps limit the extent
to which metadata can uniquely identify individual Clients. Failure to bound the
number of possible metadata values can therefore lead to a reduction in Client
privacy. Most token types do not admit any metadata, so this bound is implicitly
enforced.</t>
        </li>
      </ul>
      <t>In Privacy Pass with a reverse flow, Clients are provided with new PrivateTokens
depending on their request. They can spend these tokens to continue making further
requests.</t>
      <t>While the token are still unlinkable, the token_key_id associated to them
represent metadata. It leaks some information about the Client. The following
subsections discuss the issues that influence the anonymity set, and possible
mitigations/safeguards to protect against this underlying problem.</t>
      <section anchor="issuer-face-values">
        <name>Issuer face values</name>
        <t>When setting up a reverse flow deployment, an Origin <bcp14>MAY</bcp14> operate multiple
Issuers, and assign them some metadata to them. The amount of possible metadata
grows as 2^(origin_issuers).</t>
        <t>We RECOMMEND that:</t>
        <ol spacing="normal" type="1"><li>
            <t>Origin defines their anonimity sets, and deploy no more than
log2(#anonimity_sets). This bounds the possible anonimity sets by design.</t>
          </li>
          <li>
            <t>Client to only send 1 PrivateToken per request. This is inline with RFC9577
and RFC (Web Authentication) which only allows one challenge response to be
provided as part of Authorization HTTP header.</t>
          </li>
          <li>
            <t>Issuers metadata to be publicly disclosed via an origin endpoint, and
externally monitored</t>
          </li>
        </ol>
      </section>
      <section anchor="token-for-specific-clients">
        <name>Token for specific Clients</name>
        <t>In Privacy Pass with a reverse flow, an Origin <bcp14>MAY</bcp14> operate multiple Issuers,
with arbitrary metadata associated to them. A malicious Origin <bcp14>MAY</bcp14> uses this
opportunity to associate certain token values to a specific set of Clients.</t>
        <t>Let's consider the following deployment: the Origin operates two issuers A and
B. The Client sends Token_A, and (TokenRequest_A, TokenRequest_B). Issuer B is
associated to croissant aficionados.</t>
        <t>If a Client requests croissant, or sends Token_B, the origin provides
TokenResponse_B. If not, it provides TokenResponse_A.</t>
        <t>Over time, this means the Origin is able to track croissants aficionados.</t>
        <t>To mitigate this, we RECOMMEND:</t>
        <ol spacing="normal" type="1"><li>
            <t>The initial PrivateToken to be provided by an Issuer not in control of the
Origin. The joint Origin/Attester/Issuer model <bcp14>SHOULD NOT</bcp14> be used.</t>
          </li>
          <li>
            <t>Clients to reset their state regularly with the initial Issuer.</t>
          </li>
        </ol>
      </section>
      <section anchor="sending-more-than-one-token">
        <name>Sending more than one token</name>
        <t>While that's not part of Privacy Pass with a reverse flow, some deployment might
consider allowing Clients to send multiple PrivateToken, similar to how normal
Privacy Pass deployment allow two distinct PrivateToken to be sent.</t>
        <t>In Privacy Pass with a reverse flow deployment, there are as many bits as
Issuers; each token is one bit. We RECOMMEND to have a maximum of 6 Origin
operated Issuers, bounding Client information to 2^6 = 64. Accounting for the
initial Issuer, this means a total of log2(64)+1=7 issuers.</t>
        <t>Origin should have sufficient traffic to not single-out particular Client based
on timings of requests.</t>
      </section>
      <section anchor="swap-endpoint-and-its-privacy-implication">
        <name>Swap endpoint and its privacy implication</name>
        <t>With multiple Issuers, a Client <bcp14>MAY</bcp14> end up with a bunch of tokens, for various
Issuers. Origins <bcp14>MAY</bcp14> propose a swap endpoint at which a Client can exchange one
or more Origin tokens against one or more new Origin tokens.</t>
        <t>The Origin <bcp14>SHOULD</bcp14> ensure this endpoint receives enough traffic to not reduce the
anonymity sets.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="BATCHED-TOKENS">
          <front>
            <title>Batched Token Issuance Protocol</title>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Thibault Meunier" initials="T." surname="Meunier">
              <organization>Cloudflare Inc.</organization>
            </author>
            <date day="2" month="February" year="2025"/>
            <abstract>
              <t>   This document specifies a variant of the Privacy Pass issuance
   protocol that allows for batched issuance of tokens.  This allows
   clients to request more than one token at a time and for issuers to
   issue more than one token at a time.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-privacypass-batched-tokens-04"/>
        </reference>
        <reference anchor="RFC4648">
          <front>
            <title>The Base16, Base32, and Base64 Data Encodings</title>
            <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
            <date month="October" year="2006"/>
            <abstract>
              <t>This document describes the commonly used base 64, base 32, and base 16 encoding schemes. It also discusses the use of line-feeds in encoded data, use of padding in encoded data, use of non-alphabet characters in encoded data, use of different encoding alphabets, and canonical encodings. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="4648"/>
          <seriesInfo name="DOI" value="10.17487/RFC4648"/>
        </reference>
        <reference anchor="RFC9576">
          <front>
            <title>The Privacy Pass Architecture</title>
            <author fullname="A. Davidson" initials="A." surname="Davidson"/>
            <author fullname="J. Iyengar" initials="J." surname="Iyengar"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="June" year="2024"/>
            <abstract>
              <t>This document specifies the Privacy Pass architecture and requirements for its constituent protocols used for authorization based on privacy-preserving authentication mechanisms. It describes the conceptual model of Privacy Pass and its protocols, its security and privacy goals, practical deployment models, and recommendations for each deployment model, to help ensure that the desired security and privacy goals are fulfilled.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9576"/>
          <seriesInfo name="DOI" value="10.17487/RFC9576"/>
        </reference>
        <reference anchor="RFC9578">
          <front>
            <title>Privacy Pass Issuance Protocols</title>
            <author fullname="S. Celi" initials="S." surname="Celi"/>
            <author fullname="A. Davidson" initials="A." surname="Davidson"/>
            <author fullname="S. Valdez" initials="S." surname="Valdez"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="June" year="2024"/>
            <abstract>
              <t>This document specifies two variants of the two-message issuance protocol for Privacy Pass tokens: one that produces tokens that are privately verifiable using the Issuer Private Key and one that produces tokens that are publicly verifiable using the Issuer Public Key. Instances of "issuance protocol" and "issuance protocols" in the text of this document are used interchangeably to refer to the two variants of the Privacy Pass issuance protocol.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9578"/>
          <seriesInfo name="DOI" value="10.17487/RFC9578"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="ANONYMOUS-CREDIT-TOKENS" target="https://samuelschlesinger.github.io/ietf-anonymous-credit-tokens/draft-schlesinger-cfrg-act.html">
          <front>
            <title>Anonymous Credit Tokens</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="PRIVACYPASS-ARC">
          <front>
            <title>Privacy Pass Issuance Protocol for Anonymous Rate-Limited Credentials</title>
            <author fullname="Cathie Yun" initials="C." surname="Yun">
              <organization>Apple, Inc.</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Apple, Inc.</organization>
            </author>
            <date day="5" month="February" year="2025"/>
            <abstract>
              <t>   This document specifies the issuance and redemption protocols for
   tokens based on the Anonymous Rate-Limited Credential (ARC) protocol.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-yun-privacypass-arc-00"/>
        </reference>
        <reference anchor="PRIVACYPASS-BBS">
          <front>
            <title>BBS for PrivacyPass</title>
            <author fullname="Watson Ladd" initials="W." surname="Ladd">
              <organization>Akamai Technologies</organization>
            </author>
            <date day="26" month="February" year="2024"/>
            <abstract>
              <t>   Existing token types in privacy pass conflate attribution with rate
   limiting.  This document describes a token type where the issuer
   attests to a set of properties of the client, which the client can
   then selectively prove to the origin.  Repeated showings of the same
   credential are unlinkable, unlike other token types in privacy pass.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ladd-privacypass-bbs-01"/>
        </reference>
        <reference anchor="RFC9110">
          <front>
            <title>HTTP Semantics</title>
            <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
            <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
            <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
            <date month="June" year="2022"/>
            <abstract>
              <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document describes the overall architecture of HTTP, establishes common terminology, and defines aspects of the protocol that are shared by all versions. In this definition are core protocol elements, extensibility mechanisms, and the "http" and "https" Uniform Resource Identifier (URI) schemes.</t>
              <t>This document updates RFC 3864 and obsoletes RFCs 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, and portions of 7230.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="97"/>
          <seriesInfo name="RFC" value="9110"/>
          <seriesInfo name="DOI" value="10.17487/RFC9110"/>
        </reference>
      </references>
    </references>
    <?line 405?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The author would like to thank Tommy Pauly, Chris Wood, Raphael Robert, and Armando Faz Hernandez
for helpful discussion on Privacy Pass architecture and its considerations.</t>
    </section>
    <section numbered="false" anchor="changelog">
      <name>Changelog</name>
      <t>v01</t>
      <ul spacing="normal">
        <li>
          <t>Editorial pass on the introduction</t>
        </li>
        <li>
          <t>Add a motivation section: refunding tokens, bootstraping issuer, attester feeback loop</t>
        </li>
        <li>
          <t>Split protocol overview via HTTP headers in its own section</t>
        </li>
        <li>
          <t>Add consideration about anonymous credentials in joint origin/issuer deployment</t>
        </li>
      </ul>
      <t>v00</t>
      <ul spacing="normal">
        <li>
          <t>Initial draft</t>
        </li>
        <li>
          <t>Possibility of a new HTTP request for inlining request</t>
        </li>
        <li>
          <t>Privacy considerations about additional metadata</t>
        </li>
      </ul>
    </section>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
