{"id":26758460,"url":"https://github.com/alessiofrittoli/crypto-jwt","last_synced_at":"2025-09-11T11:38:49.426Z","repository":{"id":283833542,"uuid":"903441991","full_name":"alessiofrittoli/crypto-jwt","owner":"alessiofrittoli","description":"Lightweight TypeScript JSON Web Tokens library","archived":false,"fork":false,"pushed_at":"2025-06-12T12:08:37.000Z","size":219,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-08T13:32:38.497Z","etag":null,"topics":["json-web-token","jwt"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@alessiofrittoli/crypto-jwt","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alessiofrittoli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"license.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["alessiofrittoli"]}},"created_at":"2024-12-14T16:04:54.000Z","updated_at":"2025-05-03T15:27:40.000Z","dependencies_parsed_at":"2025-04-15T05:28:01.822Z","dependency_job_id":"e8f8cb1e-caba-4db6-ad23-6f9271bd47b9","html_url":"https://github.com/alessiofrittoli/crypto-jwt","commit_stats":null,"previous_names":["alessiofrittoli/crypto-jwt"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/alessiofrittoli/crypto-jwt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-jwt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-jwt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-jwt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-jwt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alessiofrittoli","download_url":"https://codeload.github.com/alessiofrittoli/crypto-jwt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-jwt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274626935,"owners_count":25320305,"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-09-11T02:00:13.660Z","response_time":74,"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":["json-web-token","jwt"],"created_at":"2025-03-28T16:20:10.765Z","updated_at":"2025-09-11T11:38:49.361Z","avatar_url":"https://github.com/alessiofrittoli.png","language":"TypeScript","funding_links":["https://github.com/sponsors/alessiofrittoli"],"categories":[],"sub_categories":[],"readme":"# Crypto JSON Web Token 🔗\n\n[![NPM Latest Version][version-badge]][npm-url] [![Coverage Status][coverage-badge]][coverage-url] [![Socket Status][socket-badge]][socket-url] [![NPM Monthly Downloads][downloads-badge]][npm-url] [![Dependencies][deps-badge]][deps-url]\n\n[![GitHub Sponsor][sponsor-badge]][sponsor-url]\n\n[version-badge]: https://img.shields.io/npm/v/%40alessiofrittoli%2Fcrypto-jwt\n[npm-url]: https://npmjs.org/package/%40alessiofrittoli%2Fcrypto-jwt\n[coverage-badge]: https://coveralls.io/repos/github/alessiofrittoli/crypto-jwt/badge.svg\n[coverage-url]: https://coveralls.io/github/alessiofrittoli/crypto-jwt\n[socket-badge]: https://socket.dev/api/badge/npm/package/@alessiofrittoli/crypto-jwt\n[socket-url]: https://socket.dev/npm/package/@alessiofrittoli/crypto-jwt/overview\n[downloads-badge]: https://img.shields.io/npm/dm/%40alessiofrittoli%2Fcrypto-jwt.svg\n[deps-badge]: https://img.shields.io/librariesio/release/npm/%40alessiofrittoli%2Fcrypto-jwt\n[deps-url]: https://libraries.io/npm/%40alessiofrittoli%2Fcrypto-jwt\n\n[sponsor-badge]: https://img.shields.io/static/v1?label=Fund%20this%20package\u0026message=%E2%9D%A4\u0026logo=GitHub\u0026color=%23DB61A2\n[sponsor-url]: https://github.com/sponsors/alessiofrittoli\n\n## Lightweight TypeScript JSON Web Tokens library\n\nJSON Web Tokens are an open, industry standard [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) method for representing claims securely between two parties.\n\nKeep in mind that JSON Web Tokens can be easly decoded and they should **never** contains sensible informations!\n\nJSON Web Tokens should be only used to store reference data (e.g. user ID). The token get then signed with the given \"payload\" and signature is verified to ensure the token hasn't been modified by third parties.\n\n- Read more informations abot at [RFC 7519 - Internet Engineering Task Force (IETF)](https://datatracker.ietf.org/doc/html/rfc7519).\n\n### Table of Contents\n\n- [Getting started](#getting-started)\n- [Supported Algorithms](#supported-algorithms)\n- [Jwt Class API Reference](#jwt-class-api-reference)\n  - [Constructor](#constructor)\n  - [Properties](#properties)\n  - [Methods](#methods)\n  - [Example usage](#example-usage)\n  - [Expiration](#expiration)\n  - [Not before](#not-before)\n  - [Type casting](#type-casting)\n- [Error handling](#error-handling)\n- [Development](#development)\n  - [ESLint](#eslint)\n  - [Jest](#jest)\n- [Contributing](#contributing)\n- [Security](#security)\n- [Credits](#made-with-)\n\n---\n\n### Getting started\n\nRun the following command to start using `crypto-jwt` in your projects:\n\n```bash\nnpm i @alessiofrittoli/crypto-jwt\n```\n\nor using `pnpm`\n\n```bash\npnpm i @alessiofrittoli/crypto-jwt\n```\n\n---\n\n### Supported Algorithms\n\nThe `Jwt` class supports different algorithms. You will find detailed informations in this documentation on how to use them so you can choose the best fit for you needs.\n\nIf no algorithm is specified, `HS256` is being used.\n\n⚠️ Keep in mind that:\n\n- you will need different key types based on the signing algorithm being used.\n- usage of symmetric keys is insecure. Using asymmetric keys is recommended.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eSupported algorithms\u003c/summary\u003e\n\n| Type         | JWK name | Description                                                              |\n|--------------|----------|--------------------------------------------------------------------------|\n| `none`       |          | No signing process is performed.                                         |\n| `HMAC`       |          |                                                                          |\n|              | `HS1`    | Token signature generated/verified with `HMAC` key and `SHA-1`.          |\n|              | `HS256`  | Token signature generated/verified with `HMAC` key and `SHA-256`.        |\n|              | `HS384`  | Token signature generated/verified with `HMAC` key and `SHA-384`.        |\n|              | `HS512`  | Token signature generated/verified with `HMAC` key and `SHA-512`.        |\n| `DSA`        |          |                                                                          |\n|              | `DS1`    | Token signature generated/verified with `DSA` keys and `SHA-1`.          |\n|              | `DS256`  | Token signature generated/verified with `DSA` keys and `SHA-256`.        |\n|              | `DS384`  | Token signature generated/verified with `DSA` keys and `SHA-384`.        |\n|              | `DS512`  | Token signature generated/verified with `DSA` keys and `SHA-512`.        |\n| `EcDSA`      |          |                                                                          |\n|              | `ES256`  | Token signature generated/verified with `EC` keys and `SHA-256`.         |\n|              | `ES384`  | Token signature generated/verified with `EC` keys and `SHA-384`.         |\n|              | `ES512`  | Token signature generated/verified with `EC` keys and `SHA-512`.         |\n| `EdDSA`      |          |                                                                          |\n|              | `EdDSA`  | Token signature generated/verified with `ed448` keys.                    |\n|              | `EdDSA`  | Token signature generated/verified with `ed25519` keys.                  |\n| `RSA`        |          |                                                                          |\n|              | `RS1`    | Token signature generated/verified with `RSA` keys and `SHA-1`.          |\n|              | `RS256`  | Token signature generated/verified with `RSA` keys and `SHA-256`.        |\n|              | `RS384`  | Token signature generated/verified with `RSA` keys and `SHA-384`.        |\n|              | `RS512`  | Token signature generated/verified with `RSA` keys and `SHA-512`.        |\n| `RSASSA-PSS` |          |                                                                          |\n|              | `PS256`  | Token signature generated/verified with `RSASSA-PSS` keys and `SHA-256`. |\n|              | `PS384`  | Token signature generated/verified with `RSASSA-PSS` keys and `SHA-384`. |\n|              | `PS512`  | Token signature generated/verified with `RSASSA-PSS` keys and `SHA-512`. |\n\n\u003c/details\u003e\n\n---\n\n### Jwt Class API Reference\n\n#### Constructor\n\nThe `Jwt` class constructor accepts an `object` argument with the following properties:\n\n\u003cdetails\u003e\n\n\u003csummary\u003eCommon properties\u003c/summary\u003e\n\n| Property | Type   | Default | Description |\n|----------|--------|---------|-------------|\n| `name` | `string` | `\"JWT\"` | (Optional) The token name. This is used in error messages and is intended for debugging purposes only. |\n| `header` | `JsonWebToken.Header` | - | (Optional) The JOSE Header. |\n|          |        |         |             |\n| `header.alg` | `JsonWebToken.Algorithm` | `HS256` | Message authentication code algorithm. |\n| `header.cty` | `string` | - | (Optional) Content type - If nested signing or encryption is employed, it is recommended to set this to JWT; otherwise, omit this field. |\n| `header.kid`  | `string` | - | (Optional) Key ID - A hint indicating which key the client used to generate the token signature. The server will match this value to a key on file in order to verify that the signature is valid and the token is authentic. |\n| `header.crit` | `string[]` | - | (Optional) Critical - A list of headers that must be understood by the server in order to accept the token as valid. |\n| `header.x5c` | `string \\| string[]` | - | ⚠️ x.509 Certificate Chain - A certificate chain in RFC4945 format corresponding to the private key used to generate the token signature. The server will use this information to verify that the signature is valid and the token is authentic. - not supported yet. |\n| `header.x5u` | `string \\| string[]` | - | ⚠️ x.509 Certificate Chain URL - A URL where the server can retrieve a certificate chain corresponding to the private key used to generate the token signature. The server will retrieve and use this information to verify that the signature is authentic. - not supported yet. |\n| `header.x5t` | `string` | - | - |\n| `header.jku` | `string` | - | - |\n| `header['x5t#S256']` | `string` | - | - |\n|          |        |         |             |\n| `iat` | `string \\| numbet \\| Date` | current timestamp | (Optional) The token issuing Date time value in milliseconds past unix epoch, a Date string or a Date instance on which the JWT has been issued. |\n| `exp` | `string \\| numbet \\| Date` | - | (Optional) The token expiration Date time value in milliseconds past unix epoch, a Date string or a Date instance on and after which the JWT it's not accepted for processing. |\n| `nbf` | `string \\| numbet \\| Date` | - | (Optional) The token Date time value in milliseconds past unix epoch, a Date string or a Date instance on which the JWT will start to be accepted for processing. |\n| `jti` | `string` | - | (Optional) JWT ID - Case-sensitive unique identifier of the token even among different issuers. |\n| `iss` | `string` | - | (Optional) Issuer - Identifies principal that issued the JWT. |\n| `sub` | `string` | - | (Optional) Subject - Identifies the subject of the JWT. |\n| `aud` | `string` | - | (Optional) Audience - Identifies the recipients that the JWT is intended for. Each principal intended to process the JWT must identify itself with a value in the audience claim. |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eSigning properties\u003c/summary\u003e\n\n| Property | Type | Description                                                 |\n|----------|------|-------------------------------------------------------------|\n| `data`   | `T`  | The Payload data to sign into the token. Could be any non nullable value. |\n| `key`    | `Sign.PrivateKey` | The token secret key used for HMAC or the PEM private key for RSA, RSASSA-PSS, DSA, EdDSA and EcDSA signing algorithms. |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eSignature verification properties\u003c/summary\u003e\n\n| Property | Type     | Description       |\n|----------|----------|-------------------|\n| `token`  | `string` | The token string. |\n| `key`    | `Sign.PublicKey` | The token secret key used for HMAC or the PEM public key for RSA, RSASSA-PSS, DSA, EdDSA and EcDSA sign verification algorithms.  |\n\n\u003c/details\u003e\n\n---\n\n#### Properties\n\nHere are listed the `Jwt` class instance accessible properties:\n\n\u003cdetails\u003e\n\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property  | Type                | Description     |\n|-----------|---------------------|-----------------|\n| `name`    | `string`            | The token name. |\n| `iat`     | `Date \\| undefined` | The token issuing Date. This properties defaults to the current timestamp when `Jwt.sign()` is called. |\n| `exp`     | `Date \\| undefined` | The token expiration Date. |\n| `nbf`     | `Date \\| undefined` | The token \"not before\" Date. |\n| `aud`     | `string[] \\| undefined` | Audience. This value is stored in the `payload` while signing the token or is being used to validate the `aud` property found in the token `payload` to validate. |\n| `iss`     | `string \\| undefined` | Issuer. This value is stored in the `payload` while signing the token or is being used to validate the `iss` property found in the token `payload` to validate. |\n| `jti`     | `string \\| undefined` | JWT ID. This value is stored in the `payload` while signing the token or is being used to validate the `jti` property found in the token `payload` to validate. |\n| `header` | `JsonWebToken.Header` | The parsed JOSE header. |\n| `payload` | `JsonWebToken.Payload\u003cT\u003e` | The parsed JWS payload. |\n| `isVerified` | `boolean \\| null` | Flag that is being set to `true \\| false` when `Jwt.verify()` is executed. |\n| `key`        | `Sign.PublicKey \\| Sign.PrivateKey` | The key set when creating a new `Jwt` instance. |\n| `token` | `string \\| undefined` | The parsed JWT string. |\n\n\u003c/details\u003e\n\n#### Methods\n\n\u003cdetails\u003e\n\n\u003csummary\u003e`Jwt.sign()`\u003c/summary\u003e\n\nThe `Jwt.sign()` method synchronously generates and returns a new token string.\n\n- It stores the result string in the `Jwt.token` property for further usage.\n- The parsed `header` is being stored in the `Jwt.header` property.\n- The `iat` property is being set to the current timestamp if none has been provided in the constructor.\n- If the given `data` is an object, it's properties are being added to the `Jwt.payload` property.\n- If the given `data` is not an object, it will be assigned to `Jwt.payload.data` property.\n- stores the signature `Buffer` to the `Jwt.signature` property.\n\nThe `Jwt.sign()` method throws a new `Exception` when:\n\n- no private key has been provided.\n- no valid payload has been parsed.\n- signature creation fails with the choosen algorithm due to invalid keys provided.\n\nSee [Error Handling](#error-handling) section for further informations.\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003e`Jwt.verify()`\u003c/summary\u003e\n\nThe `Jwt.verify()` method synchronously verifies a token string and returns `true` on signature verification success.\n\nIt throws a new `Exception` when:\n\n- no public key has been provided.\n- no token value has been provided.\n- wrong formatted token has been provided.\n- the token is expired or not yet in charge.\n- expected values mismatch in the token header/payload (Issuer, Audience, algorithm...).\n- signature verification failures due to an invalid signature (altered token).\n- signature verification failures due to an invalid public key.\n\nSee [Error Handling](#error-handling) section for further informations.\n\n\u003c/details\u003e\n\n---\n\n### Example usage\n\n#### Creating and verifying JSON Web Tokens\n\nYou can use the `Jwt` class to create or verify a JSON Web Token.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eCreating a JWT with no signature\u003c/summary\u003e\n\n```ts\nconst jwt = new Jwt( {\n  data    : 'Data encoded in the JWT payload.',\n  header  : { alg: 'none' },\n} )\nconsole.log( jwt.sign() )\n```\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eJWT with HMAC\u003c/summary\u003e\n\n#### `HS1`/`HS256`/`HS384`/`HS512`\n\nTo create a JWT using `HMAC` secrets you need to specify a secret key in the `key` field of the `Jwt` constructor.\n\nThe private key could be any `string`, KeyObject or Binary data. It is suggested to use a 256 bit string.\n\n`HS1`/`HS256`/`HS384`/`HS512` (`HMAC` with `SHA-1`/`SHA-256`/`SHA-384`/`SHA-512`) is a symmetric keyed hashing algorithm that uses one secret key. Symmetric means two parties share the secret key. The key is used for both generating the signature and verifying it.\n\nBe mindful when using a shared key; it can open potential vulnerabilities if the verifiers(multiple applications) are not appropriately secured.\n\n##### Create the token\n\n```ts\nimport crypto from 'crypto'\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst secretKey = crypto.createSecretKey( Buffer.from( 'mysecretkey' ) )\n\nconst jwt = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  key     : secretKey,\n  header  : {\n    alg: 'HS1', // HS1 | HS256 | HS384 | HS512\n  },\n} )\nconst signedJwt = jwt.sign()\n```\n\n---\n\n##### Verify the token\n\n```ts\nconst jwt = new Jwt( {\n  token   : signedJwt,\n  key     : secretKey,\n  header  : {\n    alg: 'HS1', // HS1 | HS256 | HS384 | HS512 -\u003e expected algorithm.\n  },\n} )\nconst isValid = jwt.verify()\n```\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eJWT with DSA\u003c/summary\u003e\n\n#### `DS1`/`DS256`/`DS384`/`DS512`\n\n- Generate a keypair:\n\n```ts\nimport crypto from 'crypto'\n\nconst keypair = crypto.generateKeyPairSync( 'dsa', {\n  modulusLength       : 2048,\n  divisorLength       : 256,\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n```\n\n- Parse and sign a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst jwt = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  key     : keypair.privateKey,\n  header  : {\n    alg: 'DS1', // DS1 | DS256 | DS384 | DS512\n  },\n} )\nconst signedJwt = jwt.sign()\n```\n\n- Parse and verify a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst jwt = new Jwt( {\n  token   : signedJwt,\n  key     : keypair.publicKey,\n  header  : {\n    alg: 'DS1', // DS1 | DS256 | DS384 | DS512 // expected algorithm\n  },\n} )\nconst isValid = jwt.verify()\n```\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eJWT with EcDSA\u003c/summary\u003e\n\n#### `ES256`/`ES384`/`ES512`\n\nElliptic curve based JSON Web Signatures (JWS) provide integrity, authenticity and non-reputation to JSON Web Tokens (JWT).\n\nThe EC keys should be of sufficient length to match the required level of security. Note that while EC signatures are shorter than an RSA signature of equivalent strength, they may take more CPU time to verify.\n\n#### EcDSA using P-256/384/521 and SHA-256/384/512\n\nTo generate a JWT signed with the `ES256`/`ES384`/`ES512` algorithm and EcDSA keys you need to generate an asymmetric keys as follow:\n\n- Generate a keypair:\n\n```ts\nimport crypto from 'crypto'\n\nconst es256keypair = crypto.generateKeyPairSync( 'ec', {\n  namedCurve          : 'secp256k1',\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n\nconst es384keypair = crypto.generateKeyPairSync( 'ec', {\n  namedCurve          : 'secp384r1',\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n\nconst es512keypair = crypto.generateKeyPairSync( 'ec', {\n  namedCurve          : 'secp521r1',\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n```\n\n- Parse and sign a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst es256Token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'ES256' },\n  key     : es256keypair.privateKey,\n} ).sign()\n\nconst es384Token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'ES384' },\n  key     : es384keypair.privateKey,\n} ).sign()\n\nconst es512Token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'ES512' },\n  key     : es512keypair.privateKey,\n} ).sign()\n```\n\n- Parse and verify a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst es256Valid = new Jwt( {\n  token   : es256Token,\n  header  : { alg: 'ES256' }, // expected algorithm\n  key     : es256keypair.publicKey,\n} ).verify()\n\nconst es384Valid = new Jwt( {\n  token   : es384Token,\n  header  : { alg: 'ES384' }, // expected algorithm\n  key     : es384keypair.publicKey,\n} ).verify()\n\nconst es512Valid = new Jwt( {\n  token   : es512Token,\n  header  : { alg: 'ES512' }, // expected algorithm\n  key     : es512keypair.publicKey,\n} ).verify()\n```\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eJWT with EdDSA\u003c/summary\u003e\n\n- Generate a keypair:\n\n```ts\nimport crypto from 'crypto'\n\nconst ed448keypair = crypto.generateKeyPairSync( 'ed448', {\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n\nconst ed25519keypair = crypto.generateKeyPairSync( 'ed25519', {\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n```\n\n- Parse and sign a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst ed448Token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'EdDSA' },\n  key     : ed448keypair.privateKey,\n} ).sign()\n\nconst ed25519Token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'EdDSA' },\n  key     : ed25519keypair.privateKey,\n} ).sign()\n```\n\n- Parse and verify a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst ed448Valid = new Jwt( {\n  token   : ed448Token,\n  header  : { alg: 'EdDSA' }, // expected algorithm\n  key     : ed448keypair.publicKey,\n} ).verify()\n\nconst ed25519Valid = new Jwt( {\n  token   : ed25519Token,\n  header  : { alg: 'EdDSA' }, // expected algorithm\n  key     : ed25519keypair.publicKey,\n} ).verify()\n```\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eJWT with RSA\u003c/summary\u003e\n\n#### `RS1`/`RS256`/`RS384`/`RS512`\n\n- Generate a keypair:\n\n```ts\nimport crypto from 'crypto'\n\nconst bytes   = 256\nconst keypair = crypto.generateKeyPairSync( 'rsa', {\n  modulusLength     : bytes * 8,\n  publicKeyEncoding : { type: 'spki', format: 'pem' },\n  privateKeyEncoding: { type: 'pkcs1', format: 'pem' },\n} )\n```\n\n- Parse and sign a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst signedJwt = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'RS1' }, // RS1 | RS256 | RS384 | RS512\n  key     : keypair.privateKey,\n} ).sign()\n```\n\n- Parse and verify a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst validToken = new Jwt( {\n  token   : signedJwt,\n  header  : { alg: 'RS1' }, // RS1 | RS256 | RS384 | RS512\n  key     : keypair.publicKey,\n} ).verify()\n```\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eJWT with RSASSA-PSS\u003c/summary\u003e\n\n#### `PS256`/`PS384`/`PS512`\n\n- Generate a keypair:\n\n```ts\nimport crypto from 'crypto'\n\nconst bytes = 256\n\n/** RSASSA-PSS using `SHA-256` and MGF1 with `SHA-256` */\nconst rsapss256keypair = crypto.generateKeyPairSync( 'rsa-pss', {\n  modulusLength       : bytes * 8,\n  hashAlgorithm       : 'SHA-256',\n  mgf1HashAlgorithm   : 'SHA-256',\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n\n/** RSASSA-PSS using `SHA-384` and MGF1 with `SHA-384` */\nconst rsapss384keypair = crypto.generateKeyPairSync( 'rsa-pss', {\n  modulusLength       : bytes * 8,\n  hashAlgorithm       : 'SHA-384',\n  mgf1HashAlgorithm   : 'SHA-384',\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n\n/** RSASSA-PSS using `SHA-512` and MGF1 with `SHA-512` */\nconst rsapss512keypair = crypto.generateKeyPairSync( 'rsa-pss', {\n  modulusLength       : bytes * 8,\n  hashAlgorithm       : 'SHA-512',\n  mgf1HashAlgorithm   : 'SHA-512',\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs8', format: 'pem' },\n} )\n```\n\n- Parse and sign a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst rsapss256token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'PS256' },\n  key     : rsapss256keypair.privateKey,\n} ).sign()\n\nconst rsapss384token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'PS384' },\n  key     : rsapss384keypair.privateKey,\n} ).sign()\n\nconst rsapss512token = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'PS512' },\n  key     : rsapss512keypair.privateKey,\n} ).sign()\n```\n\n- Parse and verify a token:\n\n```ts\nimport { Jwt } from '@alessiofrittoli/crypto-jwt'\n\nconst rsapss256Valid = new Jwt( {\n  token   : rsapss256token,\n  header  : { alg: 'PS256' },\n  key     : rsapss256keypair.publicKey,\n} ).verify()\n\nconst rsapss384Valid = new Jwt( {\n  token   : rsapss384token,\n  header  : { alg: 'PS384' },\n  key     : rsapss384keypair.publicKey,\n} ).verify()\n\nconst rsapss512Valid = new Jwt( {\n  token   : rsapss512token,\n  header  : { alg: 'PS512' },\n  key     : rsapss512keypair.publicKey,\n} ).verify()\n```\n\n\u003c/details\u003e\n\n---\n\n#### Using keys that requires a passphrase\n\nMost of asymmetric key pairs allows you to set a passphrase for the Private Key. This passphrase must be provided in order to use that key for generating a signature.\n\nLet's assume we got this keypair with the following passphrase:\n\n```ts\nimport crypto from 'crypto'\n\nconst bytes       = 256\nconst passphrase  = 'my-private-key-optional-passphrase'\nconst keypair     = crypto.generateKeyPairSync( 'rsa', {\n    modulusLength       : 256 * 8,\n    publicKeyEncoding   : { type: 'spki', format: 'pem' },\n    privateKeyEncoding  : { type: 'pkcs1', format: 'pem', passphrase, cipher: 'aes-256-cbc' },\n} )\n```\n\nWe can then sign a token as follow:\n\n```ts\nconst jwt = new Jwt( {\n  data    : 'Data to be signed into the token.',\n  header  : { alg: 'RS1' },\n  key     : {\n    key         : keypair.privateKey,\n    passphrase  : passphrase,\n  },\n} )\n```\n\n---\n\n#### Expiration\n\nBy setting an expiration Date, the token will no longer be accepted on and after that Date. The `Jwt.verify()` method will then throw an Exception with the `ErrorCode.EXPIRED` code.\n\n```ts\n/** 5 minutes expiration token. */\nconst jwt = new Jwt( {\n  exp: new Date().getTime() + ( 5 * 60 * 1000 ),\n  ...\n} )\n```\n\n#### Not before\n\nBy setting \"not before\" Date, the token will not be accepted on and before that Date. The `Jwt.verify()` method will then throw an Exception with the `ErrorCode.TOO_EARLY` code.\n\n```ts\n/** token should not be accepted in the next 5 minutes. */\nconst jwt = new Jwt( {\n  nbf: new Date().getTime() + ( 5 * 60 * 1000 ),\n  ...\n} )\n```\n\n---\n\n#### Type casting\n\nBy default the `Jwt` class will infer the type of the given `data` to the payload. So for example:\n\n```ts\nconst jwt = new Jwt( {\n  data: 'Data to be signed into the token.',\n  ...\n} )\n// `jwt` -\u003e `Jwt\u003cstring\u003e`\n// `jwt.payload.data` -\u003e `string`\n\nconst jwt = new Jwt( {\n  data: [ 1, 2, 3 ],\n  ...\n} )\n// `jwt` -\u003e `Jwt\u003cnumber[]\u003e`\n// `jwt.payload.data` -\u003e `number[]`\n\nconst jwt = new Jwt( {\n  data: { property: 'value' },\n  ...\n} )\n// `jwt` -\u003e `Jwt\u003c{property: string}\u003e`\n// `jwt.payload` -\u003e `{property: string} \u0026 JsonWebToken.JwsPayload`\n```\n\nFor obvious reasons the type cannot be inferred when \"reading\" a token and `Jwt` class will fallback to the type of `unknown`.\n\n```ts\nnew Jwt( {\n  token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoiQW4gdW5rbm93biB0eXBlIG9mIHBheWxvYWQiLCJpYXQiOjE3MzQzNzc3MTJ9.qptazZOXfAgFbMpVlPdGa6RstKlA945_-Qm1PhfmPIQ',\n  ...\n} ) // -\u003e `Jwt\u003cunknown\u003e`\n```\n\nThe `Jwt` class allows you to assing a custom type to the `T` parameter so that type can securely inferred to the payload data.\n\n```ts\nnew Jwt\u003cUser\u003e( {\n  data: { id: 1 },\n  ...\n} ).payload // -\u003e `User \u0026 JsonWebToken.JwsPayload`\n\nconst jwt = new Jwt\u003cUser\u003e( {\n  token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiaWF0IjoxNzM0Mzc4MDc0fQ.jt3-bjXe8NEyr9MEk5cvzCM_M_YcG9tpaWwKPhnIK8c',\n  ...\n} )\n// `jwt.payload` // -\u003e `User \u0026 JsonWebToken.JwsPayload`\n// `jwt.payload.id` // -\u003e safe type access\n```\n\n---\n\n### Error handling\n\nThis module throws a new `Exception` when an error occures providing an error code that will help in error handling.\n\nThe `ErrorCode` enumerator can be used to handle different errors with ease.\n\n\u003cdetails\u003e\n\n\u003csummary\u003e`ErrorCode` enum\u003c/summary\u003e\n\n| Constant              | Description                                              |\n|-----------------------|----------------------------------------------------------|\n| `UNKNOWN`             | Thrown when `Jwt.sign()` encounters an unexpected error. |\n| `NO_PRIVATEKEY`       | Thrown when `Jwt.sign()` has no private key. |\n| `EMPTY_VALUE`         | Thrown when: |\n|                       | `Jwt.sign()` has no `payload` to sign. |\n|                       | `Jwt.verify()` has no `token` to verify. |\n| `WRONG_FORMAT`        | Thrown when `Jwt.verify()` encounter a malformed JWT. |\n| `NO_HEADER`           | Thrown when `Jwt.verify()` has no JOSE Header to validate. |\n| `WRONG_HEADER`        | Thrown when `Jwt.verify()` cannot parse JOSE Header. |\n| `WRONG_ALGO`          | Thrown when `Jwt.verify()` finds an unexpected `alg` field in the given `token` JOSE Header. |\n| `WRONG_KID`           | Thrown when `Jwt.verify()` finds an unexpected `kid` field in the given `token` JOSE Header. |\n| `WRONG_JWS`           | Thrown when `Jwt` couldn't parse the given `token` payload. |\n| `EXPIRED`             | Thrown when `Jwt.verify()` finds an expired token. |\n| `TOO_EARLY`           | Thrown when `Jwt.verify()` verifies a token that cannot be still processed. |\n| `UNEXPECTED_ISSUER`   | Thrown when `Jwt.verify()` finds an unexpected `iss` field in the given `token` payload. |\n| `UNEXPECTED_AUDIENCE` | Thrown when `Jwt.verify()` finds an unexpected `aud` field in the given `token` payload. |\n| `UNEXPECTED_JTI`      | Thrown when `Jwt.verify()` finds an unexpected `jti` field in the given `token` payload. |\n| `NO_SIGN`             | Thrown when `Jwt.verify()` doesn't find any signature in the given `token`. |\n| `UNEXPECTED_SIGN`     | Thrown when `Jwt.verify()` finds an unexpected signature in the given `token` (expected `none` algorithm). |\n| `INVALID_SIGN`        | Thrown when `Jwt.verify()` receives an invalid signature (altered JWT). |\n| `NO_PUBLICKEY`        | Thrown when `Jwt.verify()` has no public key. |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eExample usage\u003c/summary\u003e\n\n```ts\nimport { Exception } from '@alessiofrittoli/exception'\nimport { ErrorCode } from '@alessiofrittoli/crypto-jwt/error'\n\ntry {\n  new Jwt( {\n    token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.invalid'\n  } ) // will throw error with code: ErrorCode.Jwt.WRONG_JWS\n} catch ( error ) {\n  if ( Exception.isException\u003cstring, ErrorCode\u003e( error ) ) {\n      switch ( error.code ) {\n        case ErrorCode.Jwt.WRONG_JWS:\n          // malformed JWT payload\n          break\n        // ... other cases here\n        default:\n          // unknown error\n      }\n  }\n}\n```\n\n\u003c/details\u003e\n\n---\n\n### Development\n\n#### Install depenendencies\n\n```bash\nnpm install\n```\n\nor using `pnpm`\n\n```bash\npnpm i\n```\n\n#### Build the source code\n\nRun the following command to test and build code for distribution.\n\n```bash\npnpm build\n```\n\n#### [ESLint](https://www.npmjs.com/package/eslint)\n\nwarnings / errors check.\n\n```bash\npnpm lint\n```\n\n#### [Jest](https://npmjs.com/package/jest)\n\nRun all the defined test suites by running the following:\n\n```bash\n# Run tests and watch file changes.\npnpm test:watch\n\n# Run tests in a CI environment.\npnpm test:ci\n```\n\n- See [`package.json`](./package.json) file scripts for more info.\n\nRun tests with coverage.\n\nAn HTTP server is then started to serve coverage files from `./coverage` folder.\n\n⚠️ You may see a blank page the first time you run this command. Simply refresh the browser to see the updates.\n\n```bash\ntest:coverage:serve\n```\n\n---\n\n### Contributing\n\nContributions are truly welcome!\n\nPlease refer to the [Contributing Doc](./CONTRIBUTING.md) for more information on how to start contributing to this project.\n\nHelp keep this project up to date with [GitHub Sponsor][sponsor-url].\n\n[![GitHub Sponsor][sponsor-badge]][sponsor-url]\n\n---\n\n### Security\n\nIf you believe you have found a security vulnerability, we encourage you to **_responsibly disclose this and NOT open a public issue_**. We will investigate all legitimate reports. Email `security@alessiofrittoli.it` to disclose any security vulnerabilities.\n\n### Made with ☕\n\n\u003ctable style='display:flex;gap:20px;'\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        \u003cimg alt=\"avatar\" src='https://avatars.githubusercontent.com/u/35973186' style='width:60px;border-radius:50%;object-fit:contain;'\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003ctable style='display:flex;gap:2px;flex-direction:column;'\u003e\n          \u003ctbody\u003e\n              \u003ctr\u003e\n                \u003ctd\u003e\n                  \u003ca href='https://github.com/alessiofrittoli' target='_blank' rel='noopener'\u003eAlessio Frittoli\u003c/a\u003e\n                \u003c/td\u003e\n              \u003c/tr\u003e\n              \u003ctr\u003e\n                \u003ctd\u003e\n                  \u003csmall\u003e\n                    \u003ca href='https://alessiofrittoli.it' target='_blank' rel='noopener'\u003ehttps://alessiofrittoli.it\u003c/a\u003e |\n                    \u003ca href='mailto:info@alessiofrittoli.it' target='_blank' rel='noopener'\u003einfo@alessiofrittoli.it\u003c/a\u003e\n                  \u003c/small\u003e\n                \u003c/td\u003e\n              \u003c/tr\u003e\n          \u003c/tbody\u003e\n        \u003c/table\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessiofrittoli%2Fcrypto-jwt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falessiofrittoli%2Fcrypto-jwt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessiofrittoli%2Fcrypto-jwt/lists"}