hono 4.2.0-rc.1 → 4.2.1
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/middleware/basic-auth/index.js +22 -9
- package/dist/cjs/middleware/bearer-auth/index.js +4 -2
- package/dist/cjs/middleware/jwt/index.js +6 -5
- package/dist/cjs/test-utils/setup-vitest.js +5 -3
- package/dist/cjs/utils/jwt/jws.js +2 -2
- package/dist/middleware/basic-auth/index.js +22 -9
- package/dist/middleware/bearer-auth/index.js +4 -2
- package/dist/middleware/jwt/index.js +6 -5
- package/dist/test-utils/setup-vitest.js +5 -3
- package/dist/types/middleware/basic-auth/index.d.ts +9 -2
- package/dist/types/middleware/bearer-auth/index.d.ts +10 -2
- package/dist/types/middleware/jwt/index.d.ts +2 -1
- package/dist/utils/jwt/jws.js +1 -1
- package/package.json +1 -1
- package/dist/types/helper.d.ts +0 -12
|
@@ -43,25 +43,38 @@ const auth = (req) => {
|
|
|
43
43
|
return { username: userPass[1], password: userPass[2] };
|
|
44
44
|
};
|
|
45
45
|
const basicAuth = (options, ...users) => {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
const usernamePasswordInOptions = "username" in options && "password" in options;
|
|
47
|
+
const verifyUserInOptions = "verifyUser" in options;
|
|
48
|
+
if (!(usernamePasswordInOptions || verifyUserInOptions)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
'basic auth middleware requires options for "username and password" or "verifyUser"'
|
|
51
|
+
);
|
|
48
52
|
}
|
|
49
53
|
if (!options.realm) {
|
|
50
54
|
options.realm = "Secure Area";
|
|
51
55
|
}
|
|
52
|
-
|
|
56
|
+
if (usernamePasswordInOptions) {
|
|
57
|
+
users.unshift({ username: options.username, password: options.password });
|
|
58
|
+
}
|
|
53
59
|
return async function basicAuth2(ctx, next) {
|
|
54
60
|
const requestUser = auth(ctx.req);
|
|
55
61
|
if (requestUser) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
(0, import_buffer.timingSafeEqual)(user.username, requestUser.username, options.hashFunction),
|
|
59
|
-
(0, import_buffer.timingSafeEqual)(user.password, requestUser.password, options.hashFunction)
|
|
60
|
-
]);
|
|
61
|
-
if (usernameEqual && passwordEqual) {
|
|
62
|
+
if (verifyUserInOptions) {
|
|
63
|
+
if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
|
|
62
64
|
await next();
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
67
|
+
} else {
|
|
68
|
+
for (const user of users) {
|
|
69
|
+
const [usernameEqual, passwordEqual] = await Promise.all([
|
|
70
|
+
(0, import_buffer.timingSafeEqual)(user.username, requestUser.username, options.hashFunction),
|
|
71
|
+
(0, import_buffer.timingSafeEqual)(user.password, requestUser.password, options.hashFunction)
|
|
72
|
+
]);
|
|
73
|
+
if (usernameEqual && passwordEqual) {
|
|
74
|
+
await next();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
80
|
const res = new Response("Unauthorized", {
|
|
@@ -26,7 +26,7 @@ var import_buffer = require("../../utils/buffer");
|
|
|
26
26
|
const TOKEN_STRINGS = "[A-Za-z0-9._~+/-]+=*";
|
|
27
27
|
const PREFIX = "Bearer";
|
|
28
28
|
const bearerAuth = (options) => {
|
|
29
|
-
if (!options
|
|
29
|
+
if (!("token" in options || "verifyToken" in options)) {
|
|
30
30
|
throw new Error('bearer auth middleware requires options for "token"');
|
|
31
31
|
}
|
|
32
32
|
if (!options.realm) {
|
|
@@ -59,7 +59,9 @@ const bearerAuth = (options) => {
|
|
|
59
59
|
throw new import_http_exception.HTTPException(400, { res });
|
|
60
60
|
} else {
|
|
61
61
|
let equal = false;
|
|
62
|
-
if (
|
|
62
|
+
if ("verifyToken" in options) {
|
|
63
|
+
equal = await options.verifyToken(match[1], c);
|
|
64
|
+
} else if (typeof options.token === "string") {
|
|
63
65
|
equal = await (0, import_buffer.timingSafeEqual)(options.token, match[1], options.hashFunction);
|
|
64
66
|
} else if (Array.isArray(options.token) && options.token.length > 0) {
|
|
65
67
|
for (const token of options.token) {
|
|
@@ -68,21 +68,22 @@ const jwt = (options) => {
|
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
70
|
let payload;
|
|
71
|
-
let
|
|
71
|
+
let cause;
|
|
72
72
|
try {
|
|
73
73
|
payload = await import_jwt.Jwt.verify(token, options.secret, options.alg);
|
|
74
74
|
} catch (e) {
|
|
75
|
-
|
|
75
|
+
cause = e;
|
|
76
76
|
}
|
|
77
77
|
if (!payload) {
|
|
78
78
|
throw new import_http_exception.HTTPException(401, {
|
|
79
|
-
message:
|
|
79
|
+
message: "Unauthorized",
|
|
80
80
|
res: unauthorizedResponse({
|
|
81
81
|
ctx,
|
|
82
82
|
error: "invalid_token",
|
|
83
|
-
statusText:
|
|
83
|
+
statusText: "Unauthorized",
|
|
84
84
|
errDescription: "token verification failure"
|
|
85
|
-
})
|
|
85
|
+
}),
|
|
86
|
+
cause
|
|
86
87
|
});
|
|
87
88
|
}
|
|
88
89
|
ctx.set("jwtPayload", payload);
|
|
@@ -17,10 +17,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
17
17
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
18
18
|
mod
|
|
19
19
|
));
|
|
20
|
-
var
|
|
20
|
+
var nodeCrypto = __toESM(require("node:crypto"), 1);
|
|
21
21
|
var import_vitest = require("vitest");
|
|
22
|
-
|
|
23
|
-
import_vitest.vi.stubGlobal("
|
|
22
|
+
if (!globalThis.crypto) {
|
|
23
|
+
import_vitest.vi.stubGlobal("crypto", nodeCrypto);
|
|
24
|
+
import_vitest.vi.stubGlobal("CryptoKey", nodeCrypto.webcrypto.CryptoKey);
|
|
25
|
+
}
|
|
24
26
|
class MockCache {
|
|
25
27
|
name;
|
|
26
28
|
store;
|
|
@@ -22,7 +22,7 @@ __export(jws_exports, {
|
|
|
22
22
|
verifying: () => verifying
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(jws_exports);
|
|
25
|
-
var
|
|
25
|
+
var import_adapter = require("../../helper/adapter");
|
|
26
26
|
var import_encode = require("../encode");
|
|
27
27
|
var import_types = require("./types");
|
|
28
28
|
var import_types2 = require("./types");
|
|
@@ -199,7 +199,7 @@ function getKeyAlgorithm(name) {
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
function isCryptoKey(key) {
|
|
202
|
-
const runtime = (0,
|
|
202
|
+
const runtime = (0, import_adapter.getRuntimeKey)();
|
|
203
203
|
if (runtime === "node" && !!crypto.webcrypto) {
|
|
204
204
|
return key instanceof crypto.webcrypto.CryptoKey;
|
|
205
205
|
}
|
|
@@ -21,25 +21,38 @@ var auth = (req) => {
|
|
|
21
21
|
return { username: userPass[1], password: userPass[2] };
|
|
22
22
|
};
|
|
23
23
|
var basicAuth = (options, ...users) => {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const usernamePasswordInOptions = "username" in options && "password" in options;
|
|
25
|
+
const verifyUserInOptions = "verifyUser" in options;
|
|
26
|
+
if (!(usernamePasswordInOptions || verifyUserInOptions)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'basic auth middleware requires options for "username and password" or "verifyUser"'
|
|
29
|
+
);
|
|
26
30
|
}
|
|
27
31
|
if (!options.realm) {
|
|
28
32
|
options.realm = "Secure Area";
|
|
29
33
|
}
|
|
30
|
-
|
|
34
|
+
if (usernamePasswordInOptions) {
|
|
35
|
+
users.unshift({ username: options.username, password: options.password });
|
|
36
|
+
}
|
|
31
37
|
return async function basicAuth2(ctx, next) {
|
|
32
38
|
const requestUser = auth(ctx.req);
|
|
33
39
|
if (requestUser) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
timingSafeEqual(user.username, requestUser.username, options.hashFunction),
|
|
37
|
-
timingSafeEqual(user.password, requestUser.password, options.hashFunction)
|
|
38
|
-
]);
|
|
39
|
-
if (usernameEqual && passwordEqual) {
|
|
40
|
+
if (verifyUserInOptions) {
|
|
41
|
+
if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
|
|
40
42
|
await next();
|
|
41
43
|
return;
|
|
42
44
|
}
|
|
45
|
+
} else {
|
|
46
|
+
for (const user of users) {
|
|
47
|
+
const [usernameEqual, passwordEqual] = await Promise.all([
|
|
48
|
+
timingSafeEqual(user.username, requestUser.username, options.hashFunction),
|
|
49
|
+
timingSafeEqual(user.password, requestUser.password, options.hashFunction)
|
|
50
|
+
]);
|
|
51
|
+
if (usernameEqual && passwordEqual) {
|
|
52
|
+
await next();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
43
56
|
}
|
|
44
57
|
}
|
|
45
58
|
const res = new Response("Unauthorized", {
|
|
@@ -4,7 +4,7 @@ import { timingSafeEqual } from "../../utils/buffer.js";
|
|
|
4
4
|
var TOKEN_STRINGS = "[A-Za-z0-9._~+/-]+=*";
|
|
5
5
|
var PREFIX = "Bearer";
|
|
6
6
|
var bearerAuth = (options) => {
|
|
7
|
-
if (!options
|
|
7
|
+
if (!("token" in options || "verifyToken" in options)) {
|
|
8
8
|
throw new Error('bearer auth middleware requires options for "token"');
|
|
9
9
|
}
|
|
10
10
|
if (!options.realm) {
|
|
@@ -37,7 +37,9 @@ var bearerAuth = (options) => {
|
|
|
37
37
|
throw new HTTPException(400, { res });
|
|
38
38
|
} else {
|
|
39
39
|
let equal = false;
|
|
40
|
-
if (
|
|
40
|
+
if ("verifyToken" in options) {
|
|
41
|
+
equal = await options.verifyToken(match[1], c);
|
|
42
|
+
} else if (typeof options.token === "string") {
|
|
41
43
|
equal = await timingSafeEqual(options.token, match[1], options.hashFunction);
|
|
42
44
|
} else if (Array.isArray(options.token) && options.token.length > 0) {
|
|
43
45
|
for (const token of options.token) {
|
|
@@ -43,21 +43,22 @@ var jwt = (options) => {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
let payload;
|
|
46
|
-
let
|
|
46
|
+
let cause;
|
|
47
47
|
try {
|
|
48
48
|
payload = await Jwt.verify(token, options.secret, options.alg);
|
|
49
49
|
} catch (e) {
|
|
50
|
-
|
|
50
|
+
cause = e;
|
|
51
51
|
}
|
|
52
52
|
if (!payload) {
|
|
53
53
|
throw new HTTPException(401, {
|
|
54
|
-
message:
|
|
54
|
+
message: "Unauthorized",
|
|
55
55
|
res: unauthorizedResponse({
|
|
56
56
|
ctx,
|
|
57
57
|
error: "invalid_token",
|
|
58
|
-
statusText:
|
|
58
|
+
statusText: "Unauthorized",
|
|
59
59
|
errDescription: "token verification failure"
|
|
60
|
-
})
|
|
60
|
+
}),
|
|
61
|
+
cause
|
|
61
62
|
});
|
|
62
63
|
}
|
|
63
64
|
ctx.set("jwtPayload", payload);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// src/test-utils/setup-vitest.ts
|
|
2
|
-
import
|
|
2
|
+
import * as nodeCrypto from "node:crypto";
|
|
3
3
|
import { vi } from "vitest";
|
|
4
|
-
|
|
5
|
-
vi.stubGlobal("
|
|
4
|
+
if (!globalThis.crypto) {
|
|
5
|
+
vi.stubGlobal("crypto", nodeCrypto);
|
|
6
|
+
vi.stubGlobal("CryptoKey", nodeCrypto.webcrypto.CryptoKey);
|
|
7
|
+
}
|
|
6
8
|
var MockCache = class {
|
|
7
9
|
name;
|
|
8
10
|
store;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
import type { Context } from '../../context';
|
|
1
2
|
import type { MiddlewareHandler } from '../../types';
|
|
2
|
-
|
|
3
|
+
type BasicAuthOptions = {
|
|
3
4
|
username: string;
|
|
4
5
|
password: string;
|
|
5
6
|
realm?: string;
|
|
6
7
|
hashFunction?: Function;
|
|
7
|
-
}
|
|
8
|
+
} | {
|
|
9
|
+
verifyUser: (username: string, password: string, c: Context) => boolean | Promise<boolean>;
|
|
10
|
+
realm?: string;
|
|
11
|
+
hashFunction?: Function;
|
|
12
|
+
};
|
|
13
|
+
export declare const basicAuth: (options: BasicAuthOptions, ...users: {
|
|
8
14
|
username: string;
|
|
9
15
|
password: string;
|
|
10
16
|
}[]) => MiddlewareHandler;
|
|
17
|
+
export {};
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
import type { Context } from '../../context';
|
|
1
2
|
import type { MiddlewareHandler } from '../../types';
|
|
2
|
-
|
|
3
|
+
type BearerAuthOptions = {
|
|
3
4
|
token: string | string[];
|
|
4
5
|
realm?: string;
|
|
5
6
|
prefix?: string;
|
|
6
7
|
hashFunction?: Function;
|
|
7
|
-
}
|
|
8
|
+
} | {
|
|
9
|
+
realm?: string;
|
|
10
|
+
prefix?: string;
|
|
11
|
+
verifyToken: (token: string, c: Context) => boolean | Promise<boolean>;
|
|
12
|
+
hashFunction?: Function;
|
|
13
|
+
};
|
|
14
|
+
export declare const bearerAuth: (options: BearerAuthOptions) => MiddlewareHandler;
|
|
15
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MiddlewareHandler } from '../../types';
|
|
2
2
|
import '../../context';
|
|
3
|
+
import type { SignatureAlgorithm } from '../../utils/jwt/jwa';
|
|
3
4
|
declare module '../../context' {
|
|
4
5
|
interface ContextVariableMap {
|
|
5
6
|
jwtPayload: any;
|
|
@@ -8,7 +9,7 @@ declare module '../../context' {
|
|
|
8
9
|
export declare const jwt: (options: {
|
|
9
10
|
secret: string;
|
|
10
11
|
cookie?: string;
|
|
11
|
-
alg?:
|
|
12
|
+
alg?: SignatureAlgorithm;
|
|
12
13
|
}) => MiddlewareHandler;
|
|
13
14
|
export declare const verify: (token: string, publicKey: import("../../utils/jwt/jws").SignatureKey, alg?: "HS256" | "HS384" | "HS512" | "RS256" | "RS384" | "RS512" | "PS256" | "PS384" | "PS512" | "ES256" | "ES384" | "ES512" | "EdDSA") => Promise<any>;
|
|
14
15
|
export declare const decode: (token: string) => {
|
package/dist/utils/jwt/jws.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/utils/jwt/jws.ts
|
|
2
|
-
import { getRuntimeKey } from "../../helper.js";
|
|
2
|
+
import { getRuntimeKey } from "../../helper/adapter/index.js";
|
|
3
3
|
import { decodeBase64 } from "../encode.js";
|
|
4
4
|
import { JwtAlgorithmNotImplemented } from "./types.js";
|
|
5
5
|
import { CryptoKeyUsage } from "./types.js";
|
package/package.json
CHANGED
package/dist/types/helper.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export * from './helper/accepts';
|
|
2
|
-
export * from './helper/adapter';
|
|
3
|
-
export * from './helper/cookie';
|
|
4
|
-
export * from './helper/css';
|
|
5
|
-
export * from './helper/factory';
|
|
6
|
-
export * from './helper/html';
|
|
7
|
-
export * from './helper/streaming';
|
|
8
|
-
export * from './helper/testing';
|
|
9
|
-
export * from './helper/dev';
|
|
10
|
-
export * from './adapter/deno/ssg';
|
|
11
|
-
export * from './adapter/deno/websocket';
|
|
12
|
-
export { decode as jwtDecode, sign as jwtSign, verify as jwtVerify } from './middleware/jwt';
|