@prosopo/better-auth-procaptcha-plugin 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +32 -0
  2. package/.turbo/turbo-build$colon$esm.log +33 -0
  3. package/.turbo/turbo-build$colon$tsc.log +23 -0
  4. package/.turbo/turbo-build$colon$types.log +1 -54
  5. package/CHANGELOG.md +12 -0
  6. package/dist/esm/_virtual/_rolldown/runtime.js +0 -1
  7. package/dist/tsc/client.d.ts +19 -0
  8. package/dist/tsc/client.d.ts.map +1 -0
  9. package/dist/tsc/client.js +39 -0
  10. package/dist/tsc/client.js.map +1 -0
  11. package/dist/tsc/constants.d.ts +12 -0
  12. package/dist/tsc/constants.d.ts.map +1 -0
  13. package/dist/tsc/constants.js +16 -0
  14. package/dist/tsc/constants.js.map +1 -0
  15. package/dist/tsc/index.d.ts +28 -0
  16. package/dist/tsc/index.d.ts.map +1 -0
  17. package/dist/tsc/index.js +94 -0
  18. package/dist/tsc/index.js.map +1 -0
  19. package/dist/tsc/path.d.ts +4 -0
  20. package/dist/tsc/path.d.ts.map +1 -0
  21. package/dist/tsc/path.js +59 -0
  22. package/dist/tsc/path.js.map +1 -0
  23. package/dist/tsc/siteverify.d.ts +40 -0
  24. package/dist/tsc/siteverify.d.ts.map +1 -0
  25. package/dist/tsc/siteverify.js +80 -0
  26. package/dist/tsc/siteverify.js.map +1 -0
  27. package/dist/tsc/tests/client.unit.test.d.ts +2 -0
  28. package/dist/tsc/tests/client.unit.test.d.ts.map +1 -0
  29. package/dist/tsc/tests/client.unit.test.js +56 -0
  30. package/dist/tsc/tests/client.unit.test.js.map +1 -0
  31. package/dist/tsc/tests/path.unit.test.d.ts +2 -0
  32. package/dist/tsc/tests/path.unit.test.d.ts.map +1 -0
  33. package/dist/tsc/tests/path.unit.test.js +53 -0
  34. package/dist/tsc/tests/path.unit.test.js.map +1 -0
  35. package/dist/tsc/tests/procaptcha.unit.test.d.ts +2 -0
  36. package/dist/tsc/tests/procaptcha.unit.test.d.ts.map +1 -0
  37. package/dist/tsc/tests/procaptcha.unit.test.js +158 -0
  38. package/dist/tsc/tests/procaptcha.unit.test.js.map +1 -0
  39. package/dist/tsc/tests/siteVerifyMock.d.ts +17 -0
  40. package/dist/tsc/tests/siteVerifyMock.d.ts.map +1 -0
  41. package/dist/tsc/tests/siteVerifyMock.js +43 -0
  42. package/dist/tsc/tests/siteVerifyMock.js.map +1 -0
  43. package/dist/tsc/tests/siteverify.unit.test.d.ts +2 -0
  44. package/dist/tsc/tests/siteverify.unit.test.d.ts.map +1 -0
  45. package/dist/tsc/tests/siteverify.unit.test.js +50 -0
  46. package/dist/tsc/tests/siteverify.unit.test.js.map +1 -0
  47. package/package.json +2 -2
  48. package/coverage/base.css +0 -362
  49. package/coverage/block-navigation.js +0 -82
  50. package/coverage/client.ts.html +0 -316
  51. package/coverage/clover.xml +0 -151
  52. package/coverage/constants.ts.html +0 -190
  53. package/coverage/coverage-final.json +0 -6
  54. package/coverage/favicon.png +0 -0
  55. package/coverage/index.html +0 -176
  56. package/coverage/index.ts.html +0 -706
  57. package/coverage/path.ts.html +0 -355
  58. package/coverage/prettify.css +0 -101
  59. package/coverage/prettify.js +0 -937
  60. package/coverage/siteverify.ts.html +0 -559
  61. package/coverage/sort-arrow-sprite.png +0 -0
  62. package/coverage/sorter.js +0 -205
