@aziontech/jwt 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +218 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.mjs +253 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Azion JWT Library
|
|
2
|
+
|
|
3
|
+
The Azion JWT Library provides utility functions for signing, verifying, and decoding JSON Web Tokens (JWTs). This library ensures ease of use and security when handling JWTs in web applications.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Usage](#usage)
|
|
9
|
+
- [Sign JWT](#sign-jwt)
|
|
10
|
+
- [Verify JWT](#verify-jwt)
|
|
11
|
+
- [Decode JWT](#decode-jwt)
|
|
12
|
+
- [API Reference](#api-reference)
|
|
13
|
+
- [`sign`](#sign)
|
|
14
|
+
- [`verify`](#verify)
|
|
15
|
+
- [`decode`](#decode)
|
|
16
|
+
- [Types](#types)
|
|
17
|
+
- [`JWTPayload`](#jwtpayload)
|
|
18
|
+
- [`TokenHeader`](#tokenheader)
|
|
19
|
+
- [Errors](#errors)
|
|
20
|
+
- [`JwtAlgorithmNotImplemented`](#jwtalgorithmnotimplemented)
|
|
21
|
+
- [`JwtTokenInvalid`](#jwttokeninvalid)
|
|
22
|
+
- [`JwtTokenNotBefore`](#jwttokennotbefore)
|
|
23
|
+
- [`JwtTokenExpired`](#jwttokenexpired)
|
|
24
|
+
- [`JwtTokenIssuedAt`](#jwttokenissuedat)
|
|
25
|
+
- [`JwtHeaderInvalid`](#jwtheaderinvalid)
|
|
26
|
+
- [`JwtTokenSignatureMismatched`](#jwttokensignaturemismatched)
|
|
27
|
+
- [Contributing](#contributing)
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
Install the package using npm or yarn:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
npm install azion
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
or
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
yarn add azion
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### Sign JWT
|
|
46
|
+
|
|
47
|
+
**JavaScript:**
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
import { sign } from '@aziontech/jwt';
|
|
51
|
+
|
|
52
|
+
const privateKey = 'your-private-key';
|
|
53
|
+
const payload = { userId: 123, exp: Math.floor(Date.now() / 1000) + 3600 }; // 1 hour expiration
|
|
54
|
+
sign(payload, privateKey).then((token) => console.log(token)); // Outputs the signed JWT
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**TypeScript:**
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { sign } from '@aziontech/jwt';
|
|
61
|
+
import type { JWTPayload } from '@aziontech/jwt';
|
|
62
|
+
|
|
63
|
+
const privateKey: string = 'your-private-key';
|
|
64
|
+
const payload: JWTPayload = { userId: 123, exp: Math.floor(Date.now() / 1000) + 3600 }; // 1 hour expiration
|
|
65
|
+
sign(payload, privateKey).then((token: string) => console.log(token)); // Outputs the signed JWT
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Verify JWT
|
|
69
|
+
|
|
70
|
+
**JavaScript:**
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
import { verify } from '@aziontech/jwt';
|
|
74
|
+
|
|
75
|
+
const publicKey = 'your-public-key';
|
|
76
|
+
const token = 'your-jwt-token';
|
|
77
|
+
verify(token, publicKey)
|
|
78
|
+
.then((payload) => console.log(payload))
|
|
79
|
+
.catch((err) => console.error(err)); // Outputs the payload if verification is successful
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**TypeScript:**
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { verify } from '@aziontech/jwt';
|
|
86
|
+
import type { JWTPayload } from '@aziontech/jwt';
|
|
87
|
+
|
|
88
|
+
const publicKey: string = 'your-public-key';
|
|
89
|
+
const token: string = 'your-jwt-token';
|
|
90
|
+
verify(token, publicKey)
|
|
91
|
+
.then((payload: JWTPayload) => console.log(payload))
|
|
92
|
+
.catch((err) => console.error(err)); // Outputs the payload if verification is successful
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Decode JWT
|
|
96
|
+
|
|
97
|
+
**JavaScript:**
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
import { decode } from '@aziontech/jwt';
|
|
101
|
+
|
|
102
|
+
const token = 'your-jwt-token';
|
|
103
|
+
const { header, payload } = decode(token);
|
|
104
|
+
console.log(header, payload); // Outputs the decoded header and payload
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**TypeScript:**
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { decode } from '@aziontech/jwt';
|
|
111
|
+
import type { JWTPayload, TokenHeader } from '@aziontech/jwt';
|
|
112
|
+
|
|
113
|
+
const token: string = 'your-jwt-token';
|
|
114
|
+
const { header, payload }: { header: TokenHeader; payload: JWTPayload } = decode(token);
|
|
115
|
+
console.log(header, payload); // Outputs the decoded header and payload
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## API Reference
|
|
119
|
+
|
|
120
|
+
### `sign`
|
|
121
|
+
|
|
122
|
+
Signs a JWT payload with the specified algorithm and private key.
|
|
123
|
+
|
|
124
|
+
**Parameters:**
|
|
125
|
+
|
|
126
|
+
- `payload: JWTPayload` - The payload to be signed.
|
|
127
|
+
- `privateKey: SignatureKey` - The private key used for signing.
|
|
128
|
+
- `alg?: SignatureAlgorithm` - The algorithm to use for signing (default is `'HS256'`).
|
|
129
|
+
|
|
130
|
+
**Returns:**
|
|
131
|
+
|
|
132
|
+
- `Promise<string>` - The signed JWT.
|
|
133
|
+
|
|
134
|
+
### `verify`
|
|
135
|
+
|
|
136
|
+
Verifies a JWT using the specified public key and algorithm.
|
|
137
|
+
|
|
138
|
+
**Parameters:**
|
|
139
|
+
|
|
140
|
+
- `token: string` - The JWT to verify.
|
|
141
|
+
- `publicKey: SignatureKey` - The public key used for verification.
|
|
142
|
+
- `alg?: SignatureAlgorithm` - The algorithm to use for verification (default is `'HS256'`).
|
|
143
|
+
|
|
144
|
+
**Returns:**
|
|
145
|
+
|
|
146
|
+
- `Promise<JWTPayload>` - The decoded payload if the token is valid.
|
|
147
|
+
|
|
148
|
+
### `decode`
|
|
149
|
+
|
|
150
|
+
Decodes a JWT without verifying its signature.
|
|
151
|
+
|
|
152
|
+
**Parameters:**
|
|
153
|
+
|
|
154
|
+
- `token: string` - The JWT to decode.
|
|
155
|
+
|
|
156
|
+
**Returns:**
|
|
157
|
+
|
|
158
|
+
- `{ header: TokenHeader; payload: JWTPayload }` - The decoded header and payload.
|
|
159
|
+
|
|
160
|
+
## Types
|
|
161
|
+
|
|
162
|
+
### `JWTPayload`
|
|
163
|
+
|
|
164
|
+
Defines the structure of the JWT payload.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
type JWTPayload = {
|
|
168
|
+
[key: string]: unknown;
|
|
169
|
+
exp?: number;
|
|
170
|
+
nbf?: number;
|
|
171
|
+
iat?: number;
|
|
172
|
+
};
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### `TokenHeader`
|
|
176
|
+
|
|
177
|
+
Defines the structure of the JWT header.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
interface TokenHeader {
|
|
181
|
+
alg: SignatureAlgorithm;
|
|
182
|
+
typ?: 'JWT';
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Errors
|
|
187
|
+
|
|
188
|
+
### `JwtAlgorithmNotImplemented`
|
|
189
|
+
|
|
190
|
+
Thrown when an algorithm is not implemented.
|
|
191
|
+
|
|
192
|
+
### `JwtTokenInvalid`
|
|
193
|
+
|
|
194
|
+
Thrown when a JWT is invalid.
|
|
195
|
+
|
|
196
|
+
### `JwtTokenNotBefore`
|
|
197
|
+
|
|
198
|
+
Thrown when a JWT is used before its `nbf` claim.
|
|
199
|
+
|
|
200
|
+
### `JwtTokenExpired`
|
|
201
|
+
|
|
202
|
+
Thrown when a JWT has expired.
|
|
203
|
+
|
|
204
|
+
### `JwtTokenIssuedAt`
|
|
205
|
+
|
|
206
|
+
Thrown when a JWT `iat` claim is in the future.
|
|
207
|
+
|
|
208
|
+
### `JwtHeaderInvalid`
|
|
209
|
+
|
|
210
|
+
Thrown when a JWT header is invalid.
|
|
211
|
+
|
|
212
|
+
### `JwtTokenSignatureMismatched`
|
|
213
|
+
|
|
214
|
+
Thrown when a JWT signature does not match.
|
|
215
|
+
|
|
216
|
+
## Contributing
|
|
217
|
+
|
|
218
|
+
Feel free to submit issues or pull requests to improve the functionality or documentation.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class g extends Error{constructor(t){super(`${t} is not an implemented algorithm`),this.name="JwtAlgorithmNotImplemented"}}class h extends Error{constructor(t){super(`invalid JWT token: ${t}`),this.name="JwtTokenInvalid"}}class J extends Error{constructor(t){super(`token (${t}) is being used before it's valid`),this.name="JwtTokenNotBefore"}}class x extends Error{constructor(t){super(`token (${t}) expired`),this.name="JwtTokenExpired"}}class K extends Error{constructor(t,r){super(`Incorrect "iat" claim must be a older than "${t}" (iat: "${r}")`),this.name="JwtTokenIssuedAt"}}class R extends Error{constructor(t){super(`jwt header is invalid: ${JSON.stringify(t)}`),this.name="JwtHeaderInvalid"}}class C extends Error{constructor(t){super(`token(${t}) signature mismatched`),this.name="JwtTokenSignatureMismatched"}}var i=(e=>(e.Encrypt="encrypt",e.Decrypt="decrypt",e.Sign="sign",e.Verify="verify",e.DeriveKey="deriveKey",e.DeriveBits="deriveBits",e.WrapKey="wrapKey",e.UnwrapKey="unwrapKey",e))(i||{}),m=(e=>(e.HS256="HS256",e.HS384="HS384",e.HS512="HS512",e.RS256="RS256",e.RS384="RS384",e.RS512="RS512",e.PS256="PS256",e.PS384="PS384",e.PS512="PS512",e.ES256="ES256",e.ES384="ES384",e.ES512="ES512",e.EdDSA="EdDSA",e))(m||{});const y=e=>E(e.replace(/_|-/g,t=>({_:"/","-":"+"})[t]??t)),b=e=>I(e).replace(/\/|\+/g,t=>({"/":"_","+":"-"})[t]??t),I=e=>{let t="";const r=new Uint8Array(e);for(let n=0,a=r.length;n<a;n++)t+=String.fromCharCode(r[n]);return btoa(t)},E=e=>{const t=atob(e),r=new Uint8Array(new ArrayBuffer(t.length)),n=t.length/2;for(let a=0,s=t.length-1;a<=n;a++,s--)r[a]=t.charCodeAt(a),r[s]=t.charCodeAt(s);return r},u=new TextEncoder,$=new TextDecoder;async function D(e,t,r){const n=v(t),a=await B(e,n);return await crypto.subtle.sign(n,a,r)}async function j(e,t,r,n){const a=v(t),s=await T(e,a);return await crypto.subtle.verify(a,s,r,n)}function d(e){return E(e.split(`
|
|
2
|
+
`).filter(t=>!t.includes("BEGIN")&&!t.includes("END")).join("").replace(/\s/g,""))}async function B(e,t){if(!crypto.subtle||!crypto.subtle.importKey)throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");if(P(e)){if(e.type!=="private")throw new Error(`unexpected non private key: CryptoKey.type is ${e.type}`);return e}const r=[i.Sign];return typeof e=="object"?await crypto.subtle.importKey("jwk",e,t,!1,r):e.includes("PRIVATE")?await crypto.subtle.importKey("pkcs8",d(e),t,!1,r):await crypto.subtle.importKey("raw",u.encode(e),t,!1,r)}async function T(e,t){if(!crypto.subtle||!crypto.subtle.importKey)throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");if(P(e)){if(e.type==="public"||e.type==="secret")return e;e=await p(e)}if(typeof e=="string"&&e.includes("PRIVATE")){const n=await crypto.subtle.importKey("pkcs8",d(e),t,!0,[i.Sign]);e=await p(n)}const r=[i.Verify];return typeof e=="object"?await crypto.subtle.importKey("jwk",e,t,!1,r):e.includes("PUBLIC")?await crypto.subtle.importKey("spki",d(e),t,!1,r):await crypto.subtle.importKey("raw",u.encode(e),t,!1,r)}async function p(e){if(e.type!=="private")throw new Error(`unexpected key type: ${e.type}`);if(!e.extractable)throw new Error("unexpected private key is unextractable");const t=await crypto.subtle.exportKey("jwk",e),{kty:r}=t,{alg:n,e:a,n:s}=t,{crv:o,x:c,y:l}=t;return{kty:r,alg:n,e:a,n:s,crv:o,x:c,y:l,key_ops:[i.Verify]}}function v(e){switch(e){case"HS256":return{name:"HMAC",hash:{name:"SHA-256"}};case"HS384":return{name:"HMAC",hash:{name:"SHA-384"}};case"HS512":return{name:"HMAC",hash:{name:"SHA-512"}};case"RS256":return{name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};case"RS384":return{name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-384"}};case"RS512":return{name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-512"}};case"PS256":return{name:"RSA-PSS",hash:{name:"SHA-256"},saltLength:32};case"PS384":return{name:"RSA-PSS",hash:{name:"SHA-384"},saltLength:48};case"PS512":return{name:"RSA-PSS",hash:{name:"SHA-512"},saltLength:64};case"ES256":return{name:"ECDSA",hash:{name:"SHA-256"},namedCurve:"P-256"};case"ES384":return{name:"ECDSA",hash:{name:"SHA-384"},namedCurve:"P-384"};case"ES512":return{name:"ECDSA",hash:{name:"SHA-512"},namedCurve:"P-521"};case"EdDSA":return{name:"Ed25519",namedCurve:"Ed25519"};default:throw new g(e)}}function P(e){return e instanceof CryptoKey}const w=e=>b(u.encode(JSON.stringify(e))).replace(/=/g,""),N=e=>b(e).replace(/=/g,""),f=e=>JSON.parse($.decode(y(e)));function _(e){if(typeof e=="object"&&e!==null){const t=e;return"alg"in t&&Object.values(m).includes(t.alg)&&(!("typ"in t)||t.typ==="JWT")}return!1}const A=async(e,t,r="HS256")=>{const n=w(e),s=`${w({alg:r,typ:"JWT"})}.${n}`,o=await D(t,r,u.encode(s)),c=N(o);return`${s}.${c}`},H=async(e,t,r="HS256")=>{const n=e.split(".");if(n.length!==3)throw new h(e);const{header:a,payload:s}=S(e);if(!_(a))throw new R(a);const o=Math.floor(Date.now()/1e3);if(s.nbf&&s.nbf>o)throw new J(e);if(s.exp&&s.exp<=o)throw new x(e);if(s.iat&&o<s.iat)throw new K(o,s.iat);const c=e.substring(0,e.lastIndexOf("."));if(!await j(t,r,y(n[2]),u.encode(c)))throw new C(e);return s},S=e=>{try{const[t,r]=e.split("."),n=f(t),a=f(r);return{header:n,payload:a}}catch{throw new h(e)}},M={decode:S,sign:A,verify:H};exports.decode=S;exports.default=M;exports.sign=A;exports.verify=H;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* JSON Web Algorithms (JWA)
|
|
4
|
+
* https://datatracker.ietf.org/doc/html/rfc7518
|
|
5
|
+
*/
|
|
6
|
+
declare enum AlgorithmTypes {
|
|
7
|
+
HS256 = "HS256",
|
|
8
|
+
HS384 = "HS384",
|
|
9
|
+
HS512 = "HS512",
|
|
10
|
+
RS256 = "RS256",
|
|
11
|
+
RS384 = "RS384",
|
|
12
|
+
RS512 = "RS512",
|
|
13
|
+
PS256 = "PS256",
|
|
14
|
+
PS384 = "PS384",
|
|
15
|
+
PS512 = "PS512",
|
|
16
|
+
ES256 = "ES256",
|
|
17
|
+
ES384 = "ES384",
|
|
18
|
+
ES512 = "ES512",
|
|
19
|
+
EdDSA = "EdDSA"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export declare enum CryptoKeyUsage {
|
|
23
|
+
Encrypt = "encrypt",
|
|
24
|
+
Decrypt = "decrypt",
|
|
25
|
+
Sign = "sign",
|
|
26
|
+
Verify = "verify",
|
|
27
|
+
DeriveKey = "deriveKey",
|
|
28
|
+
DeriveBits = "deriveBits",
|
|
29
|
+
WrapKey = "wrapKey",
|
|
30
|
+
UnwrapKey = "unwrapKey"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Decodes a JWT into its header and payload.
|
|
35
|
+
* @param token - The JWT to decode.
|
|
36
|
+
* @returns An object containing the decoded header and payload.
|
|
37
|
+
* @throws {JwtTokenInvalid} If the token is invalid.
|
|
38
|
+
* @example
|
|
39
|
+
* const { header, payload } = decode(token);
|
|
40
|
+
* console.log(header, payload);
|
|
41
|
+
*/
|
|
42
|
+
export declare const decode: (token: string) => {
|
|
43
|
+
header: TokenHeader;
|
|
44
|
+
payload: JWTPayload;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
declare const jwt: {
|
|
48
|
+
decode: (token: string) => {
|
|
49
|
+
header: TokenHeader;
|
|
50
|
+
payload: JWTPayload;
|
|
51
|
+
};
|
|
52
|
+
sign: (payload: JWTPayload, privateKey: SignatureKey, alg?: SignatureAlgorithm) => Promise<string>;
|
|
53
|
+
verify: (token: string, publicKey: SignatureKey, alg?: SignatureAlgorithm) => Promise<JWTPayload>;
|
|
54
|
+
};
|
|
55
|
+
export default jwt;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @module
|
|
59
|
+
* Type definitions for JWT utilities.
|
|
60
|
+
*/
|
|
61
|
+
export declare class JwtAlgorithmNotImplemented extends Error {
|
|
62
|
+
constructor(alg: string);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export declare class JwtHeaderInvalid extends Error {
|
|
66
|
+
constructor(header: object);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* JWT Payload
|
|
71
|
+
*/
|
|
72
|
+
export declare type JWTPayload = {
|
|
73
|
+
[key: string]: unknown;
|
|
74
|
+
/**
|
|
75
|
+
* The token is checked to ensure it has not expired.
|
|
76
|
+
*/
|
|
77
|
+
exp?: number;
|
|
78
|
+
/**
|
|
79
|
+
* The token is checked to ensure it is not being used before a specified time.
|
|
80
|
+
*/
|
|
81
|
+
nbf?: number;
|
|
82
|
+
/**
|
|
83
|
+
* The token is checked to ensure it is not issued in the future.
|
|
84
|
+
*/
|
|
85
|
+
iat?: number;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export declare class JwtTokenExpired extends Error {
|
|
89
|
+
constructor(token: string);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export declare class JwtTokenInvalid extends Error {
|
|
93
|
+
constructor(token: string);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export declare class JwtTokenIssuedAt extends Error {
|
|
97
|
+
constructor(currentTimestamp: number, iat: number);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export declare class JwtTokenNotBefore extends Error {
|
|
101
|
+
constructor(token: string);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export declare class JwtTokenSignatureMismatched extends Error {
|
|
105
|
+
constructor(token: string);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Signs a JWT payload with a given private key and algorithm.
|
|
110
|
+
* @param payload - The JWT payload to sign.
|
|
111
|
+
* @param privateKey - The private key to sign the payload with.
|
|
112
|
+
* @param alg - The signature algorithm to use (default is 'HS256').
|
|
113
|
+
* @returns The signed JWT as a string.
|
|
114
|
+
* @example
|
|
115
|
+
* const token = await sign({ sub: '1234567890', name: 'John Doe', iat: 1516239022 }, privateKey);
|
|
116
|
+
* console.log(token);
|
|
117
|
+
*/
|
|
118
|
+
export declare const sign: (payload: JWTPayload, privateKey: SignatureKey, alg?: SignatureAlgorithm) => Promise<string>;
|
|
119
|
+
|
|
120
|
+
declare type SignatureAlgorithm = keyof typeof AlgorithmTypes;
|
|
121
|
+
|
|
122
|
+
declare type SignatureKey = string | JsonWebKey | CryptoKey;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Interface representing the JWT header.
|
|
126
|
+
*/
|
|
127
|
+
declare interface TokenHeader {
|
|
128
|
+
alg: SignatureAlgorithm;
|
|
129
|
+
typ?: 'JWT';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Verifies a JWT with a given public key and algorithm.
|
|
134
|
+
* @param token - The JWT to verify.
|
|
135
|
+
* @param publicKey - The public key to verify the JWT with.
|
|
136
|
+
* @param alg - The signature algorithm to use (default is 'HS256').
|
|
137
|
+
* @returns The decoded JWT payload if verification is successful.
|
|
138
|
+
* @throws {JwtTokenInvalid} If the token is invalid.
|
|
139
|
+
* @throws {JwtHeaderInvalid} If the token header is invalid.
|
|
140
|
+
* @throws {JwtTokenNotBefore} If the token is not yet valid.
|
|
141
|
+
* @throws {JwtTokenExpired} If the token has expired.
|
|
142
|
+
* @throws {JwtTokenIssuedAt} If the token was issued in the future.
|
|
143
|
+
* @throws {JwtTokenSignatureMismatched} If the token signature does not match.
|
|
144
|
+
* @example
|
|
145
|
+
* const payload = await verify(token, publicKey);
|
|
146
|
+
* console.log(payload);
|
|
147
|
+
*/
|
|
148
|
+
export declare const verify: (token: string, publicKey: SignatureKey, alg?: SignatureAlgorithm) => Promise<JWTPayload>;
|
|
149
|
+
|
|
150
|
+
export { }
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
class H extends Error {
|
|
2
|
+
constructor(t) {
|
|
3
|
+
super(`${t} is not an implemented algorithm`), this.name = "JwtAlgorithmNotImplemented";
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
class f extends Error {
|
|
7
|
+
constructor(t) {
|
|
8
|
+
super(`invalid JWT token: ${t}`), this.name = "JwtTokenInvalid";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
class P extends Error {
|
|
12
|
+
constructor(t) {
|
|
13
|
+
super(`token (${t}) is being used before it's valid`), this.name = "JwtTokenNotBefore";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
class J extends Error {
|
|
17
|
+
constructor(t) {
|
|
18
|
+
super(`token (${t}) expired`), this.name = "JwtTokenExpired";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
class x extends Error {
|
|
22
|
+
constructor(t, r) {
|
|
23
|
+
super(`Incorrect "iat" claim must be a older than "${t}" (iat: "${r}")`), this.name = "JwtTokenIssuedAt";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
class g extends Error {
|
|
27
|
+
constructor(t) {
|
|
28
|
+
super(`jwt header is invalid: ${JSON.stringify(t)}`), this.name = "JwtHeaderInvalid";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class K extends Error {
|
|
32
|
+
constructor(t) {
|
|
33
|
+
super(`token(${t}) signature mismatched`), this.name = "JwtTokenSignatureMismatched";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
var i = /* @__PURE__ */ ((e) => (e.Encrypt = "encrypt", e.Decrypt = "decrypt", e.Sign = "sign", e.Verify = "verify", e.DeriveKey = "deriveKey", e.DeriveBits = "deriveBits", e.WrapKey = "wrapKey", e.UnwrapKey = "unwrapKey", e))(i || {}), h = /* @__PURE__ */ ((e) => (e.HS256 = "HS256", e.HS384 = "HS384", e.HS512 = "HS512", e.RS256 = "RS256", e.RS384 = "RS384", e.RS512 = "RS512", e.PS256 = "PS256", e.PS384 = "PS384", e.PS512 = "PS512", e.ES256 = "ES256", e.ES384 = "ES384", e.ES512 = "ES512", e.EdDSA = "EdDSA", e))(h || {});
|
|
37
|
+
const m = (e) => E(e.replace(/_|-/g, (t) => ({ _: "/", "-": "+" })[t] ?? t)), y = (e) => R(e).replace(/\/|\+/g, (t) => ({ "/": "_", "+": "-" })[t] ?? t), R = (e) => {
|
|
38
|
+
let t = "";
|
|
39
|
+
const r = new Uint8Array(e);
|
|
40
|
+
for (let n = 0, a = r.length; n < a; n++)
|
|
41
|
+
t += String.fromCharCode(r[n]);
|
|
42
|
+
return btoa(t);
|
|
43
|
+
}, E = (e) => {
|
|
44
|
+
const t = atob(e), r = new Uint8Array(new ArrayBuffer(t.length)), n = t.length / 2;
|
|
45
|
+
for (let a = 0, s = t.length - 1; a <= n; a++, s--)
|
|
46
|
+
r[a] = t.charCodeAt(a), r[s] = t.charCodeAt(s);
|
|
47
|
+
return r;
|
|
48
|
+
}, u = new TextEncoder(), C = new TextDecoder();
|
|
49
|
+
async function I(e, t, r) {
|
|
50
|
+
const n = b(t), a = await D(e, n);
|
|
51
|
+
return await crypto.subtle.sign(n, a, r);
|
|
52
|
+
}
|
|
53
|
+
async function $(e, t, r, n) {
|
|
54
|
+
const a = b(t), s = await B(e, a);
|
|
55
|
+
return await crypto.subtle.verify(a, s, r, n);
|
|
56
|
+
}
|
|
57
|
+
function d(e) {
|
|
58
|
+
return E(
|
|
59
|
+
e.split(`
|
|
60
|
+
`).filter((t) => !t.includes("BEGIN") && !t.includes("END")).join("").replace(/\s/g, "")
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
async function D(e, t) {
|
|
64
|
+
if (!crypto.subtle || !crypto.subtle.importKey)
|
|
65
|
+
throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
|
|
66
|
+
if (v(e)) {
|
|
67
|
+
if (e.type !== "private")
|
|
68
|
+
throw new Error(`unexpected non private key: CryptoKey.type is ${e.type}`);
|
|
69
|
+
return e;
|
|
70
|
+
}
|
|
71
|
+
const r = [i.Sign];
|
|
72
|
+
return typeof e == "object" ? await crypto.subtle.importKey("jwk", e, t, !1, r) : e.includes("PRIVATE") ? await crypto.subtle.importKey("pkcs8", d(e), t, !1, r) : await crypto.subtle.importKey("raw", u.encode(e), t, !1, r);
|
|
73
|
+
}
|
|
74
|
+
async function B(e, t) {
|
|
75
|
+
if (!crypto.subtle || !crypto.subtle.importKey)
|
|
76
|
+
throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
|
|
77
|
+
if (v(e)) {
|
|
78
|
+
if (e.type === "public" || e.type === "secret")
|
|
79
|
+
return e;
|
|
80
|
+
e = await l(e);
|
|
81
|
+
}
|
|
82
|
+
if (typeof e == "string" && e.includes("PRIVATE")) {
|
|
83
|
+
const n = await crypto.subtle.importKey("pkcs8", d(e), t, !0, [i.Sign]);
|
|
84
|
+
e = await l(n);
|
|
85
|
+
}
|
|
86
|
+
const r = [i.Verify];
|
|
87
|
+
return typeof e == "object" ? await crypto.subtle.importKey("jwk", e, t, !1, r) : e.includes("PUBLIC") ? await crypto.subtle.importKey("spki", d(e), t, !1, r) : await crypto.subtle.importKey("raw", u.encode(e), t, !1, r);
|
|
88
|
+
}
|
|
89
|
+
async function l(e) {
|
|
90
|
+
if (e.type !== "private")
|
|
91
|
+
throw new Error(`unexpected key type: ${e.type}`);
|
|
92
|
+
if (!e.extractable)
|
|
93
|
+
throw new Error("unexpected private key is unextractable");
|
|
94
|
+
const t = await crypto.subtle.exportKey("jwk", e), { kty: r } = t, { alg: n, e: a, n: s } = t, { crv: o, x: c, y: S } = t;
|
|
95
|
+
return { kty: r, alg: n, e: a, n: s, crv: o, x: c, y: S, key_ops: [i.Verify] };
|
|
96
|
+
}
|
|
97
|
+
function b(e) {
|
|
98
|
+
switch (e) {
|
|
99
|
+
case "HS256":
|
|
100
|
+
return {
|
|
101
|
+
name: "HMAC",
|
|
102
|
+
hash: {
|
|
103
|
+
name: "SHA-256"
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
case "HS384":
|
|
107
|
+
return {
|
|
108
|
+
name: "HMAC",
|
|
109
|
+
hash: {
|
|
110
|
+
name: "SHA-384"
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
case "HS512":
|
|
114
|
+
return {
|
|
115
|
+
name: "HMAC",
|
|
116
|
+
hash: {
|
|
117
|
+
name: "SHA-512"
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
case "RS256":
|
|
121
|
+
return {
|
|
122
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
123
|
+
hash: {
|
|
124
|
+
name: "SHA-256"
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
case "RS384":
|
|
128
|
+
return {
|
|
129
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
130
|
+
hash: {
|
|
131
|
+
name: "SHA-384"
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
case "RS512":
|
|
135
|
+
return {
|
|
136
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
137
|
+
hash: {
|
|
138
|
+
name: "SHA-512"
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
case "PS256":
|
|
142
|
+
return {
|
|
143
|
+
name: "RSA-PSS",
|
|
144
|
+
hash: {
|
|
145
|
+
name: "SHA-256"
|
|
146
|
+
},
|
|
147
|
+
saltLength: 32
|
|
148
|
+
// 256 >> 3
|
|
149
|
+
};
|
|
150
|
+
case "PS384":
|
|
151
|
+
return {
|
|
152
|
+
name: "RSA-PSS",
|
|
153
|
+
hash: {
|
|
154
|
+
name: "SHA-384"
|
|
155
|
+
},
|
|
156
|
+
saltLength: 48
|
|
157
|
+
// 384 >> 3
|
|
158
|
+
};
|
|
159
|
+
case "PS512":
|
|
160
|
+
return {
|
|
161
|
+
name: "RSA-PSS",
|
|
162
|
+
hash: {
|
|
163
|
+
name: "SHA-512"
|
|
164
|
+
},
|
|
165
|
+
saltLength: 64
|
|
166
|
+
// 512 >> 3,
|
|
167
|
+
};
|
|
168
|
+
case "ES256":
|
|
169
|
+
return {
|
|
170
|
+
name: "ECDSA",
|
|
171
|
+
hash: {
|
|
172
|
+
name: "SHA-256"
|
|
173
|
+
},
|
|
174
|
+
namedCurve: "P-256"
|
|
175
|
+
};
|
|
176
|
+
case "ES384":
|
|
177
|
+
return {
|
|
178
|
+
name: "ECDSA",
|
|
179
|
+
hash: {
|
|
180
|
+
name: "SHA-384"
|
|
181
|
+
},
|
|
182
|
+
namedCurve: "P-384"
|
|
183
|
+
};
|
|
184
|
+
case "ES512":
|
|
185
|
+
return {
|
|
186
|
+
name: "ECDSA",
|
|
187
|
+
hash: {
|
|
188
|
+
name: "SHA-512"
|
|
189
|
+
},
|
|
190
|
+
namedCurve: "P-521"
|
|
191
|
+
};
|
|
192
|
+
case "EdDSA":
|
|
193
|
+
return {
|
|
194
|
+
name: "Ed25519",
|
|
195
|
+
namedCurve: "Ed25519"
|
|
196
|
+
};
|
|
197
|
+
default:
|
|
198
|
+
throw new H(e);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function v(e) {
|
|
202
|
+
return e instanceof CryptoKey;
|
|
203
|
+
}
|
|
204
|
+
const p = (e) => (
|
|
205
|
+
// eslint-disable-next-line
|
|
206
|
+
// @ts-ignore
|
|
207
|
+
y(u.encode(JSON.stringify(e))).replace(/=/g, "")
|
|
208
|
+
), j = (e) => y(e).replace(/=/g, ""), w = (e) => JSON.parse(C.decode(m(e)));
|
|
209
|
+
function T(e) {
|
|
210
|
+
if (typeof e == "object" && e !== null) {
|
|
211
|
+
const t = e;
|
|
212
|
+
return "alg" in t && Object.values(h).includes(t.alg) && (!("typ" in t) || t.typ === "JWT");
|
|
213
|
+
}
|
|
214
|
+
return !1;
|
|
215
|
+
}
|
|
216
|
+
const N = async (e, t, r = "HS256") => {
|
|
217
|
+
const n = p(e), s = `${p({ alg: r, typ: "JWT" })}.${n}`, o = await I(t, r, u.encode(s)), c = j(o);
|
|
218
|
+
return `${s}.${c}`;
|
|
219
|
+
}, W = async (e, t, r = "HS256") => {
|
|
220
|
+
const n = e.split(".");
|
|
221
|
+
if (n.length !== 3)
|
|
222
|
+
throw new f(e);
|
|
223
|
+
const { header: a, payload: s } = A(e);
|
|
224
|
+
if (!T(a))
|
|
225
|
+
throw new g(a);
|
|
226
|
+
const o = Math.floor(Date.now() / 1e3);
|
|
227
|
+
if (s.nbf && s.nbf > o)
|
|
228
|
+
throw new P(e);
|
|
229
|
+
if (s.exp && s.exp <= o)
|
|
230
|
+
throw new J(e);
|
|
231
|
+
if (s.iat && o < s.iat)
|
|
232
|
+
throw new x(o, s.iat);
|
|
233
|
+
const c = e.substring(0, e.lastIndexOf("."));
|
|
234
|
+
if (!await $(t, r, m(n[2]), u.encode(c)))
|
|
235
|
+
throw new K(e);
|
|
236
|
+
return s;
|
|
237
|
+
}, A = (e) => {
|
|
238
|
+
try {
|
|
239
|
+
const [t, r] = e.split("."), n = w(t), a = w(r);
|
|
240
|
+
return {
|
|
241
|
+
header: n,
|
|
242
|
+
payload: a
|
|
243
|
+
};
|
|
244
|
+
} catch {
|
|
245
|
+
throw new f(e);
|
|
246
|
+
}
|
|
247
|
+
}, _ = { decode: A, sign: N, verify: W };
|
|
248
|
+
export {
|
|
249
|
+
A as decode,
|
|
250
|
+
_ as default,
|
|
251
|
+
N as sign,
|
|
252
|
+
W as verify
|
|
253
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aziontech/jwt",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The Azion JWT Library provides utility functions for signing, verifying, and decoding JSON Web Tokens (JWTs).",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"compile": "vite build",
|
|
10
|
+
"lint": "eslint .",
|
|
11
|
+
"lint:fix": "eslint --fix .",
|
|
12
|
+
"prettier": "prettier --write .",
|
|
13
|
+
"prettier:check": "prettier --check .",
|
|
14
|
+
"test": "jest --clearCache && jest"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"require": "./dist/index.cjs",
|
|
20
|
+
"import": "./dist/index.mjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"author": "aziontech",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"package.json"
|
|
28
|
+
],
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@aziontech/vite-config": "workspace:*",
|
|
31
|
+
"@jest/globals": "^29.7.0",
|
|
32
|
+
"@peculiar/webcrypto": "^1.5.0",
|
|
33
|
+
"@types/jest": "^29.5.12",
|
|
34
|
+
"jest": "^29.7.0",
|
|
35
|
+
"ts-jest": "^29.2.2",
|
|
36
|
+
"ts-node": "^10.9.2",
|
|
37
|
+
"typescript": "^5.5.3"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/aziontech/lib.git",
|
|
42
|
+
"directory": "packages/jwt"
|
|
43
|
+
}
|
|
44
|
+
}
|