altcha-lib 1.4.1 → 2.0.0-beta.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.
Files changed (133) hide show
  1. package/LICENSE.txt +1 -1
  2. package/README.md +44 -149
  3. package/bin/cli.mjs +35 -0
  4. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  5. package/dist/cjs/v2/algorithms/argon2id.d.ts +2 -0
  6. package/dist/cjs/v2/algorithms/argon2id.js +26 -0
  7. package/dist/cjs/v2/algorithms/pbkdf2.d.ts +2 -0
  8. package/dist/cjs/v2/algorithms/pbkdf2.js +23 -0
  9. package/dist/cjs/v2/algorithms/scrypt.d.ts +2 -0
  10. package/dist/cjs/v2/algorithms/scrypt.js +17 -0
  11. package/dist/cjs/v2/algorithms/sha.d.ts +2 -0
  12. package/dist/cjs/v2/algorithms/sha.js +35 -0
  13. package/dist/cjs/v2/algorithms/web/pbkdf2.d.ts +2 -0
  14. package/dist/cjs/v2/algorithms/web/pbkdf2.js +19 -0
  15. package/dist/cjs/v2/algorithms/web/sha.d.ts +2 -0
  16. package/dist/cjs/v2/algorithms/web/sha.js +23 -0
  17. package/dist/cjs/v2/capped-map.d.ts +7 -0
  18. package/dist/cjs/v2/capped-map.js +18 -0
  19. package/dist/cjs/v2/frameworks/express.d.ts +21 -0
  20. package/dist/cjs/v2/frameworks/express.js +77 -0
  21. package/dist/cjs/v2/frameworks/fastify.d.ts +26 -0
  22. package/dist/cjs/v2/frameworks/fastify.js +88 -0
  23. package/dist/cjs/v2/frameworks/h3.d.ts +37 -0
  24. package/dist/cjs/v2/frameworks/h3.js +89 -0
  25. package/dist/cjs/v2/frameworks/hono.d.ts +99 -0
  26. package/dist/cjs/v2/frameworks/hono.js +86 -0
  27. package/dist/cjs/v2/frameworks/nestjs.d.ts +79 -0
  28. package/dist/cjs/v2/frameworks/nestjs.js +198 -0
  29. package/dist/cjs/v2/frameworks/nextjs.d.ts +21 -0
  30. package/dist/cjs/v2/frameworks/nextjs.js +112 -0
  31. package/dist/cjs/v2/frameworks/shared.d.ts +8 -0
  32. package/dist/cjs/v2/frameworks/shared.js +121 -0
  33. package/dist/cjs/v2/frameworks/sveltekit.d.ts +29 -0
  34. package/dist/cjs/v2/frameworks/sveltekit.js +101 -0
  35. package/dist/cjs/v2/frameworks/types.d.ts +47 -0
  36. package/dist/cjs/v2/frameworks/types.js +2 -0
  37. package/dist/cjs/v2/helpers.d.ts +27 -0
  38. package/dist/cjs/v2/helpers.js +127 -0
  39. package/dist/cjs/v2/index.d.ts +19 -0
  40. package/dist/cjs/v2/index.js +28 -0
  41. package/dist/cjs/v2/obfuscation.d.ts +11 -0
  42. package/dist/cjs/v2/obfuscation.js +74 -0
  43. package/dist/cjs/v2/pow.d.ts +60 -0
  44. package/dist/cjs/v2/pow.js +286 -0
  45. package/dist/cjs/v2/server-signature.d.ts +12 -0
  46. package/dist/cjs/v2/server-signature.js +68 -0
  47. package/dist/cjs/v2/types.d.ts +277 -0
  48. package/dist/cjs/v2/types.js +18 -0
  49. package/dist/cjs/v2/workers/argon2id.js +7 -0
  50. package/dist/cjs/v2/workers/pbkdf2.js +7 -0
  51. package/dist/cjs/v2/workers/scrypt.d.ts +1 -0
  52. package/dist/cjs/v2/workers/scrypt.js +7 -0
  53. package/dist/cjs/v2/workers/sha.d.ts +1 -0
  54. package/dist/cjs/v2/workers/sha.js +7 -0
  55. package/dist/cjs/v2/workers/shared.d.ts +4 -0
  56. package/dist/cjs/v2/workers/shared.js +32 -0
  57. package/dist/esm/tsconfig.build.tsbuildinfo +1 -0
  58. package/dist/esm/v1/types.js +1 -0
  59. package/dist/esm/v1/worker.d.ts +1 -0
  60. package/dist/esm/v2/algorithms/argon2id.d.ts +2 -0
  61. package/dist/esm/v2/algorithms/argon2id.js +20 -0
  62. package/dist/esm/v2/algorithms/pbkdf2.d.ts +2 -0
  63. package/dist/esm/v2/algorithms/pbkdf2.js +20 -0
  64. package/dist/esm/v2/algorithms/scrypt.d.ts +2 -0
  65. package/dist/esm/v2/algorithms/scrypt.js +14 -0
  66. package/dist/esm/v2/algorithms/sha.d.ts +2 -0
  67. package/dist/esm/v2/algorithms/sha.js +32 -0
  68. package/dist/esm/v2/algorithms/web/pbkdf2.d.ts +2 -0
  69. package/dist/esm/v2/algorithms/web/pbkdf2.js +16 -0
  70. package/dist/esm/v2/algorithms/web/sha.d.ts +2 -0
  71. package/dist/esm/v2/algorithms/web/sha.js +20 -0
  72. package/dist/esm/v2/capped-map.d.ts +7 -0
  73. package/dist/esm/v2/capped-map.js +15 -0
  74. package/dist/esm/v2/frameworks/express.d.ts +21 -0
  75. package/dist/esm/v2/frameworks/express.js +71 -0
  76. package/dist/esm/v2/frameworks/fastify.d.ts +26 -0
  77. package/dist/esm/v2/frameworks/fastify.js +82 -0
  78. package/dist/esm/v2/frameworks/h3.d.ts +37 -0
  79. package/dist/esm/v2/frameworks/h3.js +83 -0
  80. package/dist/esm/v2/frameworks/hono.d.ts +99 -0
  81. package/dist/esm/v2/frameworks/hono.js +80 -0
  82. package/dist/esm/v2/frameworks/nestjs.d.ts +79 -0
  83. package/dist/esm/v2/frameworks/nestjs.js +202 -0
  84. package/dist/esm/v2/frameworks/nextjs.d.ts +21 -0
  85. package/dist/esm/v2/frameworks/nextjs.js +106 -0
  86. package/dist/esm/v2/frameworks/shared.d.ts +8 -0
  87. package/dist/esm/v2/frameworks/shared.js +117 -0
  88. package/dist/esm/v2/frameworks/sveltekit.d.ts +29 -0
  89. package/dist/esm/v2/frameworks/sveltekit.js +95 -0
  90. package/dist/esm/v2/frameworks/types.d.ts +47 -0
  91. package/dist/esm/v2/frameworks/types.js +1 -0
  92. package/dist/esm/v2/helpers.d.ts +27 -0
  93. package/dist/esm/v2/helpers.js +112 -0
  94. package/dist/esm/v2/index.d.ts +19 -0
  95. package/dist/esm/v2/index.js +17 -0
  96. package/dist/esm/v2/obfuscation.d.ts +11 -0
  97. package/dist/esm/v2/obfuscation.js +70 -0
  98. package/dist/esm/v2/pow.d.ts +60 -0
  99. package/dist/esm/v2/pow.js +281 -0
  100. package/dist/esm/v2/server-signature.d.ts +12 -0
  101. package/dist/esm/v2/server-signature.js +63 -0
  102. package/dist/esm/v2/types.d.ts +277 -0
  103. package/dist/esm/v2/types.js +15 -0
  104. package/dist/esm/v2/workers/argon2id.d.ts +1 -0
  105. package/dist/esm/v2/workers/argon2id.js +5 -0
  106. package/dist/esm/v2/workers/pbkdf2.d.ts +1 -0
  107. package/dist/esm/v2/workers/pbkdf2.js +5 -0
  108. package/dist/esm/v2/workers/scrypt.d.ts +1 -0
  109. package/dist/esm/v2/workers/scrypt.js +5 -0
  110. package/dist/esm/v2/workers/sha.d.ts +1 -0
  111. package/dist/esm/v2/workers/sha.js +5 -0
  112. package/dist/esm/v2/workers/shared.d.ts +4 -0
  113. package/dist/esm/v2/workers/shared.js +29 -0
  114. package/package.json +138 -27
  115. package/cjs/dist/tsconfig.cjs.tsbuildinfo +0 -1
  116. package/cjs/package.json +0 -3
  117. package/dist/tsconfig.build.tsbuildinfo +0 -1
  118. /package/{cjs/dist → dist/cjs/v1}/helpers.d.ts +0 -0
  119. /package/{cjs/dist → dist/cjs/v1}/helpers.js +0 -0
  120. /package/{cjs/dist → dist/cjs/v1}/index.d.ts +0 -0
  121. /package/{cjs/dist → dist/cjs/v1}/index.js +0 -0
  122. /package/{cjs/dist → dist/cjs/v1}/types.d.ts +0 -0
  123. /package/{cjs/dist → dist/cjs/v1}/types.js +0 -0
  124. /package/{cjs/dist → dist/cjs/v1}/worker.d.ts +0 -0
  125. /package/{cjs/dist → dist/cjs/v1}/worker.js +0 -0
  126. /package/dist/{types.js → cjs/v2/workers/argon2id.d.ts} +0 -0
  127. /package/dist/{worker.d.ts → cjs/v2/workers/pbkdf2.d.ts} +0 -0
  128. /package/dist/{helpers.d.ts → esm/v1/helpers.d.ts} +0 -0
  129. /package/dist/{helpers.js → esm/v1/helpers.js} +0 -0
  130. /package/dist/{index.d.ts → esm/v1/index.d.ts} +0 -0
  131. /package/dist/{index.js → esm/v1/index.js} +0 -0
  132. /package/dist/{types.d.ts → esm/v1/types.d.ts} +0 -0
  133. /package/dist/{worker.js → esm/v1/worker.js} +0 -0
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.randomInt = exports.deriveHmacKeySecret = exports.CappedMap = void 0;
4
+ exports.create = create;
5
+ const pow_js_1 = require("../pow.js");
6
+ const helpers_js_1 = require("../helpers.js");
7
+ Object.defineProperty(exports, "randomInt", { enumerable: true, get: function () { return helpers_js_1.randomInt; } });
8
+ const shared_js_1 = require("./shared.js");
9
+ Object.defineProperty(exports, "deriveHmacKeySecret", { enumerable: true, get: function () { return shared_js_1.deriveHmacKeySecret; } });
10
+ const capped_map_js_1 = require("../capped-map.js");
11
+ Object.defineProperty(exports, "CappedMap", { enumerable: true, get: function () { return capped_map_js_1.CappedMap; } });
12
+ function create(options) {
13
+ const { createChallengeParameters, deriveKey, hmacSignatureSecret, hmacKeySignatureSecret, setCookie, store, } = options;
14
+ const deleteCookie = (reply, name, path = '/') => {
15
+ reply.header('Set-Cookie', `${name}=; Path=${path ?? '/'}; Max-Age=0`);
16
+ };
17
+ const parseCookies = (request) => {
18
+ if ('cookies' in request) {
19
+ return request.cookies;
20
+ }
21
+ const header = request.headers.cookie;
22
+ if (!header) {
23
+ return {};
24
+ }
25
+ return Object.fromEntries(header.split(';').map((pair) => {
26
+ const [key, ...rest] = pair.trim().split('=');
27
+ return [key, decodeURIComponent(rest.join('='))];
28
+ }));
29
+ };
30
+ const getPayloadFromRequest = async (request, cookieName) => {
31
+ if (cookieName) {
32
+ return parseCookies(request)[cookieName];
33
+ }
34
+ return request.body?.altcha;
35
+ };
36
+ const challengeHandler = async (request, reply) => {
37
+ const challenge = await (0, pow_js_1.createChallenge)({
38
+ deriveKey,
39
+ hmacSignatureSecret,
40
+ hmacKeySignatureSecret,
41
+ ...createChallengeParameters(),
42
+ });
43
+ return reply.send({
44
+ configuration: setCookie
45
+ ? {
46
+ setCookie,
47
+ }
48
+ : undefined,
49
+ ...challenge,
50
+ });
51
+ };
52
+ const verifyHandler = async (request, reply) => {
53
+ const payload = await getPayloadFromRequest(request);
54
+ const result = await (0, shared_js_1.verify)(payload, deriveKey, hmacSignatureSecret, hmacKeySignatureSecret, store);
55
+ return reply.send(result);
56
+ };
57
+ const middleware = (options = {}) => {
58
+ const { throwOnFailure = true } = options;
59
+ return async (request, reply) => {
60
+ const payload = await getPayloadFromRequest(request, setCookie?.name);
61
+ const { error, payload: resultPayload, verification, } = await (0, shared_js_1.verify)(payload, deriveKey, hmacSignatureSecret, hmacKeySignatureSecret, store);
62
+ request.altcha = {
63
+ error,
64
+ payload: resultPayload,
65
+ verification,
66
+ };
67
+ if (setCookie) {
68
+ deleteCookie(reply, setCookie.name, setCookie.path);
69
+ }
70
+ if (error && throwOnFailure) {
71
+ return reply.code(403).send({ error });
72
+ }
73
+ };
74
+ };
75
+ return {
76
+ challengeHandler,
77
+ verifyHandler,
78
+ getPayloadFromRequest,
79
+ middleware,
80
+ verify: shared_js_1.verify,
81
+ };
82
+ }
83
+ exports.default = {
84
+ CappedMap: capped_map_js_1.CappedMap,
85
+ create,
86
+ deriveHmacKeySecret: shared_js_1.deriveHmacKeySecret,
87
+ randomInt: helpers_js_1.randomInt,
88
+ };
@@ -0,0 +1,37 @@
1
+ import { randomInt } from '../helpers.js';
2
+ import { CappedMap } from '../capped-map.js';
3
+ import { deriveHmacKeySecret, verify } from './shared.js';
4
+ import type { AltchaMiddlewareOptions, AltchaOptions, AltchaResult } from './types.js';
5
+ import type { H3Event } from 'h3';
6
+ export { CappedMap, deriveHmacKeySecret, randomInt };
7
+ export type { AltchaOptions, AltchaResult };
8
+ declare module 'h3' {
9
+ interface H3EventContext {
10
+ altcha?: AltchaResult;
11
+ }
12
+ }
13
+ export declare function create(options: AltchaOptions): {
14
+ challengeHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
15
+ codeChallenge?: import("../types.js").CodeChallenge;
16
+ parameters: import("../types.js").ChallengeParameters;
17
+ signature?: string;
18
+ configuration: {
19
+ setCookie: import("./types.js").RequireField<import("../types.js").SetCookieOptions, "name">;
20
+ } | undefined;
21
+ }>>;
22
+ verifyHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
23
+ error: string | null;
24
+ payload: import("../types.js").Payload | import("../types.js").ServerSignaturePayload | null;
25
+ verification: import("../types.js").VerifySolutionResult | null;
26
+ }>>;
27
+ getPayloadFromEvent: (event: H3Event, cookieName?: string) => Promise<string | undefined>;
28
+ middleware: (options?: AltchaMiddlewareOptions) => import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<void>>;
29
+ verify: typeof verify;
30
+ };
31
+ declare const _default: {
32
+ CappedMap: typeof CappedMap;
33
+ create: typeof create;
34
+ deriveHmacKeySecret: typeof deriveHmacKeySecret;
35
+ randomInt: typeof randomInt;
36
+ };
37
+ export default _default;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.randomInt = exports.deriveHmacKeySecret = exports.CappedMap = void 0;
4
+ exports.create = create;
5
+ const h3_1 = require("h3");
6
+ const pow_js_1 = require("../pow.js");
7
+ const helpers_js_1 = require("../helpers.js");
8
+ Object.defineProperty(exports, "randomInt", { enumerable: true, get: function () { return helpers_js_1.randomInt; } });
9
+ const capped_map_js_1 = require("../capped-map.js");
10
+ Object.defineProperty(exports, "CappedMap", { enumerable: true, get: function () { return capped_map_js_1.CappedMap; } });
11
+ const shared_js_1 = require("./shared.js");
12
+ Object.defineProperty(exports, "deriveHmacKeySecret", { enumerable: true, get: function () { return shared_js_1.deriveHmacKeySecret; } });
13
+ function create(options) {
14
+ const { createChallengeParameters, deriveKey, fieldName = 'altcha', hmacSignatureSecret, hmacKeySignatureSecret, setCookie, store, } = options;
15
+ const challengeHandler = (0, h3_1.defineEventHandler)(async () => {
16
+ return {
17
+ configuration: setCookie
18
+ ? {
19
+ setCookie,
20
+ }
21
+ : undefined,
22
+ ...(await (0, pow_js_1.createChallenge)({
23
+ deriveKey,
24
+ hmacSignatureSecret,
25
+ hmacKeySignatureSecret,
26
+ ...createChallengeParameters(),
27
+ })),
28
+ };
29
+ });
30
+ const verifyHandler = (0, h3_1.defineEventHandler)(async (event) => {
31
+ return await (0, shared_js_1.verify)(await getPayloadFromEvent(event), deriveKey, hmacSignatureSecret, hmacKeySignatureSecret, store);
32
+ });
33
+ const getPayloadFromEvent = async (event, cookieName) => {
34
+ let payload = undefined;
35
+ if (cookieName) {
36
+ payload = (0, h3_1.getCookie)(event, cookieName);
37
+ }
38
+ else {
39
+ const contentType = event.req.headers.get('content-type') ?? '';
40
+ let body = null;
41
+ if (contentType.includes('application/json')) {
42
+ body = await (0, h3_1.readBody)(event);
43
+ }
44
+ else if (contentType.includes('multipart/form-data')) {
45
+ const formData = await event.req.formData();
46
+ const value = formData.get(fieldName);
47
+ if (typeof value === 'string') {
48
+ payload = value;
49
+ }
50
+ return payload;
51
+ }
52
+ else if (contentType.includes('application/x-www-form-urlencoded')) {
53
+ body = await (0, h3_1.readBody)(event);
54
+ }
55
+ payload = body?.[fieldName];
56
+ }
57
+ return payload;
58
+ };
59
+ const middleware = (options = {}) => {
60
+ const { throwOnFailure = true } = options;
61
+ return (0, h3_1.defineEventHandler)(async (event) => {
62
+ const { error, payload, verification } = await (0, shared_js_1.verify)(await getPayloadFromEvent(event, setCookie?.name), deriveKey, hmacSignatureSecret, hmacKeySignatureSecret, store);
63
+ event.context.altcha = {
64
+ error,
65
+ payload,
66
+ verification,
67
+ };
68
+ if (setCookie) {
69
+ (0, h3_1.deleteCookie)(event, setCookie.name);
70
+ }
71
+ if (error && throwOnFailure) {
72
+ throw new h3_1.HTTPError({ message: error, status: 403 });
73
+ }
74
+ });
75
+ };
76
+ return {
77
+ challengeHandler,
78
+ verifyHandler,
79
+ getPayloadFromEvent,
80
+ middleware,
81
+ verify: shared_js_1.verify,
82
+ };
83
+ }
84
+ exports.default = {
85
+ CappedMap: capped_map_js_1.CappedMap,
86
+ create,
87
+ deriveHmacKeySecret: shared_js_1.deriveHmacKeySecret,
88
+ randomInt: helpers_js_1.randomInt,
89
+ };
@@ -0,0 +1,99 @@
1
+ import { randomInt } from '../helpers.js';
2
+ import { CappedMap } from '../capped-map.js';
3
+ import { deriveHmacKeySecret, verify } from './shared.js';
4
+ import type { AltchaMiddlewareOptions, AltchaOptions, AltchaResult } from './types.js';
5
+ import type { Context, Env, MiddlewareHandler } from 'hono';
6
+ export { CappedMap, deriveHmacKeySecret, randomInt };
7
+ export type { AltchaOptions, AltchaResult };
8
+ declare module 'hono' {
9
+ interface ContextVariableMap {
10
+ altcha?: AltchaResult;
11
+ }
12
+ }
13
+ export declare function create(options: AltchaOptions): {
14
+ challengeHandler: <E extends Env, P extends string>(c: Context<E, P>) => Promise<Response & import("hono").TypedResponse<{
15
+ codeChallenge?: {
16
+ image: string;
17
+ audio?: string | undefined;
18
+ length?: number | undefined;
19
+ } | undefined;
20
+ parameters: {
21
+ algorithm: string;
22
+ nonce: string;
23
+ salt: string;
24
+ cost: number;
25
+ keyLength: number;
26
+ keyPrefix: string;
27
+ keySignature?: string | undefined;
28
+ memoryCost?: number | undefined;
29
+ parallelism?: number | undefined;
30
+ expiresAt?: number | undefined;
31
+ data?: {
32
+ [x: string]: string | number | boolean | null;
33
+ } | undefined;
34
+ };
35
+ signature?: string | undefined;
36
+ configuration: {
37
+ setCookie: {
38
+ domain?: string | undefined;
39
+ maxAge?: number | undefined;
40
+ path?: string | undefined;
41
+ sameSite?: string | undefined;
42
+ secure?: boolean | undefined;
43
+ name: string;
44
+ };
45
+ } | undefined;
46
+ }, import("hono/utils/http-status.js").ContentfulStatusCode, "json">>;
47
+ verifyHandler: <E extends Env, P extends string>(c: Context<E, P>) => Promise<Response & import("hono").TypedResponse<{
48
+ error: string | null;
49
+ payload: {
50
+ challenge: {
51
+ signature?: string | undefined;
52
+ parameters: {
53
+ algorithm: string;
54
+ nonce: string;
55
+ salt: string;
56
+ cost: number;
57
+ keyLength: number;
58
+ keyPrefix: string;
59
+ keySignature?: string | undefined;
60
+ memoryCost?: number | undefined;
61
+ parallelism?: number | undefined;
62
+ expiresAt?: number | undefined;
63
+ data?: {
64
+ [x: string]: string | number | boolean | null;
65
+ } | undefined;
66
+ };
67
+ };
68
+ solution: {
69
+ counter: number;
70
+ derivedKey: string;
71
+ time?: number | undefined;
72
+ };
73
+ } | {
74
+ algorithm: string;
75
+ apiKey?: string | undefined;
76
+ id?: string | undefined;
77
+ signature: string;
78
+ verificationData: string;
79
+ verified: boolean;
80
+ } | null;
81
+ verification: {
82
+ expired: boolean;
83
+ invalidSignature: boolean | null;
84
+ invalidSolution: boolean | null;
85
+ time: number;
86
+ verified: boolean;
87
+ } | null;
88
+ }, import("hono/utils/http-status.js").ContentfulStatusCode, "json">>;
89
+ getPayloadFromContext: (c: Context, cookieName?: string) => Promise<string | undefined>;
90
+ middleware: <E extends Env, P extends string>(options?: AltchaMiddlewareOptions) => MiddlewareHandler<E, P>;
91
+ verify: typeof verify;
92
+ };
93
+ declare const _default: {
94
+ CappedMap: typeof CappedMap;
95
+ create: typeof create;
96
+ deriveHmacKeySecret: typeof deriveHmacKeySecret;
97
+ randomInt: typeof randomInt;
98
+ };
99
+ export default _default;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.randomInt = exports.deriveHmacKeySecret = exports.CappedMap = void 0;
4
+ exports.create = create;
5
+ const cookie_1 = require("hono/cookie");
6
+ const http_exception_1 = require("hono/http-exception");
7
+ const pow_js_1 = require("../pow.js");
8
+ const helpers_js_1 = require("../helpers.js");
9
+ Object.defineProperty(exports, "randomInt", { enumerable: true, get: function () { return helpers_js_1.randomInt; } });
10
+ const capped_map_js_1 = require("../capped-map.js");
11
+ Object.defineProperty(exports, "CappedMap", { enumerable: true, get: function () { return capped_map_js_1.CappedMap; } });
12
+ const shared_js_1 = require("./shared.js");
13
+ Object.defineProperty(exports, "deriveHmacKeySecret", { enumerable: true, get: function () { return shared_js_1.deriveHmacKeySecret; } });
14
+ function create(options) {
15
+ const { createChallengeParameters, deriveKey, fieldName = 'altcha', hmacSignatureSecret, hmacKeySignatureSecret, setCookie, store, } = options;
16
+ const challengeHandler = async (c) => {
17
+ return c.json({
18
+ configuration: setCookie
19
+ ? {
20
+ setCookie,
21
+ }
22
+ : undefined,
23
+ ...(await (0, pow_js_1.createChallenge)({
24
+ deriveKey,
25
+ hmacSignatureSecret,
26
+ hmacKeySignatureSecret,
27
+ ...createChallengeParameters(),
28
+ })),
29
+ });
30
+ };
31
+ const verifyHandler = async (c) => {
32
+ return c.json(await (0, shared_js_1.verify)(await getPayloadFromContext(c), deriveKey, hmacSignatureSecret, hmacKeySignatureSecret, store));
33
+ };
34
+ const getPayloadFromContext = async (c, cookieName) => {
35
+ let payload = undefined;
36
+ if (cookieName) {
37
+ payload = (0, cookie_1.getCookie)(c, cookieName);
38
+ }
39
+ else {
40
+ const contentType = c.req.header('content-type') ?? '';
41
+ let body = null;
42
+ if (contentType.includes('application/json')) {
43
+ body = await c.req.json();
44
+ }
45
+ else if (contentType.includes('multipart/form-data') ||
46
+ contentType.includes('application/x-www-form-urlencoded')) {
47
+ body = await c.req.parseBody();
48
+ }
49
+ payload = body?.[fieldName];
50
+ }
51
+ return payload;
52
+ };
53
+ const middleware = (options = {}) => {
54
+ const { throwOnFailure = true } = options;
55
+ return async (c, next) => {
56
+ const { error, payload, verification } = await (0, shared_js_1.verify)(await getPayloadFromContext(c, setCookie?.name), deriveKey, hmacSignatureSecret, hmacKeySignatureSecret, store);
57
+ c.set('altcha', {
58
+ error,
59
+ payload,
60
+ verification,
61
+ });
62
+ if (setCookie) {
63
+ (0, cookie_1.deleteCookie)(c, setCookie.name);
64
+ }
65
+ if (error && throwOnFailure) {
66
+ throw new http_exception_1.HTTPException(403, {
67
+ message: error,
68
+ });
69
+ }
70
+ return next();
71
+ };
72
+ };
73
+ return {
74
+ challengeHandler,
75
+ verifyHandler,
76
+ getPayloadFromContext,
77
+ middleware,
78
+ verify: shared_js_1.verify,
79
+ };
80
+ }
81
+ exports.default = {
82
+ CappedMap: capped_map_js_1.CappedMap,
83
+ create,
84
+ deriveHmacKeySecret: shared_js_1.deriveHmacKeySecret,
85
+ randomInt: helpers_js_1.randomInt,
86
+ };
@@ -0,0 +1,79 @@
1
+ import { NestMiddleware, DynamicModule, InjectionToken, OptionalFactoryDependency, ForwardReference, Type } from '@nestjs/common';
2
+ import { randomInt } from '../helpers.js';
3
+ import { deriveHmacKeySecret } from './shared.js';
4
+ import { CappedMap } from '../capped-map.js';
5
+ import type { Request, Response, NextFunction } from 'express';
6
+ import type { SetCookieOptions } from '../types.js';
7
+ import type { AltchaMiddlewareOptions, AltchaOptions, AltchaResult, RequireField } from './types.js';
8
+ export { CappedMap, deriveHmacKeySecret, randomInt };
9
+ export type { AltchaOptions, AltchaResult };
10
+ declare global {
11
+ namespace Express {
12
+ interface Request {
13
+ altcha?: AltchaResult;
14
+ }
15
+ }
16
+ }
17
+ export declare const Altcha: (...dataOrPipes: unknown[]) => ParameterDecorator;
18
+ export declare function createAltchaMiddleware(options?: AltchaMiddlewareOptions): {
19
+ new (altchaService: AltchaService): {
20
+ readonly altchaService: AltchaService;
21
+ use(req: Request, res: Response, next: NextFunction): Promise<void>;
22
+ };
23
+ };
24
+ export declare class AltchaService {
25
+ private readonly hmacSignatureSecret;
26
+ private readonly hmacKeySignatureSecret?;
27
+ private readonly createChallengeParameters;
28
+ private readonly deriveKey;
29
+ private readonly fieldName;
30
+ private readonly setCookieOptions?;
31
+ private readonly store?;
32
+ constructor(options: AltchaOptions);
33
+ get setCookie(): RequireField<SetCookieOptions, 'name'> | undefined;
34
+ getChallenge(): Promise<{
35
+ codeChallenge?: import("../types.js").CodeChallenge;
36
+ parameters: import("../types.js").ChallengeParameters;
37
+ signature?: string;
38
+ configuration: {
39
+ setCookie: RequireField<SetCookieOptions, "name">;
40
+ } | undefined;
41
+ }>;
42
+ getPayloadFromRequest(req: Request, cookieName?: string): string | undefined;
43
+ verify(payload: string | undefined): Promise<{
44
+ error: string | null;
45
+ payload: import("../types.js").Payload | import("../types.js").ServerSignaturePayload | null;
46
+ verification: import("../types.js").VerifySolutionResult | null;
47
+ }>;
48
+ }
49
+ export declare class AltchaController {
50
+ private readonly altchaService;
51
+ constructor(altchaService: AltchaService);
52
+ getChallenge(): Promise<{
53
+ codeChallenge?: import("../types.js").CodeChallenge;
54
+ parameters: import("../types.js").ChallengeParameters;
55
+ signature?: string;
56
+ configuration: {
57
+ setCookie: RequireField<SetCookieOptions, "name">;
58
+ } | undefined;
59
+ }>;
60
+ verifySolution(req: Request): Promise<{
61
+ error: string | null;
62
+ payload: import("../types.js").Payload | import("../types.js").ServerSignaturePayload | null;
63
+ verification: import("../types.js").VerifySolutionResult | null;
64
+ }>;
65
+ }
66
+ export declare class AltchaMiddleware implements NestMiddleware {
67
+ private readonly altchaService;
68
+ constructor(altchaService: AltchaService);
69
+ use(req: Request, res: Response, next: NextFunction): Promise<void>;
70
+ }
71
+ export declare class AltchaModule {
72
+ static register(options: AltchaOptions): DynamicModule;
73
+ static registerAsync(asyncOptions: {
74
+ useFactory: (...args: unknown[]) => Promise<AltchaOptions> | AltchaOptions;
75
+ inject?: (InjectionToken | OptionalFactoryDependency)[];
76
+ imports?: (DynamicModule | Type<unknown> | ForwardReference<unknown> | Promise<DynamicModule>)[];
77
+ }): DynamicModule;
78
+ }
79
+ export default AltchaModule;
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var AltchaModule_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.AltchaModule = exports.AltchaMiddleware = exports.AltchaController = exports.AltchaService = exports.Altcha = exports.randomInt = exports.deriveHmacKeySecret = exports.CappedMap = void 0;
17
+ exports.createAltchaMiddleware = createAltchaMiddleware;
18
+ const common_1 = require("@nestjs/common");
19
+ const helpers_js_1 = require("../helpers.js");
20
+ Object.defineProperty(exports, "randomInt", { enumerable: true, get: function () { return helpers_js_1.randomInt; } });
21
+ const pow_js_1 = require("../pow.js");
22
+ const shared_js_1 = require("./shared.js");
23
+ Object.defineProperty(exports, "deriveHmacKeySecret", { enumerable: true, get: function () { return shared_js_1.deriveHmacKeySecret; } });
24
+ const capped_map_js_1 = require("../capped-map.js");
25
+ Object.defineProperty(exports, "CappedMap", { enumerable: true, get: function () { return capped_map_js_1.CappedMap; } });
26
+ const ALTCHA_OPTIONS = Symbol('ALTCHA_OPTIONS');
27
+ exports.Altcha = (0, common_1.createParamDecorator)((_data, ctx) => {
28
+ const request = ctx.switchToHttp().getRequest();
29
+ return request.altcha;
30
+ });
31
+ function createAltchaMiddleware(options = {}) {
32
+ const { throwOnFailure = true } = options;
33
+ let AltchaMiddleware = class AltchaMiddleware {
34
+ constructor(altchaService) {
35
+ this.altchaService = altchaService;
36
+ }
37
+ async use(req, res, next) {
38
+ const payload = this.altchaService.getPayloadFromRequest(req);
39
+ const { error, payload: resultPayload, verification, } = await this.altchaService.verify(payload);
40
+ req.altcha = {
41
+ error,
42
+ payload: resultPayload,
43
+ verification,
44
+ };
45
+ const setCookie = this.altchaService.setCookie;
46
+ if (setCookie) {
47
+ res.clearCookie(setCookie.name);
48
+ }
49
+ if (error && throwOnFailure) {
50
+ throw new common_1.HttpException(error, common_1.HttpStatus.BAD_REQUEST);
51
+ }
52
+ next();
53
+ }
54
+ };
55
+ AltchaMiddleware = __decorate([
56
+ (0, common_1.Injectable)(),
57
+ __metadata("design:paramtypes", [AltchaService])
58
+ ], AltchaMiddleware);
59
+ return AltchaMiddleware;
60
+ }
61
+ let AltchaService = class AltchaService {
62
+ constructor(options) {
63
+ this.hmacSignatureSecret = options.hmacSignatureSecret;
64
+ this.hmacKeySignatureSecret = options.hmacKeySignatureSecret;
65
+ this.createChallengeParameters = options.createChallengeParameters;
66
+ this.deriveKey = options.deriveKey;
67
+ this.fieldName = options.fieldName || 'altcha';
68
+ this.setCookieOptions = options.setCookie;
69
+ this.store = options.store;
70
+ }
71
+ get setCookie() {
72
+ return this.setCookieOptions;
73
+ }
74
+ async getChallenge() {
75
+ const challenge = await (0, pow_js_1.createChallenge)({
76
+ deriveKey: this.deriveKey,
77
+ hmacSignatureSecret: this.hmacSignatureSecret,
78
+ hmacKeySignatureSecret: this.hmacKeySignatureSecret,
79
+ ...this.createChallengeParameters(),
80
+ });
81
+ return {
82
+ configuration: this.setCookieOptions
83
+ ? { setCookie: this.setCookieOptions }
84
+ : undefined,
85
+ ...challenge,
86
+ };
87
+ }
88
+ getPayloadFromRequest(req, cookieName) {
89
+ if (cookieName) {
90
+ return req.cookies?.[cookieName];
91
+ }
92
+ return req.body?.[this.fieldName];
93
+ }
94
+ async verify(payload) {
95
+ return (0, shared_js_1.verify)(payload, this.deriveKey, this.hmacSignatureSecret, this.hmacKeySignatureSecret, this.store);
96
+ }
97
+ };
98
+ exports.AltchaService = AltchaService;
99
+ exports.AltchaService = AltchaService = __decorate([
100
+ (0, common_1.Injectable)(),
101
+ __param(0, (0, common_1.Inject)(ALTCHA_OPTIONS)),
102
+ __metadata("design:paramtypes", [Object])
103
+ ], AltchaService);
104
+ let AltchaController = class AltchaController {
105
+ constructor(altchaService) {
106
+ this.altchaService = altchaService;
107
+ }
108
+ async getChallenge() {
109
+ return this.altchaService.getChallenge();
110
+ }
111
+ async verifySolution(req) {
112
+ const payload = this.altchaService.getPayloadFromRequest(req);
113
+ return this.altchaService.verify(payload);
114
+ }
115
+ };
116
+ exports.AltchaController = AltchaController;
117
+ __decorate([
118
+ (0, common_1.Get)('challenge'),
119
+ __metadata("design:type", Function),
120
+ __metadata("design:paramtypes", []),
121
+ __metadata("design:returntype", Promise)
122
+ ], AltchaController.prototype, "getChallenge", null);
123
+ __decorate([
124
+ (0, common_1.Post)('verify'),
125
+ __param(0, (0, common_1.Req)()),
126
+ __metadata("design:type", Function),
127
+ __metadata("design:paramtypes", [Object]),
128
+ __metadata("design:returntype", Promise)
129
+ ], AltchaController.prototype, "verifySolution", null);
130
+ exports.AltchaController = AltchaController = __decorate([
131
+ (0, common_1.Controller)('altcha'),
132
+ __metadata("design:paramtypes", [AltchaService])
133
+ ], AltchaController);
134
+ let AltchaMiddleware = class AltchaMiddleware {
135
+ constructor(altchaService) {
136
+ this.altchaService = altchaService;
137
+ }
138
+ async use(req, res, next) {
139
+ const payload = this.altchaService.getPayloadFromRequest(req, this.altchaService.setCookie?.name);
140
+ const { error, payload: resultPayload, verification, } = await this.altchaService.verify(payload);
141
+ req.altcha = {
142
+ error,
143
+ payload: resultPayload,
144
+ verification,
145
+ };
146
+ const setCookie = this.altchaService.setCookie;
147
+ if (setCookie) {
148
+ res.clearCookie(setCookie.name);
149
+ }
150
+ if (error) {
151
+ throw new common_1.HttpException(error, common_1.HttpStatus.BAD_REQUEST);
152
+ }
153
+ next();
154
+ }
155
+ };
156
+ exports.AltchaMiddleware = AltchaMiddleware;
157
+ exports.AltchaMiddleware = AltchaMiddleware = __decorate([
158
+ (0, common_1.Injectable)(),
159
+ __metadata("design:paramtypes", [AltchaService])
160
+ ], AltchaMiddleware);
161
+ let AltchaModule = AltchaModule_1 = class AltchaModule {
162
+ static register(options) {
163
+ return {
164
+ module: AltchaModule_1,
165
+ controllers: [AltchaController],
166
+ providers: [
167
+ {
168
+ provide: ALTCHA_OPTIONS,
169
+ useValue: options,
170
+ },
171
+ AltchaService,
172
+ ],
173
+ exports: [AltchaService, AltchaMiddleware],
174
+ };
175
+ }
176
+ static registerAsync(asyncOptions) {
177
+ return {
178
+ module: AltchaModule_1,
179
+ imports: asyncOptions.imports ?? [],
180
+ controllers: [AltchaController],
181
+ providers: [
182
+ {
183
+ provide: ALTCHA_OPTIONS,
184
+ useFactory: asyncOptions.useFactory,
185
+ inject: asyncOptions.inject ?? [],
186
+ },
187
+ AltchaService,
188
+ AltchaMiddleware,
189
+ ],
190
+ exports: [AltchaService, AltchaMiddleware],
191
+ };
192
+ }
193
+ };
194
+ exports.AltchaModule = AltchaModule;
195
+ exports.AltchaModule = AltchaModule = AltchaModule_1 = __decorate([
196
+ (0, common_1.Module)({})
197
+ ], AltchaModule);
198
+ exports.default = AltchaModule;