@@ -0,0 +1,32 @@
1
+ $ NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
2
+ ViteCommonJSConfig: .
3
+ {
4
+ tsConfigPaths: [
5
+ '/home/runner/work/captcha/captcha/packages/types/tsconfig.json',
6
+ '/home/runner/work/captcha/captcha/packages/locale/tsconfig.json',
7
+ '/home/runner/work/captcha/captcha/packages/util/tsconfig.json',
8
+ '/home/runner/work/captcha/captcha/packages/util-crypto/tsconfig.json'
9
+ ]
10
+ }
11
+ {
12
+ externals: [
13
+ '@prosopo/types',
14
+ '@prosopo/locale',
15
+ '@prosopo/util',
16
+ '@prosopo/util-crypto'
17
+ ]
18
+ }
19
+ The plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the resolve.tsconfigPaths option. You can remove the plugin and set resolve.tsconfigPaths: true in your Vite config instead.
20
+ vite v8.1.6 building ssr environment for production...
21
+ Bundle build started
22
+ 
23
+ ✓ 6 modules transformed.
24
+ rendering chunks...
25
+ computing gzip size...
26
+ dist/cjs/constants.cjs 0.89 kB │ gzip: 0.44 kB
27
+ dist/cjs/client.cjs 1.34 kB │ gzip: 0.63 kB
28
+ dist/cjs/path.cjs 1.80 kB │ gzip: 0.67 kB
29
+ dist/cjs/siteverify.cjs 2.37 kB │ gzip: 0.95 kB
30
+ dist/cjs/index.cjs 3.48 kB │ gzip: 1.36 kB
31
+
32
+ ✓ built in 52ms
@@ -0,0 +1,33 @@
1
+ $ vite build --config vite.esm.config.ts --mode ${NODE_ENV:-development}
2
+ ViteEsmConfig: .
3
+ {
4
+ tsConfigPaths: [
5
+ '/home/runner/work/captcha/captcha/packages/types/tsconfig.json',
6
+ '/home/runner/work/captcha/captcha/packages/locale/tsconfig.json',
7
+ '/home/runner/work/captcha/captcha/packages/util/tsconfig.json',
8
+ '/home/runner/work/captcha/captcha/packages/util-crypto/tsconfig.json'
9
+ ]
10
+ }
11
+ {
12
+ externals: [
13
+ '@prosopo/types',
14
+ '@prosopo/locale',
15
+ '@prosopo/util',
16
+ '@prosopo/util-crypto'
17
+ ]
18
+ }
19
+ The plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the resolve.tsconfigPaths option. You can remove the plugin and set resolve.tsconfigPaths: true in your Vite config instead.
20
+ vite v8.1.6 building ssr environment for production...
21
+ Bundle build started
22
+ 
23
+ ✓ 6 modules transformed.
24
+ rendering chunks...
25
+ computing gzip size...
26
+ dist/esm/_virtual/_rolldown/runtime.js 0.02 kB │ gzip: 0.04 kB
27
+ dist/esm/constants.js 0.74 kB │ gzip: 0.42 kB
28
+ dist/esm/client.js 1.25 kB │ gzip: 0.60 kB
29
+ dist/esm/path.js 1.75 kB │ gzip: 0.66 kB
30
+ dist/esm/siteverify.js 2.34 kB │ gzip: 0.94 kB
31
+ dist/esm/index.js 3.15 kB │ gzip: 1.29 kB
32
+
33
+ ✓ built in 56ms
@@ -0,0 +1,23 @@
1
+ $ tsc --build --verbose
2
+ 11:11:51 AM - Projects in this build:
3
+ * ../../../../dev/config/tsconfig.json
4
+ * ../../../../packages/util/tsconfig.json
5
+ * ../../../../packages/locale/tsconfig.json
6
+ * ../../../../packages/util-crypto/tsconfig.json
7
+ * ../../../../packages/types/tsconfig.json
8
+ * tsconfig.json
9
+
10
+ 11:11:51 AM - Project '../../../../dev/config/tsconfig.json' is up to date because newest input '../../../../dev/config/src/vite/vite-plugin-sourcemap-exclude.ts' is older than output '../../../../dev/config/dist/tsc/tsconfig.tsbuildinfo'
11
+
12
+ 11:11:51 AM - Project '../../../../packages/util/tsconfig.json' is up to date because newest input '../../../../packages/util/src/text.ts' is older than output '../../../../packages/util/dist/tsc/tsconfig.tsbuildinfo'
13
+
14
+ 11:11:51 AM - Project '../../../../packages/locale/tsconfig.json' is up to date because newest input '../../../../packages/locale/src/process.ts' is older than output '../../../../packages/locale/dist/tsc/tsconfig.tsbuildinfo'
15
+
16
+ 11:11:51 AM - Project '../../../../packages/util-crypto/tsconfig.json' is up to date because newest input '../../../../packages/util-crypto/src/types.ts' is older than output '../../../../packages/util-crypto/dist/tsc/tsconfig.tsbuildinfo'
17
+
18
+ 11:11:51 AM - Project '../../../../packages/types/tsconfig.json' is up to date because newest input '../../../../packages/types/src/types.test-d.ts' is older than output '../../../../packages/types/dist/tsc/tsconfig.tsbuildinfo'
19
+
20
+ 11:11:51 AM - Project 'tsconfig.json' is out of date because output file 'dist/tsc/tsconfig.tsbuildinfo' does not exist
21
+
22
+ 11:11:51 AM - Building project '/home/runner/work/captcha/captcha/integration/frameworks/better-auth/better-auth-procaptcha-plugin/tsconfig.json'...
23
+
@@ -1,54 +1 @@
1
- $ tsc --project tsconfig.types.json
2
- src/client.ts:14:45 - error TS2307: Cannot find module 'better-auth/client' or its corresponding type declarations.
3
-
4
- 14 import type { BetterAuthClientPlugin } from "better-auth/client";
5
-    ~~~~~~~~~~~~~~~~~~~~
6
-
7
- src/client.ts:59:26 - error TS7006: Parameter 'context' implicitly has an 'any' type.
8
-
9
- 59 onRequest: async (context) => {
10
-    ~~~~~~~
11
-
12
- src/constants.ts:14:34 - error TS2307: Cannot find module 'better-auth' or its corresponding type declarations.
13
-
14
- 14 import { defineErrorCodes } from "better-auth";
15
-    ~~~~~~~~~~~~~
16
-
17
- src/index.ts:18:8 - error TS2307: Cannot find module 'better-auth' or its corresponding type declarations.
18
-
19
- 18 } from "better-auth";
20
-    ~~~~~~~~~~~~~
21
-
22
- src/index.ts:19:23 - error TS2307: Cannot find module 'better-auth/api' or its corresponding type declarations.
23
-
24
- 19 import { getIP } from "better-auth/api";
25
-    ~~~~~~~~~~~~~~~~~
26
-
27
- src/siteverify.ts:14:43 - error TS2307: Cannot find module '@prosopo/types' or its corresponding type declarations.
28
-
29
- 14 import type { VerificationResponse } from "@prosopo/types";
30
-    ~~~~~~~~~~~~~~~~
31
-
32
- src/tests/client.unit.test.ts:14:33 - error TS2307: Cannot find module 'better-auth/test' or its corresponding type declarations.
33
-
34
- 14 import { getTestInstance } from "better-auth/test";
35
-    ~~~~~~~~~~~~~~~~~~
36
-
37
- src/tests/procaptcha.unit.test.ts:14:33 - error TS2307: Cannot find module 'better-auth/test' or its corresponding type declarations.
38
-
39
- 14 import { getTestInstance } from "better-auth/test";
40
-    ~~~~~~~~~~~~~~~~~~
41
-
42
-
43
- Found 8 errors in 6 files.
44
-
45
- Errors Files
46
- 2 src/client.ts:14
47
- 1 src/constants.ts:14
48
- 2 src/index.ts:18
49
- 1 src/siteverify.ts:14
50
- 1 src/tests/client.unit.test.ts:14
51
- 1 src/tests/procaptcha.unit.test.ts:14
52
-
53
- 
54
- 
1
+ $ tsc --project tsconfig.types.json
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @prosopo/better-auth-procaptcha-plugin
2
+
3
+ ## 0.1.0
4
+ ### Minor Changes
5
+
6
+ - 1bc57d2: Add a Better Auth plugin that verifies Procaptcha tokens on sign-up, sign-in and password reset.
7
+
8
+ ### Patch Changes
9
+
10
+ - Updated dependencies [1f29d99]
11
+ - Updated dependencies [adabe50]
12
+ - @prosopo/types@5.31.0
@@ -1,3 +1,2 @@
1
- import "node:module";
2
1
  //#endregion
