@nauth-toolkit/recaptcha 0.1.92

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.
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RecaptchaV3Provider = void 0;
4
+ /**
5
+ * Google reCAPTCHA v3 Provider
6
+ *
7
+ * Implements invisible, score-based bot detection without user interaction.
8
+ * Returns a risk score (0.0 - 1.0) indicating likelihood of bot activity.
9
+ *
10
+ * v3 is recommended for most web applications as it provides better UX
11
+ * by not requiring user interaction while still detecting bots effectively.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const provider = new RecaptchaV3Provider({
16
+ * secretKey: process.env.RECAPTCHA_SECRET_KEY!,
17
+ * });
18
+ *
19
+ * const result = await provider.verify(token, clientIp, 'login');
20
+ *
21
+ * if (!result.success) {
22
+ * throw new Error('reCAPTCHA validation failed');
23
+ * }
24
+ *
25
+ * if (result.score && result.score < 0.5) {
26
+ * throw new Error('Suspicious activity detected');
27
+ * }
28
+ * ```
29
+ */
30
+ class RecaptchaV3Provider {
31
+ secretKey;
32
+ verifyUrl;
33
+ timeout;
34
+ constructor(config) {
35
+ this.secretKey = config.secretKey;
36
+ this.verifyUrl = config.verifyUrl || 'https://www.google.com/recaptcha/api/siteverify';
37
+ this.timeout = config.timeout || 10000;
38
+ }
39
+ /**
40
+ * Verify reCAPTCHA v3 token with Google's API
41
+ *
42
+ * @param token - Token from client
43
+ * @param remoteIp - Client IP address (optional but recommended)
44
+ * @param action - Action name used when generating token (e.g., 'login', 'signup')
45
+ * @returns Verification result with score
46
+ *
47
+ * @throws Error if network request fails or times out
48
+ */
49
+ async verify(token, remoteIp, _action) {
50
+ // Build request body
51
+ const params = new URLSearchParams({
52
+ secret: this.secretKey,
53
+ response: token,
54
+ });
55
+ if (remoteIp) {
56
+ params.append('remoteip', remoteIp);
57
+ }
58
+ try {
59
+ // Create abort controller for timeout
60
+ const controller = new AbortController();
61
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
62
+ // Make request to Google's API
63
+ const response = await fetch(this.verifyUrl, {
64
+ method: 'POST',
65
+ headers: {
66
+ 'Content-Type': 'application/x-www-form-urlencoded',
67
+ },
68
+ body: params.toString(),
69
+ signal: controller.signal,
70
+ });
71
+ clearTimeout(timeoutId);
72
+ if (!response.ok) {
73
+ throw new Error(`reCAPTCHA API returned status ${response.status}`);
74
+ }
75
+ const data = await response.json();
76
+ // Map Google's response to our interface
77
+ return {
78
+ success: data.success === true,
79
+ score: data.score,
80
+ action: data.action,
81
+ hostname: data.hostname,
82
+ errorCodes: data['error-codes'],
83
+ };
84
+ }
85
+ catch (error) {
86
+ // Handle network errors
87
+ if (error instanceof Error) {
88
+ if (error.name === 'AbortError') {
89
+ throw new Error(`reCAPTCHA verification timeout after ${this.timeout}ms`);
90
+ }
91
+ throw new Error(`reCAPTCHA verification failed: ${error.message}`);
92
+ }
93
+ throw new Error('reCAPTCHA verification failed with unknown error');
94
+ }
95
+ }
96
+ }
97
+ exports.RecaptchaV3Provider = RecaptchaV3Provider;
98
+ //# sourceMappingURL=recaptcha-v3.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recaptcha-v3.provider.js","sourceRoot":"","sources":["../../../src/providers/recaptcha-v3.provider.ts"],"names":[],"mappings":";;;AA2BA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAa,mBAAmB;IACb,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,OAAO,CAAS;IAEjC,YAAY,MAAyB;QACnC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,iDAAiD,CAAC;QACvF,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC;IACzC,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,QAAiB,EAAE,OAAgB;QAC7D,qBAAqB;QACrB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,MAAM,EAAE,IAAI,CAAC,SAAS;YACtB,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;QAEH,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,CAAC;YACH,sCAAsC;YACtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAErE,+BAA+B;YAC/B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE;gBAC3C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,mCAAmC;iBACpD;gBACD,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;gBACvB,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEnC,yCAAyC;YACzC,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,IAAI;gBAC9B,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;aAChC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,wBAAwB;YACxB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;gBAC5E,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;CACF;AA1ED,kDA0EC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Google reCAPTCHA provider interface
3
+ *
4
+ * Supports v2, v3, and Enterprise versions of Google reCAPTCHA.
5
+ * Implementations should handle token verification with Google's API.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const provider = new RecaptchaV3Provider({ secretKey: 'your-secret' });
10
+ * const result = await provider.verify(token, clientIp, 'login');
11
+ * if (result.success) {
12
+ * console.log('Valid token');
13
+ * }
14
+ * ```
15
+ */
16
+ export interface RecaptchaProvider {
17
+ /**
18
+ * Verify reCAPTCHA token with Google's API
19
+ *
20
+ * @param token - Token from client (generated by Google reCAPTCHA)
21
+ * @param remoteIp - Client IP address (optional but recommended for security)
22
+ * @param action - Action name for v3/Enterprise (e.g., 'login', 'signup')
23
+ * @returns Verification result with score (v3/Enterprise) or success (v2)
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const result = await provider.verify(
28
+ * 'token-from-client',
29
+ * '192.168.1.1',
30
+ * 'login'
31
+ * );
32
+ * ```
33
+ */
34
+ verify(token: string, remoteIp?: string, action?: string): Promise<RecaptchaVerificationResult>;
35
+ }
36
+ /**
37
+ * Result of reCAPTCHA token verification
38
+ *
39
+ * Different fields are populated depending on reCAPTCHA version:
40
+ * - v2: success, challengeTs, hostname
41
+ * - v3: success, score, action, hostname
42
+ * - Enterprise: success, score, action, hostname
43
+ */
44
+ export interface RecaptchaVerificationResult {
45
+ /**
46
+ * Whether the token is valid
47
+ */
48
+ success: boolean;
49
+ /**
50
+ * Risk score for v3/Enterprise (0.0 - 1.0)
51
+ *
52
+ * - 0.0: Very likely a bot
53
+ * - 1.0: Very likely a human
54
+ * - Not present for v2
55
+ */
56
+ score?: number;
57
+ /**
58
+ * Action name that was verified (v3/Enterprise only)
59
+ */
60
+ action?: string;
61
+ /**
62
+ * Timestamp of the challenge load (v2 only)
63
+ * ISO 8601 format
64
+ */
65
+ challengeTs?: string;
66
+ /**
67
+ * Hostname of the site where the reCAPTCHA was solved
68
+ */
69
+ hostname?: string;
70
+ /**
71
+ * Error codes returned by Google (if any)
72
+ *
73
+ * Common errors:
74
+ * - missing-input-secret: Secret key is missing
75
+ * - invalid-input-secret: Secret key is invalid
76
+ * - missing-input-response: Token is missing
77
+ * - invalid-input-response: Token is invalid or expired
78
+ * - timeout-or-duplicate: Token has been used or expired
79
+ */
80
+ errorCodes?: string[];
81
+ }
82
+ //# sourceMappingURL=recaptcha-provider.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recaptcha-provider.interface.d.ts","sourceRoot":"","sources":["../../src/recaptcha-provider.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACjG;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=recaptcha-provider.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recaptcha-provider.interface.js","sourceRoot":"","sources":["../../src/recaptcha-provider.interface.ts"],"names":[],"mappings":""}