@authcube/pst
Version:
Typescript library implementing Private State Token API (https://wicg.github.io/trust-token-api/)
153 lines (110 loc) • 4.67 kB
Markdown
Typescript library implementing Private State Token API (https://wicg.github.io/trust-token-api/)
This library depends on [Cloudflare's voprf-ts](https://github.com/cloudflare/voprf-ts) tested implementation to compute the Scalars and transformations.
# Security Disclaimer
🚨 This library is offered as-is, and without a guarantee. Therefore, it is expected that changes in the code, repository, and API occur in the future. We recommend to take caution before using this library in a production application since part of its content is experimental. All security issues must be reported, please notify us immediately.
## Install Dependencies and Build
```
npm install
npm run build
```
## Sample Issuer
> Sample has been built using Express Library
- Start Sample Server
```
npm run example
```
- Running with Docker
- build
```
docker-compose build
```
- start
```
docker-compose up
```
#### Running with Static Key-Pair and Expiration
- Generate up to 6 KeyPairs
```
node bin/voprf_gen_keys.cjs 1
node bin/voprf_gen_keys.cjs 2
# Keep creating until node bin/voprf_gen_keys.cjs 6
```
- Export Keys as Environment Variables
```
export PRIVATE_KEY1=<BASE64 PRIVATE KEY 1 GENERATED PREVIOUSLY>
export PUBLIC_KEY1=<BASE64 PUBLIC KEY 1 GENERATED PREVIOUSLY>
export PRIVATE_KEY2=<BASE64 PRIVATE KEY 2 GENERATED PREVIOUSLY>
export PUBLIC_KEY2=<BASE64 PUBLIC KEY 2 GENERATED PREVIOUSLY>
```
- Export Key Expiration as Environment Variable
```
export EXPIRY1=1709509052048
export EXPIRY2=1709994102048
```
> If running with **Docker** define those variables in docker-compose.yaml or -e argument for docker inline
- Key Commitment Endpoint
```
curl http://localhost:3000/.well-known/trust-token/key-commitment
```
- [Google Privacy Sandbox - Private State Tokens](https://developers.google.com/privacy-sandbox/protections/private-state-tokens)
- [Private State Tokens API Spec](https://wicg.github.io/trust-token-api/)
- [Privacy Pass Issuance Protocol Spec](https://www.ietf.org/archive/id/draft-ietf-privacypass-protocol-10.html)
- [Oblivious Pseudorandom Functions (OPRFs) Spec](https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-21.html)
- [Batched Tokens Issuance Protocol Spec](https://www.ietf.org/archive/id/draft-robert-privacypass-batched-tokens-01.html)
- [CloudFlare - Privacy Pass TypeScript Library](https://github.com/cloudflare/privacypass-ts/)
- [CloudFlare - VOPRF TypeScript Library](https://github.com/cloudflare/voprf-ts)
## How to use this library
### Token Issuance
To issue a token, you must check for the request header `sec-private-state-token`, after verify it is present and it is not null or empty you can use the Issuer class like the code bellow:
```typescript
import { PSTRedeemer, PSTResources } from "@authcube/pst";
const sec_private_state_token = req.headers[
"sec-private-state-token"
] as string;
if (sec_private_state_token && !sec_private_state_token.match(BASE64FORMAT)) {
return res.sendStatus(400);
}
try {
let issuer = await PSTResources.getIssuer();
const token = await issuer.issueToken(sec_private_state_token);
res.statusCode = 200;
res.setHeader("Content-Type", "text/html");
res.append("sec-private-state-token", token);
res.setHeader("Sec-Private-State-Token", token);
res.write("Issuing tokens.");
res.send();
return res.end();
} catch (e: any) {
// deal with the error as you see fit
console.error("Error issuing PST", e);
return res.sendStatus(500);
}
```
To redeem an issued token the process is similar, your endpoint must check for the request header `sec-private-state-token`, if it is present and it is not null or empty you can proceed to the redeemption
```typescript
import { PSTRedeemer, PSTResources } from "@authcube/pst";
try {
const redemptionToken = req.headers["sec-private-state-token"] as string;
if (redemptionToken && !redemptionToken.match(BASE64FORMAT)) {
return res.sendStatus(400);
}
const redeemer = new PSTRedeemer();
// This call will throw an Error if the token is invalid
const resToken = await redeemer.redeemToken(redemptionToken);
res.statusCode = 200;
res.setHeader("Access-Control-Allow-Origin", "*");
res.append("sec-private-state-token", resToken);
res.write("Token redeemed.");
return res.send();
} catch (e) {
// deal with the error as you see fit
console.error(`Error on redemption: ${e}`);
return res.sendStatus(400);
}
```