3
2
  export {};
@@ -0,0 +1,19 @@
1
+ import type { procaptcha } from "./index.js";
2
+ export interface ProcaptchaClientOptions {
3
+ getToken?: () => string | undefined | Promise<string | undefined>;
4
+ endpoints?: readonly string[];
5
+ headerName?: string;
6
+ }
7
+ export declare const procaptchaHeaders: (token: string, headerName?: string) => Record<string, string>;
8
+ export declare const procaptchaClient: (options?: ProcaptchaClientOptions) => {
9
+ id: "procaptcha";
10
+ $InferServerPlugin: ReturnType<typeof procaptcha>;
11
+ fetchPlugins: {
12
+ id: string;
13
+ name: string;
14
+ hooks: {
15
+ onRequest: <T extends Record<string, any>>(context: import("better-auth/client").RequestContext<T>) => Promise<import("better-auth/client").RequestContext<T>>;
16
+ };
17
+ }[];
18
+ };
19
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,WAAW,uBAAuB;IAMvC,QAAQ,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAElE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,UACtB,MAAM,eACD,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,MAAM,CAA8B,CAAC;AAQvD,eAAO,MAAM,gBAAgB,aAAa,uBAAuB;;wBASrC,UAAU,CAAC,OAAO,UAAU,CAAC;;;;;;;;CAyBxD,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { DEFAULT_ENDPOINTS, PROCAPTCHA_HEADER } from "./constants.js";
2
+ import { createPathMatcher, normalizeAuthPath } from "./path.js";
3
+ export const procaptchaHeaders = (token, headerName = PROCAPTCHA_HEADER) => ({ [headerName]: token });
4
+ const authPathOf = (url, baseURL) => {
5
+ const requestURL = new URL(url, "http://localhost");
6
+ const basePath = baseURL ? new URL(baseURL, requestURL).pathname : "";
7
+ return normalizeAuthPath(requestURL.pathname, basePath);
8
+ };
9
+ export const procaptchaClient = (options = {}) => {
10
+ const { getToken } = options;
11
+ const headerName = options.headerName ?? PROCAPTCHA_HEADER;
12
+ const isProtected = createPathMatcher(options.endpoints?.length ? options.endpoints : DEFAULT_ENDPOINTS);
13
+ return {
14
+ id: "procaptcha",
15
+ $InferServerPlugin: {},
16
+ fetchPlugins: getToken
17
+ ? [
18
+ {
19
+ id: "procaptcha",
20
+ name: "procaptcha",
21
+ hooks: {
22
+ onRequest: async (context) => {
23
+ if (context.headers.has(headerName) ||
24
+ !isProtected(authPathOf(context.url, context.baseURL))) {
25
+ return context;
26
+ }
27
+ const token = await getToken();
28
+ if (token) {
29
+ context.headers.set(headerName, token);
30
+ }
31
+ return context;
32
+ },
33
+ },
34
+ },
35
+ ]
36
+ : [],
37
+ };
38
+ };
39
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAejE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAChC,KAAa,EACb,aAAqB,iBAAiB,EACb,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAEvD,MAAM,UAAU,GAAG,CAAC,GAAiB,EAAE,OAA2B,EAAU,EAAE;IAC7E,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,OAAO,iBAAiB,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,UAAmC,EAAE,EAAE,EAAE;IACzE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC7B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAC3D,MAAM,WAAW,GAAG,iBAAiB,CACpC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CACjE,CAAC;IAEF,OAAO;QACN,EAAE,EAAE,YAAY;QAChB,kBAAkB,EAAE,EAAmC;QACvD,YAAY,EAAE,QAAQ;YACrB,CAAC,CAAC;gBACA;oBACC,EAAE,EAAE,YAAY;oBAChB,IAAI,EAAE,YAAY;oBAClB,KAAK,EAAE;wBACN,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;4BAC5B,IACC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;gCAC/B,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,EACrD,CAAC;gCACF,OAAO,OAAO,CAAC;4BAChB,CAAC;4BACD,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;4BAC/B,IAAI,KAAK,EAAE,CAAC;gCACX,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;4BACxC,CAAC;4BACD,OAAO,OAAO,CAAC;wBAChB,CAAC;qBACD;iBACD;aACD;YACF,CAAC,CAAC,EAAE;KAC4B,CAAC;AACpC,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export declare const PROCAPTCHA_SITEVERIFY_URL = "https://api.prosopo.io/siteverify";
2
+ export declare const PROCAPTCHA_HEADER = "x-captcha-response";
3
+ export declare const DEFAULT_ENDPOINTS: readonly string[];
4
+ export declare const DEFAULT_TIMEOUT_MS = 10000;
5
+ export declare const PROCAPTCHA_ERROR_CODES: {
6
+ PROCAPTCHA_MISSING_RESPONSE: import("better-auth").RawError<"PROCAPTCHA_MISSING_RESPONSE">;
7
+ PROCAPTCHA_VERIFICATION_FAILED: import("better-auth").RawError<"PROCAPTCHA_VERIFICATION_FAILED">;
8
+ PROCAPTCHA_SERVICE_UNAVAILABLE: import("better-auth").RawError<"PROCAPTCHA_SERVICE_UNAVAILABLE">;
9
+ PROCAPTCHA_UNKNOWN_ERROR: import("better-auth").RawError<"PROCAPTCHA_UNKNOWN_ERROR">;
10
+ };
11
+ export type ProcaptchaErrorCode = keyof typeof PROCAPTCHA_ERROR_CODES;
12
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,yBAAyB,sCAAsC,CAAC;AAE7E,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAI9C,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,eAAO,MAAM,sBAAsB;;;;;CAKjC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,MAAM,OAAO,sBAAsB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { defineErrorCodes } from "better-auth";
2
+ export const PROCAPTCHA_SITEVERIFY_URL = "https://api.prosopo.io/siteverify";
3
+ export const PROCAPTCHA_HEADER = "x-captcha-response";
4
+ export const DEFAULT_ENDPOINTS = [
5
+ "/sign-up/email",
6
+ "/sign-in/email",
7
+ "/request-password-reset",
8
+ ];
9
+ export const DEFAULT_TIMEOUT_MS = 10_000;
10
+ export const PROCAPTCHA_ERROR_CODES = defineErrorCodes({
11
+ PROCAPTCHA_MISSING_RESPONSE: "Missing Procaptcha response",
12
+ PROCAPTCHA_VERIFICATION_FAILED: "Procaptcha verification failed",
13
+ PROCAPTCHA_SERVICE_UNAVAILABLE: "Procaptcha service unavailable",
14
+ PROCAPTCHA_UNKNOWN_ERROR: "Something went wrong",
15
+ });
16
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,CAAC,MAAM,yBAAyB,GAAG,mCAAmC,CAAC;AAE7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAEtD,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IACnD,gBAAgB;IAChB,gBAAgB;IAChB,yBAAyB;CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAEzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,gBAAgB,CAAC;IACtD,2BAA2B,EAAE,6BAA6B;IAC1D,8BAA8B,EAAE,gCAAgC;IAChE,8BAA8B,EAAE,gCAAgC;IAChE,wBAAwB,EAAE,sBAAsB;CAChD,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { AuthContext } from "better-auth";
2
+ export { DEFAULT_ENDPOINTS, PROCAPTCHA_ERROR_CODES, PROCAPTCHA_HEADER, PROCAPTCHA_SITEVERIFY_URL, type ProcaptchaErrorCode, } from "./constants.js";
3
+ export { verifyProcaptchaToken, type SiteVerifyErrorResponse, type SiteVerifyRequestBody, type SiteVerifyResponse, type VerifyResult, type VerifyTokenParams, } from "./siteverify.js";
4
+ export interface ProcaptchaOptions {
5
+ secretKey: string;
6
+ endpoints?: readonly string[];
7
+ siteVerifyURL?: string;
8
+ headerName?: string;
9
+ sendIP?: boolean;
10
+ sendEmailDomain?: boolean;
11
+ maxScore?: number;
12
+ timeoutMs?: number;
13
+ fetch?: typeof fetch;
14
+ }
15
+ export declare const procaptcha: (options: ProcaptchaOptions) => {
16
+ id: "procaptcha";
17
+ $ERROR_CODES: {
18
+ PROCAPTCHA_MISSING_RESPONSE: import("better-auth").RawError<"PROCAPTCHA_MISSING_RESPONSE">;
19
+ PROCAPTCHA_VERIFICATION_FAILED: import("better-auth").RawError<"PROCAPTCHA_VERIFICATION_FAILED">;
20
+ PROCAPTCHA_SERVICE_UNAVAILABLE: import("better-auth").RawError<"PROCAPTCHA_SERVICE_UNAVAILABLE">;
21
+ PROCAPTCHA_UNKNOWN_ERROR: import("better-auth").RawError<"PROCAPTCHA_UNKNOWN_ERROR">;
22
+ };
23
+ onRequest: (request: Request, ctx: AuthContext) => Promise<{
24
+ response: Response;
25
+ } | undefined>;
26
+ options: ProcaptchaOptions;
27
+ };
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACX,WAAW,EAGX,MAAM,aAAa,CAAC;AAarB,OAAO,EACN,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,yBAAyB,EACzB,KAAK,mBAAmB,GACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,qBAAqB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,iBAAiB;IAEjC,SAAS,EAAE,MAAM,CAAC;IAOlB,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE9B,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,UAAU,CAAC,EAAE,MAAM,CAAC;IAOpB,MAAM,CAAC,EAAE,OAAO,CAAC;IAOjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAM1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACrB;AA8CD,eAAO,MAAM,UAAU,YAAa,iBAAiB;;;;;;;;yBAUzC,OAAO,OACX,WAAW,KACd,OAAO,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAA;KAAE,GAAG,SAAS,CAAC;;CAgE/C,CAAC"}
@@ -0,0 +1,94 @@
1
+ import { getIP } from "better-auth/api";
2
+ import { DEFAULT_ENDPOINTS, DEFAULT_TIMEOUT_MS, PROCAPTCHA_ERROR_CODES, PROCAPTCHA_HEADER, PROCAPTCHA_SITEVERIFY_URL, } from "./constants.js";
3
+ import { createPathMatcher, normalizeAuthPath } from "./path.js";
4
+ import { verifyProcaptchaToken } from "./siteverify.js";
5
+ export { DEFAULT_ENDPOINTS, PROCAPTCHA_ERROR_CODES, PROCAPTCHA_HEADER, PROCAPTCHA_SITEVERIFY_URL, } from "./constants.js";
6
+ export { verifyProcaptchaToken, } from "./siteverify.js";
7
+ const errorResponse = (code, status) => ({
8
+ response: Response.json({ code, message: PROCAPTCHA_ERROR_CODES[code].message }, { status }),
9
+ });
10
+ const resolveClientIP = (request, options) => getIP(request, {
11
+ ...options,
12
+ advanced: {
13
+ ...options.advanced,
14
+ ipAddress: { ...options.advanced?.ipAddress, ipv6Subnet: 128 },
15
+ },
16
+ }) ?? undefined;
17
+ const readEmailDomain = async (request) => {
18
+ if (!request.headers.get("content-type")?.includes("application/json")) {
19
+ return undefined;
20
+ }
21
+ try {
22
+ const body = await request.clone().json();
23
+ if (typeof body !== "object" || body === null || !("email" in body)) {
24
+ return undefined;
25
+ }
26
+ const { email } = body;
27
+ if (typeof email !== "string") {
28
+ return undefined;
29
+ }
30
+ const domain = email.slice(email.lastIndexOf("@") + 1).trim();
31
+ return email.includes("@") && domain ? domain.toLowerCase() : undefined;
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ };
37
+ export const procaptcha = (options) => {
38
+ const isProtected = createPathMatcher(options.endpoints?.length ? options.endpoints : DEFAULT_ENDPOINTS);
39
+ const headerName = options.headerName ?? PROCAPTCHA_HEADER;
40
+ return {
41
+ id: "procaptcha",
42
+ $ERROR_CODES: PROCAPTCHA_ERROR_CODES,
43
+ onRequest: async (request, ctx) => {
44
+ const path = normalizeAuthPath(new URL(request.url).pathname, ctx.options.basePath ?? "/api/auth");
45
+ if (!isProtected(path)) {
46
+ return undefined;
47
+ }
48
+ if (!options.secretKey) {
49
+ ctx.logger.error("Procaptcha: secretKey is not configured");
50
+ return errorResponse("PROCAPTCHA_UNKNOWN_ERROR", 500);
51
+ }
52
+ const token = request.headers.get(headerName);
53
+ if (!token) {
54
+ return errorResponse("PROCAPTCHA_MISSING_RESPONSE", 400);
55
+ }
56
+ const ip = options.sendIP === false
57
+ ? undefined
58
+ : resolveClientIP(request, ctx.options);
59
+ const email = options.sendEmailDomain
60
+ ? await readEmailDomain(request)
61
+ : undefined;
62
+ const result = await verifyProcaptchaToken({
63
+ secretKey: options.secretKey,
64
+ token,
65
+ ...(ip ? { ip } : {}),
66
+ ...(email ? { email } : {}),
67
+ siteVerifyURL: options.siteVerifyURL ?? PROCAPTCHA_SITEVERIFY_URL,
68
+ timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
69
+ ...(options.fetch ? { fetch: options.fetch } : {}),
70
+ });
71
+ if (result.outcome === "error") {
72
+ ctx.logger.error("Procaptcha siteverify failed", {
73
+ status: result.status,
74
+ key: result.key,
75
+ message: result.message,
76
+ });
77
+ return result.transient
78
+ ? errorResponse("PROCAPTCHA_SERVICE_UNAVAILABLE", 503)
79
+ : errorResponse("PROCAPTCHA_UNKNOWN_ERROR", 500);
80
+ }
81
+ if (result.outcome === "rejected") {
82
+ return errorResponse("PROCAPTCHA_VERIFICATION_FAILED", 403);
83
+ }
84
+ if (options.maxScore !== undefined &&
85
+ result.score !== undefined &&
86
+ result.score > options.maxScore) {
87
+ return errorResponse("PROCAPTCHA_VERIFICATION_FAILED", 403);
88
+ }
89
+ return undefined;
90
+ },
91
+ options,
92
+ };
93
+ };
94
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const normalizeAuthPath: (pathname: string, basePath: string) => string;
2
+ export type PathMatcher = (path: string) => boolean;
3
+ export declare const createPathMatcher: (endpoints: readonly string[]) => PathMatcher;
4
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/path.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,iBAAiB,aACnB,MAAM,YACN,MAAM,KACd,MAOF,CAAC;AAoDF,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;AAEpD,eAAO,MAAM,iBAAiB,cAClB,SAAS,MAAM,EAAE,KAC1B,WAUF,CAAC"}
@@ -0,0 +1,59 @@
1
+ export const normalizeAuthPath = (pathname, basePath) => {
2
+ const relative = basePath && pathname.startsWith(basePath)
3
+ ? pathname.slice(basePath.length)
4
+ : pathname;
5
+ const collapsed = `/${relative}`.replace(/\/{2,}/g, "/");
6
+ return collapsed.length > 1 ? collapsed.replace(/\/$/, "") : collapsed;
7
+ };
8
+ const matchesSegment = (pattern, segment) => {
9
+ const parts = pattern.split("*");
10
+ if (parts.length === 1) {
11
+ return pattern === segment;
12
+ }
13
+ const first = parts[0] ?? "";
14
+ const last = parts[parts.length - 1] ?? "";
15
+ if (segment.length < first.length + last.length ||
16
+ !segment.startsWith(first) ||
17
+ !segment.endsWith(last)) {
18
+ return false;
19
+ }
20
+ let cursor = first.length;
21
+ const end = segment.length - last.length;
22
+ for (const part of parts.slice(1, -1)) {
23
+ const found = segment.indexOf(part, cursor);
24
+ if (found === -1 || found + part.length > end) {
25
+ return false;
26
+ }
27
+ cursor = found + part.length;
28
+ }
29
+ return true;
30
+ };
31
+ const matchesSegments = (patterns, segments) => {
32
+ const [pattern, ...restPatterns] = patterns;
33
+ if (pattern === undefined) {
34
+ return segments.length === 0;
35
+ }
36
+ if (pattern === "**") {
37
+ for (let skip = 0; skip <= segments.length; skip++) {
38
+ if (matchesSegments(restPatterns, segments.slice(skip))) {
39
+ return true;
40
+ }
41
+ }
42
+ return false;
43
+ }
44
+ const [segment, ...restSegments] = segments;
45
+ return (segment !== undefined &&
46
+ matchesSegment(pattern, segment) &&
47
+ matchesSegments(restPatterns, restSegments));
48
+ };
49
+ export const createPathMatcher = (endpoints) => {
50
+ const matchers = endpoints.map((endpoint) => {
51
+ if (!endpoint.includes("*")) {
52
+ return (path) => path === endpoint;
53
+ }
54
+ const patterns = endpoint.split("/");
55
+ return (path) => matchesSegments(patterns, path.split("/"));
56
+ });
57
+ return (path) => matchers.some((matches) => matches(path));
58
+ };
59
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { VerificationResponse } from "@prosopo/types";
2
+ export interface SiteVerifyRequestBody {
3
+ secret: string;
4
+ token: string;
5
+ ip?: string;
6
+ email?: string;
7
+ }
8
+ export type SiteVerifyResponse = Omit<VerificationResponse, "error" | "sessionId">;
9
+ export interface SiteVerifyErrorResponse {
10
+ error: {
11
+ code: number;
12
+ key: string;
13
+ message: string | unknown[];
14
+ };
15
+ }
16
+ export type VerifyResult = {
17
+ outcome: "verified";
18
+ score?: number;
19
+ } | {
20
+ outcome: "rejected";
21
+ reason?: string;
22
+ score?: number;
23
+ } | {
24
+ outcome: "error";
25
+ transient: boolean;
26
+ status?: number;
27
+ key?: string;
28
+ message: string;
29
+ };
30
+ export interface VerifyTokenParams {
31
+ secretKey: string;
32
+ token: string;
33
+ ip?: string;
34
+ email?: string;
35
+ siteVerifyURL?: string;
36
+ timeoutMs?: number;
37
+ fetch?: typeof fetch;
38
+ }
39
+ export declare const verifyProcaptchaToken: ({ secretKey, token, ip, email, siteVerifyURL, timeoutMs, fetch: fetchImpl, }: VerifyTokenParams) => Promise<VerifyResult>;
40
+ //# sourceMappingURL=siteverify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siteverify.d.ts","sourceRoot":"","sources":["../../src/siteverify.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3D,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACpC,oBAAoB,EACpB,OAAO,GAAG,WAAW,CACrB,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACvC,KAAK,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC;KAC5B,CAAC;CACF;AAED,MAAM,MAAM,YAAY,GACrB;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD;IACA,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACf,CAAC;AAEL,MAAM,WAAW,iBAAiB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACrB;AA+BD,eAAO,MAAM,qBAAqB,iFAQ/B,iBAAiB,KAAG,OAAO,CAAC,YAAY,CA+D1C,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { DEFAULT_TIMEOUT_MS, PROCAPTCHA_SITEVERIFY_URL } from "./constants.js";
2
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3
+ const isSiteVerifyResponse = (value) => isRecord(value) &&
4
+ typeof value.status === "string" &&
5
+ typeof value.verified === "boolean" &&
6
+ (value.score === undefined || typeof value.score === "number") &&
7
+ (value.reason === undefined || typeof value.reason === "string");
8
+ const isSiteVerifyErrorResponse = (value) => isRecord(value) &&
9
+ isRecord(value.error) &&
10
+ typeof value.error.key === "string";
11
+ const readJson = async (response) => {
12
+ try {
13
+ const body = await response.json();
14
+ return body;
15
+ }
16
+ catch {
17
+ return undefined;
18
+ }
19
+ };
20
+ const isTransientStatus = (status) => status === 429 || status >= 500;
21
+ export const verifyProcaptchaToken = async ({ secretKey, token, ip, email, siteVerifyURL = PROCAPTCHA_SITEVERIFY_URL, timeoutMs = DEFAULT_TIMEOUT_MS, fetch: fetchImpl = fetch, }) => {
22
+ const body = {
23
+ secret: secretKey,
24
+ token,
25
+ ...(ip ? { ip } : {}),
26
+ ...(email ? { email } : {}),
27
+ };
28
+ let response;
29
+ try {
30
+ response = await fetchImpl(siteVerifyURL, {
31
+ method: "POST",
32
+ headers: {
33
+ "Content-Type": "application/json",
34
+ Accept: "application/json",
35
+ },
36
+ body: JSON.stringify(body),
37
+ signal: AbortSignal.timeout(timeoutMs),
38
+ });
39
+ }
40
+ catch (error) {
41
+ return {
42
+ outcome: "error",
43
+ transient: true,
44
+ message: error instanceof Error ? error.message : String(error),
45
+ };
46
+ }
47
+ const payload = await readJson(response);
48
+ if (!response.ok) {
49
+ const errorBody = isSiteVerifyErrorResponse(payload)
50
+ ? payload.error
51
+ : undefined;
52
+ return {
53
+ outcome: "error",
54
+ transient: isTransientStatus(response.status),
55
+ status: response.status,
56
+ ...(errorBody ? { key: errorBody.key } : {}),
57
+ message: typeof errorBody?.message === "string"
58
+ ? errorBody.message
59
+ : `siteverify responded with HTTP ${response.status}`,
60
+ };
61
+ }
62
+ if (!isSiteVerifyResponse(payload)) {
63
+ return {
64
+ outcome: "error",
65
+ transient: true,
66
+ status: response.status,
67
+ message: "siteverify returned an unexpected response body",
68
+ };
69
+ }
70
+ const score = payload.score === undefined ? {} : { score: payload.score };
71
+ if (!payload.verified) {
72
+ return {
73
+ outcome: "rejected",
74
+ ...(payload.reason ? { reason: payload.reason } : {}),
75
+ ...score,
76
+ };
77
+ }
78
+ return { outcome: "verified", ...score };
79
+ };
80
+ //# sourceMappingURL=siteverify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siteverify.js","sourceRoot":"","sources":["../../src/siteverify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.unit.test.d.ts","sourceRoot":"","sources":["../../../src/tests/client.unit.test.ts"],"names":[],"mappings":""}