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.
@@ -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
- if (!this._headers) {
91
- this._headers = new Headers();
92
- for (const [k, v] of Object.entries(this._preparedHeaders)) {
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
  }
@@ -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
- decodeBase64URL: () => decodeBase64URL,
22
+ decodeBase64Url: () => decodeBase64Url,
25
23
  encodeBase64: () => encodeBase64,
26
- encodeBase64URL: () => encodeBase64URL,
27
- utf8ToUint8Array: () => utf8ToUint8Array
24
+ encodeBase64Url: () => encodeBase64Url
28
25
  });
29
26
  module.exports = __toCommonJS(encode_exports);
30
- const encodeBase64 = (str) => {
31
- if (str === null) {
32
- throw new TypeError('1st argument of "encodeBase64" should not be null.');
33
- }
34
- const encoder = new TextEncoder();
35
- const bytes = encoder.encode(str);
36
- return btoa(String.fromCharCode(...bytes));
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
- if (str === null) {
40
- throw new TypeError('1st argument of "decodeBase64" should not be null.');
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
- const text = atob(str);
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
- decodeBase64URL,
48
+ decodeBase64Url,
79
49
  encodeBase64,
80
- encodeBase64URL,
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
- (0, import_encode.utf8ToUint8Array)(secret),
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, (0, import_encode.utf8ToUint8Array)(data));
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 = await (0, import_encode.encodeBase64URL)(JSON.stringify(payload));
89
- const encodedHeader = await (0, import_encode.encodeBase64URL)(JSON.stringify({ alg, typ: "JWT" }));
94
+ const encodedPayload = encodeJwtPart(payload);
95
+ const encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
90
96
  const partialToken = `${encodedHeader}.${encodedPayload}`;
91
- const signature = await (0, import_encode.arrayBufferToBase64URL)(await signing(partialToken, secret, alg));
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
- if (payload.nbf && payload.nbf > Math.floor(Date.now() / 1e3)) {
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 <= Math.floor(Date.now() / 1e3)) {
111
+ if (payload.exp && payload.exp <= now) {
104
112
  throw new import_types2.JwtTokenExpired(token);
105
113
  }
106
- const signature = await (0, import_encode.arrayBufferToBase64URL)(
107
- await signing(tokenParts.slice(0, 2).join("."), secret, alg)
108
- );
109
- if (signature !== tokenParts[2]) {
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 = JSON.parse((0, import_encode.decodeBase64URL)(h));
118
- const payload = JSON.parse((0, import_encode.decodeBase64URL)(p));
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
  });
@@ -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.endsWith("/")) {
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
- if (!this._headers) {
77
- this._headers = new Headers();
78
- for (const [k, v] of Object.entries(this._preparedHeaders)) {
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
  }
@@ -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 encodeBase64: (str: string) => string;
2
- export declare const decodeBase64: (str: string) => string;
3
- export declare const encodeBase64URL: (str: string) => string;
4
- export declare const decodeBase64URL: (str: string) => string;
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
  }
@@ -1,53 +1,25 @@
1
1
  // src/utils/encode.ts
2
- var encodeBase64 = (str) => {
3
- if (str === null) {
4
- throw new TypeError('1st argument of "encodeBase64" should not be null.');
5
- }
6
- const encoder = new TextEncoder();
7
- const bytes = encoder.encode(str);
8
- return btoa(String.fromCharCode(...bytes));
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
- if (str === null) {
12
- throw new TypeError('1st argument of "decodeBase64" should not be null.');
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
- const text = atob(str);
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
- decodeBase64URL,
22
+ decodeBase64Url,
50
23
  encodeBase64,
51
- encodeBase64URL,
52
- utf8ToUint8Array
24
+ encodeBase64Url
53
25
  };
@@ -1,11 +1,6 @@
1
1
  // src/utils/jwt/jwt.ts
2
- import {
3
- utf8ToUint8Array,
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
- utf8ToUint8Array(secret),
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, utf8ToUint8Array(data));
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 = await encodeBase64URL(JSON.stringify(payload));
58
- const encodedHeader = await encodeBase64URL(JSON.stringify({ alg, typ: "JWT" }));
58
+ const encodedPayload = encodeJwtPart(payload);
59
+ const encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
59
60
  const partialToken = `${encodedHeader}.${encodedPayload}`;
60
- const signature = await arrayBufferToBase64URL(await signing(partialToken, secret, alg));
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
- if (payload.nbf && payload.nbf > Math.floor(Date.now() / 1e3)) {
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 <= Math.floor(Date.now() / 1e3)) {
75
+ if (payload.exp && payload.exp <= now) {
73
76
  throw new JwtTokenExpired(token);
74
77
  }
75
- const signature = await arrayBufferToBase64URL(
76
- await signing(tokenParts.slice(0, 2).join("."), secret, alg)
77
- );
78
- if (signature !== tokenParts[2]) {
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 = JSON.parse(decodeBase64URL(h));
87
- const payload = JSON.parse(decodeBase64URL(p));
92
+ const header = decodeJwtPart(h);
93
+ const payload = decodeJwtPart(p);
88
94
  return {
89
95
  header,
90
96
  payload
@@ -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.endsWith("/")) {
60
+ if (strict === false && /.+\/$/.test(result)) {
61
61
  return result.slice(0, -1);
62
62
  }
63
63
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "3.1.0",
3
+ "version": "3.1.2",
4
4
  "description": "Ultrafast web framework for the Edge",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",