@lunora/auth 1.0.0-alpha.7 → 1.0.0-alpha.71
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/LICENSE.md +38 -0
- package/README.md +56 -1
- package/dist/adapter.d.mts +4 -43
- package/dist/adapter.d.ts +4 -43
- package/dist/adapter.mjs +1 -47
- package/dist/audit.d.mts +146 -0
- package/dist/audit.d.ts +146 -0
- package/dist/audit.mjs +12 -0
- package/dist/email-guard.d.mts +122 -0
- package/dist/email-guard.d.ts +122 -0
- package/dist/email-guard.mjs +1 -0
- package/dist/index.d.mts +698 -147
- package/dist/index.d.ts +698 -147
- package/dist/index.mjs +1 -12
- package/dist/middleware.d.mts +157 -156
- package/dist/middleware.d.ts +157 -156
- package/dist/middleware.mjs +1 -53
- package/dist/packem_shared/AUTH_DO_AUDIT_PATH-C4897amZ.mjs +1 -0
- package/dist/packem_shared/DEFAULT_AUTH_BASE_PATH-kIwlEt8i.mjs +1 -0
- package/dist/packem_shared/LunoraAuthAdminError-CiHsF1qZ.mjs +1 -0
- package/dist/packem_shared/adapter-RvDcm0Zy.mjs +1 -0
- package/dist/packem_shared/adapter.d-2a61HAY2.d.ts +76 -0
- package/dist/packem_shared/adapter.d-DrD3bb1u.d.mts +76 -0
- package/dist/packem_shared/authAuditHook-DG_ZNO53.mjs +1 -0
- package/dist/packem_shared/authDoColumnAdditions-B8BRbdzn.mjs +1 -0
- package/dist/packem_shared/compileMigrationsSql-BcvcHAqo.mjs +1 -0
- package/dist/packem_shared/create-auth.d-De6IOirt.d.mts +128 -0
- package/dist/packem_shared/create-auth.d-De6IOirt.d.ts +128 -0
- package/dist/packem_shared/createAuth-DRtd4q6u.mjs +1 -0
- package/dist/packem_shared/createDoAuthWiring-acnXUGZr.mjs +1 -0
- package/dist/packem_shared/createLunoraAuthClient-CedinxXU.mjs +1 -0
- package/dist/packem_shared/emailGateDatabaseHooks-DzBD1Qoq.mjs +1 -0
- package/dist/packem_shared/sessionPresets-DpEFjXKV.mjs +1 -0
- package/dist/packem_shared/uiConfig-BrYEFK3O.mjs +1 -0
- package/dist/plugins-client.d.mts +68 -1
- package/dist/plugins-client.d.ts +68 -1
- package/dist/plugins-client.mjs +1 -2
- package/dist/plugins-enterprise-client.d.mts +9 -0
- package/dist/plugins-enterprise-client.d.ts +9 -0
- package/dist/plugins-enterprise-client.mjs +1 -0
- package/dist/plugins-enterprise.d.mts +1576 -0
- package/dist/plugins-enterprise.d.ts +1576 -0
- package/dist/plugins-enterprise.mjs +1 -0
- package/dist/plugins.d.mts +83 -2
- package/dist/plugins.d.ts +83 -2
- package/dist/plugins.mjs +1 -22
- package/dist/schema.d.mts +39 -39
- package/dist/schema.d.ts +39 -39
- package/dist/schema.mjs +1 -62
- package/dist/sql-store.d.mts +28 -28
- package/dist/sql-store.d.ts +28 -28
- package/dist/sql-store.mjs +1 -162
- package/dist/store.d.mts +49 -31
- package/dist/store.d.ts +49 -31
- package/dist/store.mjs +1 -170
- package/dist/turnstile-middleware.d.mts +55 -55
- package/dist/turnstile-middleware.d.ts +55 -55
- package/dist/turnstile-middleware.mjs +1 -45
- package/dist/turnstile.d.mts +42 -59
- package/dist/turnstile.d.ts +42 -59
- package/dist/turnstile.mjs +1 -61
- package/package.json +38 -5
- package/dist/packem_shared/DEFAULT_AUTH_BASE_PATH-DjcUWEQl.mjs +0 -11
- package/dist/packem_shared/LunoraAuthAdminError-BxrfEeA_.mjs +0 -249
- package/dist/packem_shared/compileMigrationsSql-wZH3oXDu.mjs +0 -28
- package/dist/packem_shared/create-auth.d-M36jwG_Y.d.mts +0 -58
- package/dist/packem_shared/create-auth.d-M36jwG_Y.d.ts +0 -58
- package/dist/packem_shared/createAuth-B-tvsvQU.mjs +0 -56
- package/dist/packem_shared/sessionPresets-B95rXrd8.mjs +0 -35
|
@@ -2,79 +2,79 @@ import { Middleware } from '@lunora/server';
|
|
|
2
2
|
import { FetchLike, TurnstileVerifyResult } from "./turnstile.mjs";
|
|
3
3
|
interface VerifyTurnstileMiddlewareOptions<Context> {
|
|
4
4
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
* Assert the widget `action` the token was solved for (forwarded to
|
|
6
|
+
* {@link verifyTurnstile}). When set and the siteverify response's `action`
|
|
7
|
+
* does not match, the verdict is treated as a failure (403). Optional.
|
|
8
|
+
*/
|
|
9
9
|
expectedAction?: string;
|
|
10
10
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
* Assert the `hostname` the challenge was solved on (forwarded to
|
|
12
|
+
* {@link verifyTurnstile}). When set and the siteverify response's `hostname`
|
|
13
|
+
* does not match, the verdict is treated as a failure (403). Set this when a
|
|
14
|
+
* single secret/sitekey is shared across multiple domains to stop a token
|
|
15
|
+
* harvested on one origin being replayed against this procedure. Optional.
|
|
16
|
+
*/
|
|
17
17
|
expectedHostname?: string;
|
|
18
18
|
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
* Behavior when the siteverify call itself throws (network error, non-2xx).
|
|
20
|
+
* Defaults to `false` (**fail closed**: reject with 403). Set `true` only
|
|
21
|
+
* when degraded availability is preferable to denying traffic — a failing
|
|
22
|
+
* siteverify then admits every request. Mirrors `@lunora/ratelimit`'s
|
|
23
|
+
* `rateLimit` failure policy.
|
|
24
|
+
*/
|
|
25
25
|
failOpen?: boolean;
|
|
26
26
|
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
* Inject a `fetch` implementation (forwarded to {@link verifyTurnstile}).
|
|
28
|
+
* Primarily for tests.
|
|
29
|
+
*/
|
|
30
30
|
fetch?: FetchLike;
|
|
31
31
|
/** Override the error message thrown on a failed verdict. */
|
|
32
32
|
message?: string;
|
|
33
33
|
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
* Selector that pulls the visitor IP from `ctx` (the procedure context has
|
|
35
|
+
* no raw `Headers`, so this must come from `args`/ctx). Optional.
|
|
36
|
+
*/
|
|
37
37
|
remoteip?: (context: Context) => string | undefined;
|
|
38
38
|
/** Your Turnstile secret key (the `TURNSTILE_SECRET_KEY` env var). */
|
|
39
39
|
secret: string;
|
|
40
40
|
/**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
* Selector that pulls the `cf-turnstile-response` token from `ctx`. The
|
|
42
|
+
* procedure context carries only the resolved identity, **not** the raw
|
|
43
|
+
* inbound `Headers` (see `withAuthPlugins` in `./middleware`), so the token
|
|
44
|
+
* must travel in the function `args` and be read out here.
|
|
45
|
+
*/
|
|
46
46
|
token: (context: Context) => string | undefined;
|
|
47
47
|
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
* Extra predicate run on a `success: true` verdict (after the built-in
|
|
49
|
+
* `expectedHostname`/`expectedAction` checks). Return `false` to reject the
|
|
50
|
+
* request with 403 — use it for any custom replay/abuse guard that needs the
|
|
51
|
+
* full verdict (e.g. matching `cdata`, or one hostname out of an allow-list).
|
|
52
|
+
*/
|
|
53
53
|
validate?: (result: TurnstileVerifyResult) => boolean;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Procedure middleware that enforces a Turnstile (CAPTCHA) check before the
|
|
57
|
-
* handler runs. Attach it with `.use()`. It reads the token (and optional IP)
|
|
58
|
-
* from `ctx` via the provided selectors — because the procedure context does
|
|
59
|
-
* not carry raw request headers, the token must be passed through the function
|
|
60
|
-
* `args`. To gate the better-auth sign-in/sign-up flow itself, prefer
|
|
61
|
-
* better-auth's native `captcha` plugin (re-exported from `@lunora/auth/plugins`)
|
|
62
|
-
* — this middleware is for non-auth Lunora procedures.
|
|
63
|
-
*
|
|
64
|
-
* On a `success: false` verdict (or a missing token) it throws a structural
|
|
65
|
-
* `LunoraError` (`{ name: "LunoraError", code: "FORBIDDEN", status: 403 }`) —
|
|
66
|
-
* the runtime maps it to the matching RPC/HTTP status without any runtime
|
|
67
|
-
* import of `@lunora/server` (the `Middleware` import is type-only).
|
|
68
|
-
*
|
|
69
|
-
* **Failure policy:** if the siteverify call itself throws, the middleware
|
|
70
|
-
* **fails closed by default** (logs and rejects with 403). Pass
|
|
71
|
-
* `failOpen: true` to admit the request instead — mirrors `@lunora/ratelimit`.
|
|
72
|
-
*
|
|
73
|
-
* **Cross-origin replay:** a token solved on one origin can be replayed against
|
|
74
|
-
* a different endpoint when a single secret/sitekey is shared across multiple
|
|
75
|
-
* domains. Pass `expectedHostname` (and optionally `expectedAction`, or a custom
|
|
76
|
-
* `validate(result)` predicate) to assert the siteverify response's `hostname`
|
|
77
|
-
* /`action` and reject mismatches with 403.
|
|
78
|
-
*/
|
|
56
|
+
* Procedure middleware that enforces a Turnstile (CAPTCHA) check before the
|
|
57
|
+
* handler runs. Attach it with `.use()`. It reads the token (and optional IP)
|
|
58
|
+
* from `ctx` via the provided selectors — because the procedure context does
|
|
59
|
+
* not carry raw request headers, the token must be passed through the function
|
|
60
|
+
* `args`. To gate the better-auth sign-in/sign-up flow itself, prefer
|
|
61
|
+
* better-auth's native `captcha` plugin (re-exported from `@lunora/auth/plugins`)
|
|
62
|
+
* — this middleware is for non-auth Lunora procedures.
|
|
63
|
+
*
|
|
64
|
+
* On a `success: false` verdict (or a missing token) it throws a structural
|
|
65
|
+
* `LunoraError` (`{ name: "LunoraError", code: "FORBIDDEN", status: 403 }`) —
|
|
66
|
+
* the runtime maps it to the matching RPC/HTTP status without any runtime
|
|
67
|
+
* import of `@lunora/server` (the `Middleware` import is type-only).
|
|
68
|
+
*
|
|
69
|
+
* **Failure policy:** if the siteverify call itself throws, the middleware
|
|
70
|
+
* **fails closed by default** (logs and rejects with 403). Pass
|
|
71
|
+
* `failOpen: true` to admit the request instead — mirrors `@lunora/ratelimit`.
|
|
72
|
+
*
|
|
73
|
+
* **Cross-origin replay:** a token solved on one origin can be replayed against
|
|
74
|
+
* a different endpoint when a single secret/sitekey is shared across multiple
|
|
75
|
+
* domains. Pass `expectedHostname` (and optionally `expectedAction`, or a custom
|
|
76
|
+
* `validate(result)` predicate) to assert the siteverify response's `hostname`
|
|
77
|
+
* /`action` and reject mismatches with 403.
|
|
78
|
+
*/
|
|
79
79
|
declare const verifyTurnstileMiddleware: <Context>(options: VerifyTurnstileMiddlewareOptions<Context>) => Middleware<Context, Context>;
|
|
80
80
|
export { type VerifyTurnstileMiddlewareOptions, verifyTurnstileMiddleware };
|
|
@@ -2,79 +2,79 @@ import { Middleware } from '@lunora/server';
|
|
|
2
2
|
import { FetchLike, TurnstileVerifyResult } from "./turnstile.js";
|
|
3
3
|
interface VerifyTurnstileMiddlewareOptions<Context> {
|
|
4
4
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
* Assert the widget `action` the token was solved for (forwarded to
|
|
6
|
+
* {@link verifyTurnstile}). When set and the siteverify response's `action`
|
|
7
|
+
* does not match, the verdict is treated as a failure (403). Optional.
|
|
8
|
+
*/
|
|
9
9
|
expectedAction?: string;
|
|
10
10
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
* Assert the `hostname` the challenge was solved on (forwarded to
|
|
12
|
+
* {@link verifyTurnstile}). When set and the siteverify response's `hostname`
|
|
13
|
+
* does not match, the verdict is treated as a failure (403). Set this when a
|
|
14
|
+
* single secret/sitekey is shared across multiple domains to stop a token
|
|
15
|
+
* harvested on one origin being replayed against this procedure. Optional.
|
|
16
|
+
*/
|
|
17
17
|
expectedHostname?: string;
|
|
18
18
|
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
* Behavior when the siteverify call itself throws (network error, non-2xx).
|
|
20
|
+
* Defaults to `false` (**fail closed**: reject with 403). Set `true` only
|
|
21
|
+
* when degraded availability is preferable to denying traffic — a failing
|
|
22
|
+
* siteverify then admits every request. Mirrors `@lunora/ratelimit`'s
|
|
23
|
+
* `rateLimit` failure policy.
|
|
24
|
+
*/
|
|
25
25
|
failOpen?: boolean;
|
|
26
26
|
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
* Inject a `fetch` implementation (forwarded to {@link verifyTurnstile}).
|
|
28
|
+
* Primarily for tests.
|
|
29
|
+
*/
|
|
30
30
|
fetch?: FetchLike;
|
|
31
31
|
/** Override the error message thrown on a failed verdict. */
|
|
32
32
|
message?: string;
|
|
33
33
|
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
* Selector that pulls the visitor IP from `ctx` (the procedure context has
|
|
35
|
+
* no raw `Headers`, so this must come from `args`/ctx). Optional.
|
|
36
|
+
*/
|
|
37
37
|
remoteip?: (context: Context) => string | undefined;
|
|
38
38
|
/** Your Turnstile secret key (the `TURNSTILE_SECRET_KEY` env var). */
|
|
39
39
|
secret: string;
|
|
40
40
|
/**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
* Selector that pulls the `cf-turnstile-response` token from `ctx`. The
|
|
42
|
+
* procedure context carries only the resolved identity, **not** the raw
|
|
43
|
+
* inbound `Headers` (see `withAuthPlugins` in `./middleware`), so the token
|
|
44
|
+
* must travel in the function `args` and be read out here.
|
|
45
|
+
*/
|
|
46
46
|
token: (context: Context) => string | undefined;
|
|
47
47
|
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
* Extra predicate run on a `success: true` verdict (after the built-in
|
|
49
|
+
* `expectedHostname`/`expectedAction` checks). Return `false` to reject the
|
|
50
|
+
* request with 403 — use it for any custom replay/abuse guard that needs the
|
|
51
|
+
* full verdict (e.g. matching `cdata`, or one hostname out of an allow-list).
|
|
52
|
+
*/
|
|
53
53
|
validate?: (result: TurnstileVerifyResult) => boolean;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Procedure middleware that enforces a Turnstile (CAPTCHA) check before the
|
|
57
|
-
* handler runs. Attach it with `.use()`. It reads the token (and optional IP)
|
|
58
|
-
* from `ctx` via the provided selectors — because the procedure context does
|
|
59
|
-
* not carry raw request headers, the token must be passed through the function
|
|
60
|
-
* `args`. To gate the better-auth sign-in/sign-up flow itself, prefer
|
|
61
|
-
* better-auth's native `captcha` plugin (re-exported from `@lunora/auth/plugins`)
|
|
62
|
-
* — this middleware is for non-auth Lunora procedures.
|
|
63
|
-
*
|
|
64
|
-
* On a `success: false` verdict (or a missing token) it throws a structural
|
|
65
|
-
* `LunoraError` (`{ name: "LunoraError", code: "FORBIDDEN", status: 403 }`) —
|
|
66
|
-
* the runtime maps it to the matching RPC/HTTP status without any runtime
|
|
67
|
-
* import of `@lunora/server` (the `Middleware` import is type-only).
|
|
68
|
-
*
|
|
69
|
-
* **Failure policy:** if the siteverify call itself throws, the middleware
|
|
70
|
-
* **fails closed by default** (logs and rejects with 403). Pass
|
|
71
|
-
* `failOpen: true` to admit the request instead — mirrors `@lunora/ratelimit`.
|
|
72
|
-
*
|
|
73
|
-
* **Cross-origin replay:** a token solved on one origin can be replayed against
|
|
74
|
-
* a different endpoint when a single secret/sitekey is shared across multiple
|
|
75
|
-
* domains. Pass `expectedHostname` (and optionally `expectedAction`, or a custom
|
|
76
|
-
* `validate(result)` predicate) to assert the siteverify response's `hostname`
|
|
77
|
-
* /`action` and reject mismatches with 403.
|
|
78
|
-
*/
|
|
56
|
+
* Procedure middleware that enforces a Turnstile (CAPTCHA) check before the
|
|
57
|
+
* handler runs. Attach it with `.use()`. It reads the token (and optional IP)
|
|
58
|
+
* from `ctx` via the provided selectors — because the procedure context does
|
|
59
|
+
* not carry raw request headers, the token must be passed through the function
|
|
60
|
+
* `args`. To gate the better-auth sign-in/sign-up flow itself, prefer
|
|
61
|
+
* better-auth's native `captcha` plugin (re-exported from `@lunora/auth/plugins`)
|
|
62
|
+
* — this middleware is for non-auth Lunora procedures.
|
|
63
|
+
*
|
|
64
|
+
* On a `success: false` verdict (or a missing token) it throws a structural
|
|
65
|
+
* `LunoraError` (`{ name: "LunoraError", code: "FORBIDDEN", status: 403 }`) —
|
|
66
|
+
* the runtime maps it to the matching RPC/HTTP status without any runtime
|
|
67
|
+
* import of `@lunora/server` (the `Middleware` import is type-only).
|
|
68
|
+
*
|
|
69
|
+
* **Failure policy:** if the siteverify call itself throws, the middleware
|
|
70
|
+
* **fails closed by default** (logs and rejects with 403). Pass
|
|
71
|
+
* `failOpen: true` to admit the request instead — mirrors `@lunora/ratelimit`.
|
|
72
|
+
*
|
|
73
|
+
* **Cross-origin replay:** a token solved on one origin can be replayed against
|
|
74
|
+
* a different endpoint when a single secret/sitekey is shared across multiple
|
|
75
|
+
* domains. Pass `expectedHostname` (and optionally `expectedAction`, or a custom
|
|
76
|
+
* `validate(result)` predicate) to assert the siteverify response's `hostname`
|
|
77
|
+
* /`action` and reject mismatches with 403.
|
|
78
|
+
*/
|
|
79
79
|
declare const verifyTurnstileMiddleware: <Context>(options: VerifyTurnstileMiddlewareOptions<Context>) => Middleware<Context, Context>;
|
|
80
80
|
export { type VerifyTurnstileMiddlewareOptions, verifyTurnstileMiddleware };
|
|
@@ -1,45 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
const verifyTurnstileMiddleware = (options) => async ({ ctx, next }) => {
|
|
4
|
-
const token = options.token(ctx);
|
|
5
|
-
if (token === void 0 || token === "") {
|
|
6
|
-
throw Object.assign(new Error(options.message ?? "turnstile token missing"), {
|
|
7
|
-
code: "FORBIDDEN",
|
|
8
|
-
name: "LunoraError",
|
|
9
|
-
status: 403
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
let result;
|
|
13
|
-
try {
|
|
14
|
-
result = await verifyTurnstile({
|
|
15
|
-
expectedAction: options.expectedAction,
|
|
16
|
-
expectedHostname: options.expectedHostname,
|
|
17
|
-
fetch: options.fetch,
|
|
18
|
-
remoteip: options.remoteip?.(ctx),
|
|
19
|
-
secret: options.secret,
|
|
20
|
-
token
|
|
21
|
-
});
|
|
22
|
-
} catch (error) {
|
|
23
|
-
console.error(`@lunora/auth: verifyTurnstileMiddleware siteverify threw; ${options.failOpen ? "failing open" : "failing closed"}`, error);
|
|
24
|
-
if (options.failOpen) {
|
|
25
|
-
return next();
|
|
26
|
-
}
|
|
27
|
-
throw Object.assign(new Error(options.message ?? "turnstile verification unavailable"), {
|
|
28
|
-
cause: error,
|
|
29
|
-
code: "FORBIDDEN",
|
|
30
|
-
name: "LunoraError",
|
|
31
|
-
status: 403
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
if (!result.success || options.validate !== void 0 && !options.validate(result)) {
|
|
35
|
-
throw Object.assign(new Error(options.message ?? "turnstile verification failed"), {
|
|
36
|
-
code: "FORBIDDEN",
|
|
37
|
-
errorCodes: result.errorCodes,
|
|
38
|
-
name: "LunoraError",
|
|
39
|
-
status: 403
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return next();
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export { verifyTurnstileMiddleware };
|
|
1
|
+
import{LunoraError as i}from"@lunora/errors";import{verifyTurnstile as a}from"./turnstile.mjs";const d=e=>async({ctx:o,next:n})=>{const r=e.token(o);if(r===void 0||r==="")throw new i("FORBIDDEN",e.message??"turnstile token missing");let t;try{t=await a({expectedAction:e.expectedAction,expectedHostname:e.expectedHostname,fetch:e.fetch,remoteip:e.remoteip?.(o),secret:e.secret,token:r})}catch(s){if(console.error(`@lunora/auth: verifyTurnstileMiddleware siteverify threw; ${e.failOpen?"failing open":"failing closed"}`,s),e.failOpen)return n();throw new i("FORBIDDEN",e.message??"turnstile verification unavailable",{cause:s})}if(!t.success||e.validate!==void 0&&!e.validate(t))throw new i("FORBIDDEN",e.message??"turnstile verification failed",{data:t.errorCodes.length>0?{errorCodes:t.errorCodes}:void 0});return n()};export{d as verifyTurnstileMiddleware};
|
package/dist/turnstile.d.mts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cloudflare Turnstile server-side verification.
|
|
3
|
-
*
|
|
4
|
-
* Turnstile has **no Cloudflare binding** — verification is a single HTTPS POST
|
|
5
|
-
* to the public `siteverify` endpoint with your secret key. The secret lives in
|
|
6
|
-
* a plain env var / `.dev.vars` (conventionally `TURNSTILE_SECRET_KEY`), not in
|
|
7
|
-
* `wrangler.jsonc`. This module is therefore pure, transport-agnostic, and
|
|
8
|
-
* usable from any mutation/action — not just the auth flow.
|
|
9
|
-
* @see https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
|
|
10
|
-
*/
|
|
11
1
|
/** Cloudflare's public Turnstile `siteverify` endpoint. */
|
|
12
2
|
declare const TURNSTILE_VERIFY_ENDPOINT = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
|
|
13
3
|
/** Minimal `fetch` shape we depend on, so callers can inject a stub in tests. */
|
|
@@ -18,32 +8,32 @@ type FetchLike = (input: string, init?: {
|
|
|
18
8
|
}) => Promise<Response>;
|
|
19
9
|
interface VerifyTurnstileOptions {
|
|
20
10
|
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
* Assert the widget `action` the token was solved for. Cloudflare echoes the
|
|
12
|
+
* customer-supplied `action` back in the siteverify response; when this is
|
|
13
|
+
* set and the returned `action` does not match, the verdict is downgraded to
|
|
14
|
+
* `success: false` (with error code `action-mismatch`). Leave unset to skip
|
|
15
|
+
* the check.
|
|
16
|
+
*/
|
|
27
17
|
expectedAction?: string;
|
|
28
18
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
* Assert the `hostname` the challenge was solved on. Cloudflare returns the
|
|
20
|
+
* solving hostname in the siteverify response; when this is set and the
|
|
21
|
+
* returned `hostname` does not match, the verdict is downgraded to
|
|
22
|
+
* `success: false` (with error code `hostname-mismatch`). Set this when a
|
|
23
|
+
* single secret/sitekey is shared across multiple domains to stop a token
|
|
24
|
+
* harvested on one origin from being replayed against another. Leave unset
|
|
25
|
+
* to skip the check.
|
|
26
|
+
*/
|
|
37
27
|
expectedHostname?: string;
|
|
38
28
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
* Inject a `fetch` implementation. Defaults to `globalThis.fetch`. Primarily
|
|
30
|
+
* for unit tests — production callers can omit it.
|
|
31
|
+
*/
|
|
42
32
|
fetch?: FetchLike;
|
|
43
33
|
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
34
|
+
* The visitor's IP address, if known. Optional; Cloudflare uses it as an
|
|
35
|
+
* extra signal but verification works without it.
|
|
36
|
+
*/
|
|
47
37
|
remoteip?: string;
|
|
48
38
|
/** Your Turnstile secret key (the `TURNSTILE_SECRET_KEY` env var). */
|
|
49
39
|
secret: string;
|
|
@@ -51,13 +41,13 @@ interface VerifyTurnstileOptions {
|
|
|
51
41
|
token: string;
|
|
52
42
|
}
|
|
53
43
|
/**
|
|
54
|
-
* The normalized result of a Turnstile verification. Snake-cased fields from
|
|
55
|
-
* Cloudflare (`error-codes`, `challenge_ts`) are mapped to camelCase.
|
|
56
|
-
*
|
|
57
|
-
* A `success: false` verdict is a **bot/invalid-token** outcome, not an error —
|
|
58
|
-
* it is returned, never thrown. `verifyTurnstile` only throws on transport
|
|
59
|
-
* failure (network error, non-2xx response).
|
|
60
|
-
*/
|
|
44
|
+
* The normalized result of a Turnstile verification. Snake-cased fields from
|
|
45
|
+
* Cloudflare (`error-codes`, `challenge_ts`) are mapped to camelCase.
|
|
46
|
+
*
|
|
47
|
+
* A `success: false` verdict is a **bot/invalid-token** outcome, not an error —
|
|
48
|
+
* it is returned, never thrown. `verifyTurnstile` only throws on transport
|
|
49
|
+
* failure (network error, non-2xx response).
|
|
50
|
+
*/
|
|
61
51
|
interface TurnstileVerifyResult {
|
|
62
52
|
/** The customer-supplied `action` the widget was rendered with, if any. */
|
|
63
53
|
action?: string;
|
|
@@ -66,9 +56,9 @@ interface TurnstileVerifyResult {
|
|
|
66
56
|
/** ISO timestamp of the challenge, if Cloudflare returned one. */
|
|
67
57
|
challengeTs?: string;
|
|
68
58
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
59
|
+
* Cloudflare error codes for a failed verification (e.g.
|
|
60
|
+
* `"invalid-input-response"`, `"timeout-or-duplicate"`). Empty on success.
|
|
61
|
+
*/
|
|
72
62
|
errorCodes: string[];
|
|
73
63
|
/** Hostname the challenge was solved on, if Cloudflare returned one. */
|
|
74
64
|
hostname?: string;
|
|
@@ -76,23 +66,16 @@ interface TurnstileVerifyResult {
|
|
|
76
66
|
success: boolean;
|
|
77
67
|
}
|
|
78
68
|
/**
|
|
79
|
-
* Verify a Turnstile token against Cloudflare's `siteverify` endpoint.
|
|
80
|
-
*
|
|
81
|
-
* POSTs `application/x-www-form-urlencoded` (`secret`, `response`=token, and an
|
|
82
|
-
* optional `remoteip`) and returns the parsed verdict. A `success: false`
|
|
83
|
-
* outcome (bot / invalid / expired token) is **returned**, not thrown — callers
|
|
84
|
-
* decide how to react. The function throws a structural `LunoraError`-shaped
|
|
85
|
-
* error (`{ name: "LunoraError", code: "SERVICE_UNAVAILABLE", status: 503 }`)
|
|
86
|
-
* only when the siteverify call itself fails (network error or non-2xx), so a
|
|
87
|
-
* "siteverify is down" failure is distinguishable from a "this is a bot"
|
|
88
|
-
* verdict.
|
|
89
|
-
*/
|
|
90
|
-
declare const verifyTurnstile: ({
|
|
91
|
-
expectedAction,
|
|
92
|
-
expectedHostname,
|
|
93
|
-
fetch,
|
|
94
|
-
remoteip,
|
|
95
|
-
secret,
|
|
96
|
-
token
|
|
97
|
-
}: VerifyTurnstileOptions) => Promise<TurnstileVerifyResult>;
|
|
69
|
+
* Verify a Turnstile token against Cloudflare's `siteverify` endpoint.
|
|
70
|
+
*
|
|
71
|
+
* POSTs `application/x-www-form-urlencoded` (`secret`, `response`=token, and an
|
|
72
|
+
* optional `remoteip`) and returns the parsed verdict. A `success: false`
|
|
73
|
+
* outcome (bot / invalid / expired token) is **returned**, not thrown — callers
|
|
74
|
+
* decide how to react. The function throws a structural `LunoraError`-shaped
|
|
75
|
+
* error (`{ name: "LunoraError", code: "SERVICE_UNAVAILABLE", status: 503 }`)
|
|
76
|
+
* only when the siteverify call itself fails (network error or non-2xx), so a
|
|
77
|
+
* "siteverify is down" failure is distinguishable from a "this is a bot"
|
|
78
|
+
* verdict.
|
|
79
|
+
*/
|
|
80
|
+
declare const verifyTurnstile: ({ expectedAction, expectedHostname, fetch, remoteip, secret, token }: VerifyTurnstileOptions) => Promise<TurnstileVerifyResult>;
|
|
98
81
|
export { type FetchLike, TURNSTILE_VERIFY_ENDPOINT, type TurnstileVerifyResult, type VerifyTurnstileOptions, verifyTurnstile };
|
package/dist/turnstile.d.ts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cloudflare Turnstile server-side verification.
|
|
3
|
-
*
|
|
4
|
-
* Turnstile has **no Cloudflare binding** — verification is a single HTTPS POST
|
|
5
|
-
* to the public `siteverify` endpoint with your secret key. The secret lives in
|
|
6
|
-
* a plain env var / `.dev.vars` (conventionally `TURNSTILE_SECRET_KEY`), not in
|
|
7
|
-
* `wrangler.jsonc`. This module is therefore pure, transport-agnostic, and
|
|
8
|
-
* usable from any mutation/action — not just the auth flow.
|
|
9
|
-
* @see https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
|
|
10
|
-
*/
|
|
11
1
|
/** Cloudflare's public Turnstile `siteverify` endpoint. */
|
|
12
2
|
declare const TURNSTILE_VERIFY_ENDPOINT = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
|
|
13
3
|
/** Minimal `fetch` shape we depend on, so callers can inject a stub in tests. */
|
|
@@ -18,32 +8,32 @@ type FetchLike = (input: string, init?: {
|
|
|
18
8
|
}) => Promise<Response>;
|
|
19
9
|
interface VerifyTurnstileOptions {
|
|
20
10
|
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
* Assert the widget `action` the token was solved for. Cloudflare echoes the
|
|
12
|
+
* customer-supplied `action` back in the siteverify response; when this is
|
|
13
|
+
* set and the returned `action` does not match, the verdict is downgraded to
|
|
14
|
+
* `success: false` (with error code `action-mismatch`). Leave unset to skip
|
|
15
|
+
* the check.
|
|
16
|
+
*/
|
|
27
17
|
expectedAction?: string;
|
|
28
18
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
* Assert the `hostname` the challenge was solved on. Cloudflare returns the
|
|
20
|
+
* solving hostname in the siteverify response; when this is set and the
|
|
21
|
+
* returned `hostname` does not match, the verdict is downgraded to
|
|
22
|
+
* `success: false` (with error code `hostname-mismatch`). Set this when a
|
|
23
|
+
* single secret/sitekey is shared across multiple domains to stop a token
|
|
24
|
+
* harvested on one origin from being replayed against another. Leave unset
|
|
25
|
+
* to skip the check.
|
|
26
|
+
*/
|
|
37
27
|
expectedHostname?: string;
|
|
38
28
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
* Inject a `fetch` implementation. Defaults to `globalThis.fetch`. Primarily
|
|
30
|
+
* for unit tests — production callers can omit it.
|
|
31
|
+
*/
|
|
42
32
|
fetch?: FetchLike;
|
|
43
33
|
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
34
|
+
* The visitor's IP address, if known. Optional; Cloudflare uses it as an
|
|
35
|
+
* extra signal but verification works without it.
|
|
36
|
+
*/
|
|
47
37
|
remoteip?: string;
|
|
48
38
|
/** Your Turnstile secret key (the `TURNSTILE_SECRET_KEY` env var). */
|
|
49
39
|
secret: string;
|
|
@@ -51,13 +41,13 @@ interface VerifyTurnstileOptions {
|
|
|
51
41
|
token: string;
|
|
52
42
|
}
|
|
53
43
|
/**
|
|
54
|
-
* The normalized result of a Turnstile verification. Snake-cased fields from
|
|
55
|
-
* Cloudflare (`error-codes`, `challenge_ts`) are mapped to camelCase.
|
|
56
|
-
*
|
|
57
|
-
* A `success: false` verdict is a **bot/invalid-token** outcome, not an error —
|
|
58
|
-
* it is returned, never thrown. `verifyTurnstile` only throws on transport
|
|
59
|
-
* failure (network error, non-2xx response).
|
|
60
|
-
*/
|
|
44
|
+
* The normalized result of a Turnstile verification. Snake-cased fields from
|
|
45
|
+
* Cloudflare (`error-codes`, `challenge_ts`) are mapped to camelCase.
|
|
46
|
+
*
|
|
47
|
+
* A `success: false` verdict is a **bot/invalid-token** outcome, not an error —
|
|
48
|
+
* it is returned, never thrown. `verifyTurnstile` only throws on transport
|
|
49
|
+
* failure (network error, non-2xx response).
|
|
50
|
+
*/
|
|
61
51
|
interface TurnstileVerifyResult {
|
|
62
52
|
/** The customer-supplied `action` the widget was rendered with, if any. */
|
|
63
53
|
action?: string;
|
|
@@ -66,9 +56,9 @@ interface TurnstileVerifyResult {
|
|
|
66
56
|
/** ISO timestamp of the challenge, if Cloudflare returned one. */
|
|
67
57
|
challengeTs?: string;
|
|
68
58
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
59
|
+
* Cloudflare error codes for a failed verification (e.g.
|
|
60
|
+
* `"invalid-input-response"`, `"timeout-or-duplicate"`). Empty on success.
|
|
61
|
+
*/
|
|
72
62
|
errorCodes: string[];
|
|
73
63
|
/** Hostname the challenge was solved on, if Cloudflare returned one. */
|
|
74
64
|
hostname?: string;
|
|
@@ -76,23 +66,16 @@ interface TurnstileVerifyResult {
|
|
|
76
66
|
success: boolean;
|
|
77
67
|
}
|
|
78
68
|
/**
|
|
79
|
-
* Verify a Turnstile token against Cloudflare's `siteverify` endpoint.
|
|
80
|
-
*
|
|
81
|
-
* POSTs `application/x-www-form-urlencoded` (`secret`, `response`=token, and an
|
|
82
|
-
* optional `remoteip`) and returns the parsed verdict. A `success: false`
|
|
83
|
-
* outcome (bot / invalid / expired token) is **returned**, not thrown — callers
|
|
84
|
-
* decide how to react. The function throws a structural `LunoraError`-shaped
|
|
85
|
-
* error (`{ name: "LunoraError", code: "SERVICE_UNAVAILABLE", status: 503 }`)
|
|
86
|
-
* only when the siteverify call itself fails (network error or non-2xx), so a
|
|
87
|
-
* "siteverify is down" failure is distinguishable from a "this is a bot"
|
|
88
|
-
* verdict.
|
|
89
|
-
*/
|
|
90
|
-
declare const verifyTurnstile: ({
|
|
91
|
-
expectedAction,
|
|
92
|
-
expectedHostname,
|
|
93
|
-
fetch,
|
|
94
|
-
remoteip,
|
|
95
|
-
secret,
|
|
96
|
-
token
|
|
97
|
-
}: VerifyTurnstileOptions) => Promise<TurnstileVerifyResult>;
|
|
69
|
+
* Verify a Turnstile token against Cloudflare's `siteverify` endpoint.
|
|
70
|
+
*
|
|
71
|
+
* POSTs `application/x-www-form-urlencoded` (`secret`, `response`=token, and an
|
|
72
|
+
* optional `remoteip`) and returns the parsed verdict. A `success: false`
|
|
73
|
+
* outcome (bot / invalid / expired token) is **returned**, not thrown — callers
|
|
74
|
+
* decide how to react. The function throws a structural `LunoraError`-shaped
|
|
75
|
+
* error (`{ name: "LunoraError", code: "SERVICE_UNAVAILABLE", status: 503 }`)
|
|
76
|
+
* only when the siteverify call itself fails (network error or non-2xx), so a
|
|
77
|
+
* "siteverify is down" failure is distinguishable from a "this is a bot"
|
|
78
|
+
* verdict.
|
|
79
|
+
*/
|
|
80
|
+
declare const verifyTurnstile: ({ expectedAction, expectedHostname, fetch, remoteip, secret, token }: VerifyTurnstileOptions) => Promise<TurnstileVerifyResult>;
|
|
98
81
|
export { type FetchLike, TURNSTILE_VERIFY_ENDPOINT, type TurnstileVerifyResult, type VerifyTurnstileOptions, verifyTurnstile };
|