hono 3.1.0 → 3.1.2
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/dist/cjs/context.js +4 -5
- package/dist/cjs/middleware/basic-auth/index.js +2 -1
- package/dist/cjs/utils/encode.js +18 -49
- package/dist/cjs/utils/jwt/jwt.js +24 -13
- package/dist/cjs/utils/jwt/types.js +8 -0
- package/dist/cjs/utils/url.js +1 -1
- package/dist/context.js +4 -5
- package/dist/middleware/basic-auth/index.js +2 -1
- package/dist/types/hono.d.ts +1 -1
- package/dist/types/utils/encode.d.ts +4 -7
- package/dist/types/utils/jwt/types.d.ts +4 -1
- package/dist/utils/encode.js +16 -44
- package/dist/utils/jwt/jwt.js +26 -20
- package/dist/utils/jwt/types.js +7 -0
- package/dist/utils/url.js +1 -1
- package/package.json +1 -1
package/dist/cjs/context.js
CHANGED
|
@@ -39,6 +39,7 @@ class Context {
|
|
|
39
39
|
if (options?.append) {
|
|
40
40
|
if (!this._headers) {
|
|
41
41
|
this._headers = new Headers(this._preparedHeaders);
|
|
42
|
+
this._preparedHeaders = {};
|
|
42
43
|
}
|
|
43
44
|
this._headers.append(name, value);
|
|
44
45
|
} else {
|
|
@@ -87,11 +88,9 @@ class Context {
|
|
|
87
88
|
}
|
|
88
89
|
const status = arg ?? this._status;
|
|
89
90
|
this._preparedHeaders ?? (this._preparedHeaders = {});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
this._headers.set(k, v);
|
|
94
|
-
}
|
|
91
|
+
this._headers ?? (this._headers = new Headers());
|
|
92
|
+
for (const [k, v] of Object.entries(this._preparedHeaders)) {
|
|
93
|
+
this._headers.set(k, v);
|
|
95
94
|
}
|
|
96
95
|
if (this._res) {
|
|
97
96
|
this._res.headers.forEach((v, k) => {
|
|
@@ -26,12 +26,13 @@ var import_buffer = require("../../utils/buffer");
|
|
|
26
26
|
var import_encode = require("../../utils/encode");
|
|
27
27
|
const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
28
28
|
const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
29
|
+
const utf8Decoder = new TextDecoder();
|
|
29
30
|
const auth = (req) => {
|
|
30
31
|
const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
|
|
31
32
|
if (!match) {
|
|
32
33
|
return void 0;
|
|
33
34
|
}
|
|
34
|
-
const userPass = USER_PASS_REGEXP.exec((0, import_encode.decodeBase64)(match[1]));
|
|
35
|
+
const userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode((0, import_encode.decodeBase64)(match[1])));
|
|
35
36
|
if (!userPass) {
|
|
36
37
|
return void 0;
|
|
37
38
|
}
|
package/dist/cjs/utils/encode.js
CHANGED
|
@@ -18,65 +18,34 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var encode_exports = {};
|
|
20
20
|
__export(encode_exports, {
|
|
21
|
-
arrayBufferToBase64: () => arrayBufferToBase64,
|
|
22
|
-
arrayBufferToBase64URL: () => arrayBufferToBase64URL,
|
|
23
21
|
decodeBase64: () => decodeBase64,
|
|
24
|
-
|
|
22
|
+
decodeBase64Url: () => decodeBase64Url,
|
|
25
23
|
encodeBase64: () => encodeBase64,
|
|
26
|
-
|
|
27
|
-
utf8ToUint8Array: () => utf8ToUint8Array
|
|
24
|
+
encodeBase64Url: () => encodeBase64Url
|
|
28
25
|
});
|
|
29
26
|
module.exports = __toCommonJS(encode_exports);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
return btoa(
|
|
27
|
+
const decodeBase64Url = (str) => {
|
|
28
|
+
return decodeBase64(str.replace(/_|-/g, (m) => ({ _: "/", "-": "+" })[m] ?? m));
|
|
29
|
+
};
|
|
30
|
+
const encodeBase64Url = (buf) => encodeBase64(buf).replace(/\/|\+/g, (m) => ({ "/": "_", "+": "-" })[m] ?? m);
|
|
31
|
+
const encodeBase64 = (buf) => {
|
|
32
|
+
const binary = String.fromCharCode(...new Uint8Array(buf));
|
|
33
|
+
return btoa(binary);
|
|
37
34
|
};
|
|
38
35
|
const decodeBase64 = (str) => {
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
const binary = atob(str);
|
|
37
|
+
const bytes = new Uint8Array(new ArrayBuffer(binary.length));
|
|
38
|
+
const half = binary.length / 2;
|
|
39
|
+
for (let i = 0, j = binary.length - 1; i <= half; i++, j--) {
|
|
40
|
+
bytes[i] = binary.charCodeAt(i);
|
|
41
|
+
bytes[j] = binary.charCodeAt(j);
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
-
const bytes = new Uint8Array(text.split("").map((c) => c.charCodeAt(0)));
|
|
44
|
-
const decoder = new TextDecoder();
|
|
45
|
-
return decoder.decode(bytes);
|
|
46
|
-
};
|
|
47
|
-
const encodeBase64URL = (str) => {
|
|
48
|
-
return encodeBase64(str).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
49
|
-
};
|
|
50
|
-
const decodeBase64URL = (str) => {
|
|
51
|
-
const pad = (s) => {
|
|
52
|
-
const diff = s.length % 4;
|
|
53
|
-
if (diff === 2) {
|
|
54
|
-
return `${s}==`;
|
|
55
|
-
}
|
|
56
|
-
if (diff === 3) {
|
|
57
|
-
return `${s}=`;
|
|
58
|
-
}
|
|
59
|
-
return s;
|
|
60
|
-
};
|
|
61
|
-
return decodeBase64(pad(str).replace(/-/g, "+").replace("_", "/"));
|
|
62
|
-
};
|
|
63
|
-
const utf8ToUint8Array = (str) => {
|
|
64
|
-
const encoder = new TextEncoder();
|
|
65
|
-
return encoder.encode(str);
|
|
66
|
-
};
|
|
67
|
-
const arrayBufferToBase64 = async (buf) => {
|
|
68
|
-
return btoa(String.fromCharCode(...new Uint8Array(buf)));
|
|
69
|
-
};
|
|
70
|
-
const arrayBufferToBase64URL = async (buf) => {
|
|
71
|
-
return (await arrayBufferToBase64(buf)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
43
|
+
return bytes;
|
|
72
44
|
};
|
|
73
45
|
// Annotate the CommonJS export names for ESM import in node:
|
|
74
46
|
0 && (module.exports = {
|
|
75
|
-
arrayBufferToBase64,
|
|
76
|
-
arrayBufferToBase64URL,
|
|
77
47
|
decodeBase64,
|
|
78
|
-
|
|
48
|
+
decodeBase64Url,
|
|
79
49
|
encodeBase64,
|
|
80
|
-
|
|
81
|
-
utf8ToUint8Array
|
|
50
|
+
encodeBase64Url
|
|
82
51
|
});
|
|
@@ -44,6 +44,11 @@ var CryptoKeyUsage = /* @__PURE__ */ ((CryptoKeyUsage2) => {
|
|
|
44
44
|
CryptoKeyUsage2["UnwrapKey"] = "unwrapKey";
|
|
45
45
|
return CryptoKeyUsage2;
|
|
46
46
|
})(CryptoKeyUsage || {});
|
|
47
|
+
const utf8Encoder = new TextEncoder();
|
|
48
|
+
const utf8Decoder = new TextDecoder();
|
|
49
|
+
const encodeJwtPart = (part) => (0, import_encode.encodeBase64Url)(utf8Encoder.encode(JSON.stringify(part))).replace(/=/g, "");
|
|
50
|
+
const encodeSignaturePart = (buf) => (0, import_encode.encodeBase64Url)(buf).replace(/=/g, "");
|
|
51
|
+
const decodeJwtPart = (part) => JSON.parse(utf8Decoder.decode((0, import_encode.decodeBase64Url)(part)));
|
|
47
52
|
const param = (name) => {
|
|
48
53
|
switch (name.toUpperCase()) {
|
|
49
54
|
case "HS256":
|
|
@@ -75,20 +80,22 @@ const signing = async (data, secret, alg = import_types.AlgorithmTypes.HS256) =>
|
|
|
75
80
|
if (!crypto.subtle || !crypto.subtle.importKey) {
|
|
76
81
|
throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
|
|
77
82
|
}
|
|
83
|
+
const utf8Encoder2 = new TextEncoder();
|
|
78
84
|
const cryptoKey = await crypto.subtle.importKey(
|
|
79
85
|
"raw" /* RAW */,
|
|
80
|
-
|
|
86
|
+
utf8Encoder2.encode(secret),
|
|
81
87
|
param(alg),
|
|
82
88
|
false,
|
|
83
89
|
["sign" /* Sign */]
|
|
84
90
|
);
|
|
85
|
-
return await crypto.subtle.sign(param(alg), cryptoKey,
|
|
91
|
+
return await crypto.subtle.sign(param(alg), cryptoKey, utf8Encoder2.encode(data));
|
|
86
92
|
};
|
|
87
93
|
const sign = async (payload, secret, alg = import_types.AlgorithmTypes.HS256) => {
|
|
88
|
-
const encodedPayload =
|
|
89
|
-
const encodedHeader =
|
|
94
|
+
const encodedPayload = encodeJwtPart(payload);
|
|
95
|
+
const encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
|
|
90
96
|
const partialToken = `${encodedHeader}.${encodedPayload}`;
|
|
91
|
-
const
|
|
97
|
+
const signaturePart = await signing(partialToken, secret, alg);
|
|
98
|
+
const signature = encodeSignaturePart(signaturePart);
|
|
92
99
|
return `${partialToken}.${signature}`;
|
|
93
100
|
};
|
|
94
101
|
const verify = async (token, secret, alg = import_types.AlgorithmTypes.HS256) => {
|
|
@@ -97,16 +104,20 @@ const verify = async (token, secret, alg = import_types.AlgorithmTypes.HS256) =>
|
|
|
97
104
|
throw new import_types2.JwtTokenInvalid(token);
|
|
98
105
|
}
|
|
99
106
|
const { payload } = decode(token);
|
|
100
|
-
|
|
107
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
108
|
+
if (payload.nbf && payload.nbf > now) {
|
|
101
109
|
throw new import_types2.JwtTokenNotBefore(token);
|
|
102
110
|
}
|
|
103
|
-
if (payload.exp && payload.exp <=
|
|
111
|
+
if (payload.exp && payload.exp <= now) {
|
|
104
112
|
throw new import_types2.JwtTokenExpired(token);
|
|
105
113
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
if (payload.iat && now < payload.iat) {
|
|
115
|
+
throw new import_types.JwtTokenIssuedAt(now, payload.iat);
|
|
116
|
+
}
|
|
117
|
+
const signaturePart = tokenParts.slice(0, 2).join(".");
|
|
118
|
+
const signature = await signing(signaturePart, secret, alg);
|
|
119
|
+
const encodedSignature = encodeSignaturePart(signature);
|
|
120
|
+
if (encodedSignature !== tokenParts[2]) {
|
|
110
121
|
throw new import_types2.JwtTokenSignatureMismatched(token);
|
|
111
122
|
}
|
|
112
123
|
return true;
|
|
@@ -114,8 +125,8 @@ const verify = async (token, secret, alg = import_types.AlgorithmTypes.HS256) =>
|
|
|
114
125
|
const decode = (token) => {
|
|
115
126
|
try {
|
|
116
127
|
const [h, p] = token.split(".");
|
|
117
|
-
const header =
|
|
118
|
-
const payload =
|
|
128
|
+
const header = decodeJwtPart(h);
|
|
129
|
+
const payload = decodeJwtPart(p);
|
|
119
130
|
return {
|
|
120
131
|
header,
|
|
121
132
|
payload
|
|
@@ -23,6 +23,7 @@ __export(types_exports, {
|
|
|
23
23
|
JwtAlorithmNotImplemented: () => JwtAlorithmNotImplemented,
|
|
24
24
|
JwtTokenExpired: () => JwtTokenExpired,
|
|
25
25
|
JwtTokenInvalid: () => JwtTokenInvalid,
|
|
26
|
+
JwtTokenIssuedAt: () => JwtTokenIssuedAt,
|
|
26
27
|
JwtTokenNotBefore: () => JwtTokenNotBefore,
|
|
27
28
|
JwtTokenSignatureMismatched: () => JwtTokenSignatureMismatched
|
|
28
29
|
});
|
|
@@ -52,6 +53,12 @@ class JwtTokenExpired extends Error {
|
|
|
52
53
|
this.name = "JwtTokenExpired";
|
|
53
54
|
}
|
|
54
55
|
}
|
|
56
|
+
class JwtTokenIssuedAt extends Error {
|
|
57
|
+
constructor(currentTimestamp, iat) {
|
|
58
|
+
super(`Incorrect "iat" claim must be a older than "${currentTimestamp}" (iat: "${iat}")`);
|
|
59
|
+
this.name = "JwtTokenIssuedAt";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
55
62
|
class JwtTokenSignatureMismatched extends Error {
|
|
56
63
|
constructor(token) {
|
|
57
64
|
super(`token(${token}) signature mismatched`);
|
|
@@ -71,6 +78,7 @@ var AlgorithmTypes = /* @__PURE__ */ ((AlgorithmTypes2) => {
|
|
|
71
78
|
JwtAlorithmNotImplemented,
|
|
72
79
|
JwtTokenExpired,
|
|
73
80
|
JwtTokenInvalid,
|
|
81
|
+
JwtTokenIssuedAt,
|
|
74
82
|
JwtTokenNotBefore,
|
|
75
83
|
JwtTokenSignatureMismatched
|
|
76
84
|
});
|
package/dist/cjs/utils/url.js
CHANGED
|
@@ -87,7 +87,7 @@ const getPattern = (label) => {
|
|
|
87
87
|
const getPathFromURL = (url, strict = true) => {
|
|
88
88
|
const queryIndex = url.indexOf("?", 8);
|
|
89
89
|
const result = url.substring(url.indexOf("/", 8), queryIndex === -1 ? url.length : queryIndex);
|
|
90
|
-
if (strict === false && result
|
|
90
|
+
if (strict === false && /.+\/$/.test(result)) {
|
|
91
91
|
return result.slice(0, -1);
|
|
92
92
|
}
|
|
93
93
|
return result;
|
package/dist/context.js
CHANGED
|
@@ -25,6 +25,7 @@ var Context = class {
|
|
|
25
25
|
if (options?.append) {
|
|
26
26
|
if (!this._headers) {
|
|
27
27
|
this._headers = new Headers(this._preparedHeaders);
|
|
28
|
+
this._preparedHeaders = {};
|
|
28
29
|
}
|
|
29
30
|
this._headers.append(name, value);
|
|
30
31
|
} else {
|
|
@@ -73,11 +74,9 @@ var Context = class {
|
|
|
73
74
|
}
|
|
74
75
|
const status = arg ?? this._status;
|
|
75
76
|
this._preparedHeaders ?? (this._preparedHeaders = {});
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this._headers.set(k, v);
|
|
80
|
-
}
|
|
77
|
+
this._headers ?? (this._headers = new Headers());
|
|
78
|
+
for (const [k, v] of Object.entries(this._preparedHeaders)) {
|
|
79
|
+
this._headers.set(k, v);
|
|
81
80
|
}
|
|
82
81
|
if (this._res) {
|
|
83
82
|
this._res.headers.forEach((v, k) => {
|
|
@@ -4,12 +4,13 @@ import { timingSafeEqual } from "../../utils/buffer.js";
|
|
|
4
4
|
import { decodeBase64 } from "../../utils/encode.js";
|
|
5
5
|
var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
6
6
|
var USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
7
|
+
var utf8Decoder = new TextDecoder();
|
|
7
8
|
var auth = (req) => {
|
|
8
9
|
const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
|
|
9
10
|
if (!match) {
|
|
10
11
|
return void 0;
|
|
11
12
|
}
|
|
12
|
-
const userPass = USER_PASS_REGEXP.exec(decodeBase64(match[1]));
|
|
13
|
+
const userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match[1])));
|
|
13
14
|
if (!userPass) {
|
|
14
15
|
return void 0;
|
|
15
16
|
}
|
package/dist/types/hono.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare class Hono<E extends Env = Env, S = {}, BasePath extends string =
|
|
|
31
31
|
private clone;
|
|
32
32
|
private notFoundHandler;
|
|
33
33
|
private errorHandler;
|
|
34
|
-
route<SubPath extends string, SubEnv extends Env, SubSchema>(path: SubPath, app: Hono<SubEnv, SubSchema>): Hono<E, RemoveBlankRecord<MergeSchemaPath<SubSchema, SubPath> | S>, BasePath>;
|
|
34
|
+
route<SubPath extends string, SubEnv extends Env, SubSchema, SubBasePath extends string>(path: SubPath, app: Hono<SubEnv, SubSchema, SubBasePath>): Hono<E, RemoveBlankRecord<MergeSchemaPath<SubSchema, SubPath> | S>, BasePath>;
|
|
35
35
|
/** @deprecated
|
|
36
36
|
* Use `basePath` instead of `route` with one argument.
|
|
37
37
|
* The `route` with one argument has been removed in v4.
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
5
|
-
export declare const utf8ToUint8Array: (str: string) => Uint8Array;
|
|
6
|
-
export declare const arrayBufferToBase64: (buf: ArrayBuffer) => Promise<string>;
|
|
7
|
-
export declare const arrayBufferToBase64URL: (buf: ArrayBuffer) => Promise<string>;
|
|
1
|
+
export declare const decodeBase64Url: (str: string) => Uint8Array;
|
|
2
|
+
export declare const encodeBase64Url: (buf: ArrayBufferLike) => string;
|
|
3
|
+
export declare const encodeBase64: (buf: ArrayBufferLike) => string;
|
|
4
|
+
export declare const decodeBase64: (str: string) => Uint8Array;
|
|
@@ -4,7 +4,7 @@ export declare class JwtAlgorithmNotImplemented extends Error {
|
|
|
4
4
|
/**
|
|
5
5
|
* Export for backward compatibility
|
|
6
6
|
* @deprecated Use JwtAlgorithmNotImplemented instead
|
|
7
|
-
**/
|
|
7
|
+
**/
|
|
8
8
|
export declare const JwtAlorithmNotImplemented: typeof JwtAlgorithmNotImplemented;
|
|
9
9
|
export declare class JwtTokenInvalid extends Error {
|
|
10
10
|
constructor(token: string);
|
|
@@ -15,6 +15,9 @@ export declare class JwtTokenNotBefore extends Error {
|
|
|
15
15
|
export declare class JwtTokenExpired extends Error {
|
|
16
16
|
constructor(token: string);
|
|
17
17
|
}
|
|
18
|
+
export declare class JwtTokenIssuedAt extends Error {
|
|
19
|
+
constructor(currentTimestamp: number, iat: number);
|
|
20
|
+
}
|
|
18
21
|
export declare class JwtTokenSignatureMismatched extends Error {
|
|
19
22
|
constructor(token: string);
|
|
20
23
|
}
|
package/dist/utils/encode.js
CHANGED
|
@@ -1,53 +1,25 @@
|
|
|
1
1
|
// src/utils/encode.ts
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
return btoa(
|
|
2
|
+
var decodeBase64Url = (str) => {
|
|
3
|
+
return decodeBase64(str.replace(/_|-/g, (m) => ({ _: "/", "-": "+" })[m] ?? m));
|
|
4
|
+
};
|
|
5
|
+
var encodeBase64Url = (buf) => encodeBase64(buf).replace(/\/|\+/g, (m) => ({ "/": "_", "+": "-" })[m] ?? m);
|
|
6
|
+
var encodeBase64 = (buf) => {
|
|
7
|
+
const binary = String.fromCharCode(...new Uint8Array(buf));
|
|
8
|
+
return btoa(binary);
|
|
9
9
|
};
|
|
10
10
|
var decodeBase64 = (str) => {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const binary = atob(str);
|
|
12
|
+
const bytes = new Uint8Array(new ArrayBuffer(binary.length));
|
|
13
|
+
const half = binary.length / 2;
|
|
14
|
+
for (let i = 0, j = binary.length - 1; i <= half; i++, j--) {
|
|
15
|
+
bytes[i] = binary.charCodeAt(i);
|
|
16
|
+
bytes[j] = binary.charCodeAt(j);
|
|
13
17
|
}
|
|
14
|
-
|
|
15
|
-
const bytes = new Uint8Array(text.split("").map((c) => c.charCodeAt(0)));
|
|
16
|
-
const decoder = new TextDecoder();
|
|
17
|
-
return decoder.decode(bytes);
|
|
18
|
-
};
|
|
19
|
-
var encodeBase64URL = (str) => {
|
|
20
|
-
return encodeBase64(str).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
21
|
-
};
|
|
22
|
-
var decodeBase64URL = (str) => {
|
|
23
|
-
const pad = (s) => {
|
|
24
|
-
const diff = s.length % 4;
|
|
25
|
-
if (diff === 2) {
|
|
26
|
-
return `${s}==`;
|
|
27
|
-
}
|
|
28
|
-
if (diff === 3) {
|
|
29
|
-
return `${s}=`;
|
|
30
|
-
}
|
|
31
|
-
return s;
|
|
32
|
-
};
|
|
33
|
-
return decodeBase64(pad(str).replace(/-/g, "+").replace("_", "/"));
|
|
34
|
-
};
|
|
35
|
-
var utf8ToUint8Array = (str) => {
|
|
36
|
-
const encoder = new TextEncoder();
|
|
37
|
-
return encoder.encode(str);
|
|
38
|
-
};
|
|
39
|
-
var arrayBufferToBase64 = async (buf) => {
|
|
40
|
-
return btoa(String.fromCharCode(...new Uint8Array(buf)));
|
|
41
|
-
};
|
|
42
|
-
var arrayBufferToBase64URL = async (buf) => {
|
|
43
|
-
return (await arrayBufferToBase64(buf)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
18
|
+
return bytes;
|
|
44
19
|
};
|
|
45
20
|
export {
|
|
46
|
-
arrayBufferToBase64,
|
|
47
|
-
arrayBufferToBase64URL,
|
|
48
21
|
decodeBase64,
|
|
49
|
-
|
|
22
|
+
decodeBase64Url,
|
|
50
23
|
encodeBase64,
|
|
51
|
-
|
|
52
|
-
utf8ToUint8Array
|
|
24
|
+
encodeBase64Url
|
|
53
25
|
};
|
package/dist/utils/jwt/jwt.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
// src/utils/jwt/jwt.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
encodeBase64URL,
|
|
5
|
-
arrayBufferToBase64URL,
|
|
6
|
-
decodeBase64URL
|
|
7
|
-
} from "../../utils/encode.js";
|
|
8
|
-
import { AlgorithmTypes } from "./types.js";
|
|
2
|
+
import { encodeBase64Url, decodeBase64Url } from "../../utils/encode.js";
|
|
3
|
+
import { AlgorithmTypes, JwtTokenIssuedAt } from "./types.js";
|
|
9
4
|
import {
|
|
10
5
|
JwtTokenInvalid,
|
|
11
6
|
JwtTokenNotBefore,
|
|
@@ -13,6 +8,11 @@ import {
|
|
|
13
8
|
JwtTokenSignatureMismatched,
|
|
14
9
|
JwtAlgorithmNotImplemented
|
|
15
10
|
} from "./types.js";
|
|
11
|
+
var utf8Encoder = new TextEncoder();
|
|
12
|
+
var utf8Decoder = new TextDecoder();
|
|
13
|
+
var encodeJwtPart = (part) => encodeBase64Url(utf8Encoder.encode(JSON.stringify(part))).replace(/=/g, "");
|
|
14
|
+
var encodeSignaturePart = (buf) => encodeBase64Url(buf).replace(/=/g, "");
|
|
15
|
+
var decodeJwtPart = (part) => JSON.parse(utf8Decoder.decode(decodeBase64Url(part)));
|
|
16
16
|
var param = (name) => {
|
|
17
17
|
switch (name.toUpperCase()) {
|
|
18
18
|
case "HS256":
|
|
@@ -44,20 +44,22 @@ var signing = async (data, secret, alg = AlgorithmTypes.HS256) => {
|
|
|
44
44
|
if (!crypto.subtle || !crypto.subtle.importKey) {
|
|
45
45
|
throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
|
|
46
46
|
}
|
|
47
|
+
const utf8Encoder2 = new TextEncoder();
|
|
47
48
|
const cryptoKey = await crypto.subtle.importKey(
|
|
48
49
|
"raw" /* RAW */,
|
|
49
|
-
|
|
50
|
+
utf8Encoder2.encode(secret),
|
|
50
51
|
param(alg),
|
|
51
52
|
false,
|
|
52
53
|
["sign" /* Sign */]
|
|
53
54
|
);
|
|
54
|
-
return await crypto.subtle.sign(param(alg), cryptoKey,
|
|
55
|
+
return await crypto.subtle.sign(param(alg), cryptoKey, utf8Encoder2.encode(data));
|
|
55
56
|
};
|
|
56
57
|
var sign = async (payload, secret, alg = AlgorithmTypes.HS256) => {
|
|
57
|
-
const encodedPayload =
|
|
58
|
-
const encodedHeader =
|
|
58
|
+
const encodedPayload = encodeJwtPart(payload);
|
|
59
|
+
const encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
|
|
59
60
|
const partialToken = `${encodedHeader}.${encodedPayload}`;
|
|
60
|
-
const
|
|
61
|
+
const signaturePart = await signing(partialToken, secret, alg);
|
|
62
|
+
const signature = encodeSignaturePart(signaturePart);
|
|
61
63
|
return `${partialToken}.${signature}`;
|
|
62
64
|
};
|
|
63
65
|
var verify = async (token, secret, alg = AlgorithmTypes.HS256) => {
|
|
@@ -66,16 +68,20 @@ var verify = async (token, secret, alg = AlgorithmTypes.HS256) => {
|
|
|
66
68
|
throw new JwtTokenInvalid(token);
|
|
67
69
|
}
|
|
68
70
|
const { payload } = decode(token);
|
|
69
|
-
|
|
71
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
72
|
+
if (payload.nbf && payload.nbf > now) {
|
|
70
73
|
throw new JwtTokenNotBefore(token);
|
|
71
74
|
}
|
|
72
|
-
if (payload.exp && payload.exp <=
|
|
75
|
+
if (payload.exp && payload.exp <= now) {
|
|
73
76
|
throw new JwtTokenExpired(token);
|
|
74
77
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
if (payload.iat && now < payload.iat) {
|
|
79
|
+
throw new JwtTokenIssuedAt(now, payload.iat);
|
|
80
|
+
}
|
|
81
|
+
const signaturePart = tokenParts.slice(0, 2).join(".");
|
|
82
|
+
const signature = await signing(signaturePart, secret, alg);
|
|
83
|
+
const encodedSignature = encodeSignaturePart(signature);
|
|
84
|
+
if (encodedSignature !== tokenParts[2]) {
|
|
79
85
|
throw new JwtTokenSignatureMismatched(token);
|
|
80
86
|
}
|
|
81
87
|
return true;
|
|
@@ -83,8 +89,8 @@ var verify = async (token, secret, alg = AlgorithmTypes.HS256) => {
|
|
|
83
89
|
var decode = (token) => {
|
|
84
90
|
try {
|
|
85
91
|
const [h, p] = token.split(".");
|
|
86
|
-
const header =
|
|
87
|
-
const payload =
|
|
92
|
+
const header = decodeJwtPart(h);
|
|
93
|
+
const payload = decodeJwtPart(p);
|
|
88
94
|
return {
|
|
89
95
|
header,
|
|
90
96
|
payload
|
package/dist/utils/jwt/types.js
CHANGED
|
@@ -24,6 +24,12 @@ var JwtTokenExpired = class extends Error {
|
|
|
24
24
|
this.name = "JwtTokenExpired";
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
|
+
var JwtTokenIssuedAt = class extends Error {
|
|
28
|
+
constructor(currentTimestamp, iat) {
|
|
29
|
+
super(`Incorrect "iat" claim must be a older than "${currentTimestamp}" (iat: "${iat}")`);
|
|
30
|
+
this.name = "JwtTokenIssuedAt";
|
|
31
|
+
}
|
|
32
|
+
};
|
|
27
33
|
var JwtTokenSignatureMismatched = class extends Error {
|
|
28
34
|
constructor(token) {
|
|
29
35
|
super(`token(${token}) signature mismatched`);
|
|
@@ -42,6 +48,7 @@ export {
|
|
|
42
48
|
JwtAlorithmNotImplemented,
|
|
43
49
|
JwtTokenExpired,
|
|
44
50
|
JwtTokenInvalid,
|
|
51
|
+
JwtTokenIssuedAt,
|
|
45
52
|
JwtTokenNotBefore,
|
|
46
53
|
JwtTokenSignatureMismatched
|
|
47
54
|
};
|
package/dist/utils/url.js
CHANGED
|
@@ -57,7 +57,7 @@ var getPattern = (label) => {
|
|
|
57
57
|
var getPathFromURL = (url, strict = true) => {
|
|
58
58
|
const queryIndex = url.indexOf("?", 8);
|
|
59
59
|
const result = url.substring(url.indexOf("/", 8), queryIndex === -1 ? url.length : queryIndex);
|
|
60
|
-
if (strict === false && result
|
|
60
|
+
if (strict === false && /.+\/$/.test(result)) {
|
|
61
61
|
return result.slice(0, -1);
|
|
62
62
|
}
|
|
63
63
|
return result;
|