{"id":27979271,"url":"https://github.com/apeleghq/ts-privacypass","last_synced_at":"2025-07-26T18:03:08.798Z","repository":{"id":172577845,"uuid":"649469129","full_name":"ApelegHQ/ts-privacypass","owner":"ApelegHQ","description":"Library for working with Private Access Tokens","archived":false,"fork":false,"pushed_at":"2023-10-06T01:25:43.000Z","size":293,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-18T11:43:00.453Z","etag":null,"topics":["authentication","captcha","captcha-alternative","privacy-access-tokens","privacypass","private-tokens"],"latest_commit_sha":null,"homepage":"https://exact.realty/blog/posts/2023/06/09/privacypass/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ApelegHQ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["Exact-Realty"]}},"created_at":"2023-06-04T23:44:31.000Z","updated_at":"2024-07-07T00:18:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"9857f7da-9868-4a83-859a-c2ed3bde1cf2","html_url":"https://github.com/ApelegHQ/ts-privacypass","commit_stats":null,"previous_names":["exact-realty/ts-privacypass","apeleghq/ts-privacypass"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ApelegHQ/ts-privacypass","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApelegHQ%2Fts-privacypass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApelegHQ%2Fts-privacypass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApelegHQ%2Fts-privacypass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApelegHQ%2Fts-privacypass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ApelegHQ","download_url":"https://codeload.github.com/ApelegHQ/ts-privacypass/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApelegHQ%2Fts-privacypass/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267205919,"owners_count":24052762,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","captcha","captcha-alternative","privacy-access-tokens","privacypass","private-tokens"],"created_at":"2025-05-08T02:51:42.072Z","updated_at":"2025-07-26T18:03:08.595Z","avatar_url":"https://github.com/ApelegHQ.png","language":"TypeScript","funding_links":["https://github.com/sponsors/Exact-Realty"],"categories":[],"sub_categories":[],"readme":"# Private Access Tokens (PATs) TypeScript Implementation\r\n\r\n [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=Exact-Realty_ts-privacypass\u0026metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=Exact-Realty_ts-privacypass)\r\n [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=Exact-Realty_ts-privacypass\u0026metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=Exact-Realty_ts-privacypass)\r\n [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=Exact-Realty_ts-privacypass\u0026metric=bugs)](https://sonarcloud.io/summary/new_code?id=Exact-Realty_ts-privacypass)\r\n [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=Exact-Realty_ts-privacypass\u0026metric=security_rating)](https://sonarcloud.io/summary/new_code?id=Exact-Realty_ts-privacypass)\r\n [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=Exact-Realty_ts-privacypass\u0026metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=Exact-Realty_ts-privacypass)\r\n ![NPM Downloads](https://img.shields.io/npm/dw/@exact-realty/privacypass?style=flat-square)\r\n\r\nThis project aims to provide a comprehensive implementation of the various\r\nPrivate Access Token (PAT) Internet Engineering Task Force (IETF) drafts in\r\nTypeScript. PATs offer a privacy-focused and efficient way to validate user\r\nauthenticity without relying on CAPTCHAs or collecting personal data.\r\n\r\n## ✨ Features\r\n\r\n- Complete implementation of the current PAT IETF drafts\r\n- Seamless integration with existing web applications and APIs\r\n- Improved user experience with no CAPTCHA challenges or data collection\r\n- Privacy-focused approach with minimal data exchange\r\n- Specifically, the following token types are currently supported:\r\n  * Token type `0x0002` (Blind RSA)\r\n  * Token type `0x5750` (Proof of Work; experimental, non-standard)\r\n- The following token type is not currently supported:\r\n  * Token type `0x0001` (VOPRF)\r\n\r\n## 📦 Installation\r\n\r\nTo use the PAT TypeScript implementation in your project, install the NPM\r\npackage:\r\n\r\n```sh\r\nnpm install \"@exact-realty/privacypass\"\r\n```\r\n\r\n## 🚀 Usage\r\n\r\n1. Import the PAT library into your project:\r\n\r\n```js\r\nimport {\r\n  produceBlindRsaWwwAuthenticateHeader,\r\n  redeemPatAuthorizationHeader,\r\n} from '@exact-realty/privacypass';\r\n```\r\n\r\n2. Use the PAT library to generate and validate tokens:\r\n\r\n```js\r\n/**\r\n * Put method for a KV store\r\n * @param {ArrayBuffer} key Key\r\n * @param {string} value Value\r\n * @returns {Promise\u003cvoid\u003e | void} Response\r\n */\r\nconst transientStorePut = (key, value) =\u003e {\r\n  // KV store\r\n  // ...\r\n};\r\n\r\n/**\r\n * Retrieve method for a KV store\r\n * @param {ArrayBuffer} key Key\r\n * @returns {Promise\u003cstring\u003e | string} Value\r\n */\r\nconst transientStoreGet = (key: ArrayBuffer) =\u003e {\r\n  // KV store\r\n  // ...\r\n};\r\n\r\n/**\r\n * Delete method for a KV store\r\n * @param {ArrayBuffer} key Key\r\n * @returns {Promise\u003cvoid\u003e | void} Response\r\n */\r\nconst transientStoreDelete = (key, value) =\u003e {\r\n  // KV store\r\n  // ...\r\n};\r\n\r\n/**\r\n * Your request handler\r\n * @param {Request} req Incoming request\r\n * @returns {Response} Response\r\n */\r\nconst requestHandler = async (req) =\u003e {\r\n  // If the request has an authorization header, validate the header and, if\r\n  // successful, return some restricted content\r\n  if (req.headers.has('authorization')) {\r\n    const redemptionResult = redeemPatAuthorizationHeader(\r\n      // REQUIRED. A string containing the HTTP authorization header\r\n      req.headers.get('authorization'),\r\n      // REQUIRED. KV-store function. Used to retrieve issued tokens.\r\n      transientStoreGet,\r\n      // REQUIRED. KV-store function. Used to remove spent tokens.\r\n      transientStoreDelete,\r\n    );\r\n\r\n    if (redemptionResult) {\r\n      // The token has been \r\n      return new Response('Hello, World!', {\r\n        headers: [['content-type', 'text/plain']],\r\n      });\r\n    }\r\n  }\r\n\r\n  // If no authorization header was present or validation failed, issue a\r\n  // challenge\r\n  const wwwAuthenticate = produceBlindRsaWwwAuthenticateHeader(\r\n    // REQUIRED. Hostname of the issuer.\r\n    // Example: 'demo-pat.issuer.cloudflare.com'\r\n    'issuer',\r\n    // REQUIRED. Hostname of your server, or empty.\r\n    // Example: 'example.com'\r\n    'origin',\r\n    // REQUIRED. KV-store function. Used to remember issued challenges and\r\n    // lookup the verification key\r\n    transientStorePut,\r\n    // OPTIONAL. Array buffer for the redemption context. If provided it must be\r\n    // an `ArrayBuffer` of length 0 or 32. Defaults to a random value.\r\n    undefined,\r\n    // OPTIONAL. `fetch` implementation to retrieve information about the\r\n    // issuer. Defaults to `fetch`.\r\n    fetch,\r\n  );\r\n\r\n  if (!wwwAuthenticate) {\r\n    throw new Error('Error producing blind RSA token');\r\n  }\r\n\r\n  return new Response(null, {\r\n    headers: [\r\n        ['www-authenticate', produceBlindRsaWwwAuthenticateHeader],\r\n    ],\r\n  });\r\n}\r\n```\r\n\r\n## 🤝 Contributing\r\n\r\nContributions are welcome and appreciated! If you would like to contribute to\r\nthis project, feel free to submit pull requests, bug reports or feature requests\r\nto our GitHub repository.\r\n\r\n## 📄 License\r\n\r\nThis project is licensed under the ISC License. For more information, please\r\nrefer to the [LICENSE](LICENSE) file.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapeleghq%2Fts-privacypass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapeleghq%2Fts-privacypass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapeleghq%2Fts-privacypass/lists"}