WICG / trust-token-api

Trust Token API
https://wicg.github.io/trust-token-api/
Other
415 stars 82 forks source link

This API does not need to be coupled to Fetch #221

Open martinthomson opened 1 year ago

martinthomson commented 1 year ago

The fetch integration in the specification is very complicated. It also appears to be unnecessary.

Imagine an API like this:

interface PrivateStateToken {
  // Initiate token issuance.
  Promise<PstChallenge> issue(optional PstChallengeOptions = {});
  // Attempt to redeem a token.
  Promise<ArrayBuffer> redeem(DOMString issuer, optional PstRedemptionOptions = {});
};
interface PstChallenge {
  // An accessor for the set of challenges that the browser provides.
  sequence<ArrayBuffer> blindedNonces;
  // Fulfill the challenges, or a prefix subset of them.
  Promise<undefined> fulfill(sequence<BufferSource> blindedTokens, optional PstIssuanceOptions = {});
};

I've omitted the definition of options and some additional fields, which might include issuance protocol choice, expiration times, and other less significant details.

A site could then call PrivateStateToken.challenge() to request that the browser generate a challenge, which is a set of blinded nonces in some of the instantiations of the protocol. It would then receive a challenge in response. This could contain multiple challenges (blinded nonces) to allow for batching. The site then does whatever it needs to do to fulfill those challenges. This would normally involve contacting a server, but the details do not matter much here. Calling PstChallenge.fulfill() would have the browser validate and store the tokens that are provided.

Redemption involves asking for a token, identifying the issuer by its origin. This can reject if there are too many issuers, if there are insufficient tokens, or whatever.

Obviously, the current design is more fully featured (or, to be fair, it contains more of what is needed to be a viable design). Including attributes for signaling the type of token, expiration times, and other important characteristics is trivial and so I've omitted those.

yoavweiss commented 1 year ago

I'm seeing some parallels here with the PendingBeacon proposal, which based on feedback, is now moving in the opposite direction: from a dedicated API to a fetch() based one.

It'd be good to decide on an underlying design principle: when should new APIs extend fetch() and when should they create a dedicated surface?

martinthomson commented 1 year ago

Beacons are necessarily tied to fetch, because that is what they do. That is not true here because, at its core, this is an API for accessing browser storage.

The only reason I can think of that might want explicit fetch decoration is if you wanted some sort of declarative API that you could use for frames or images so that the appropriate headers can be added in cases where you don't have access to script or access to script is unwieldy. That's a real possibility here, as this API is used for serving ads and ad serving is monstrously complex with tons of constraints on operation. But I want to say that fetch integration needs to be an option of last resort that is only used when a strong case is made for it. And only used for those places where it is necessary (as it might be for redemption). Even then, that integration should be build on top of platform primitives that can be expressed in terms of an API.

yoavweiss commented 1 year ago

That is not true here because, at its core, this is an API for accessing browser storage.

Can you elaborate on that? The PrivacyPass protocol is by its nature a network protocol, isn't it?

martinthomson commented 1 year ago

A Privacy Pass Client does need to talk to Attesters, Issuers, and Origins, definitely. So yes, there is networking involved, because those roles can't be played by a single entity, by design.

But my central point is that this is not inherently bound to fetch. The protocol operates at a higher layer and could equally use WebTransport, forms, or any of the other mechanisms we use for that part.

The key part of this proposal is how it allows one site to create in-browser state that can be queried by other sites in a very limited fashion. An Origin site[^1] can request a token that has been deposited by an Issuer/Attester site. In that way, the key component of the feature is how the two sites interact with this new form of storage that the browser provides to sites. It is not about the details of how each site accesses resources or obtains the information that is being stored.

[^1]: Yes this is an odd use of terminology. When using Privacy Pass nomenclature, I use Origin in title case to refer to the Privacy Pass role, not a general Web origin.