@authn-sh/sdk-node 0.4.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +117 -0
- package/dist/errors.cjs +45 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +46 -0
- package/dist/errors.d.ts +46 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.cjs +1529 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +728 -0
- package/dist/index.d.ts +728 -0
- package/dist/index.js +1477 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @authn-sh/sdk-node
|
|
2
|
+
|
|
3
|
+
Node.js / Edge-runtime backend SDK for [authn.sh](https://authn.sh).
|
|
4
|
+
|
|
5
|
+
Mirrors [`@authn-sh/sdk-php`](https://github.com/authn-sh/sdk-php) — BAPI resource managers, session-JWT verification, webhook signature verification. The frontend counterpart is [`@authn-sh/sdk-js`](https://github.com/authn-sh/javascript/tree/main/packages/sdk-js).
|
|
6
|
+
|
|
7
|
+
Runs anywhere `fetch` exists: Node 18+, Cloudflare Workers, Vercel Edge, Bun, Deno.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
npm install @authn-sh/sdk-node
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## BAPI client
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { Authn } from '@authn-sh/sdk-node';
|
|
19
|
+
|
|
20
|
+
const authn = new Authn({ secretKey: process.env.AUTHN_SECRET_KEY! });
|
|
21
|
+
|
|
22
|
+
// Users
|
|
23
|
+
const user = await authn.users.get('user_01HXYZ');
|
|
24
|
+
await authn.users.ban('user_01HXYZ');
|
|
25
|
+
const fresh = await authn.users.create({ first_name: 'Alice', email_addresses: ['alice@example.com'] });
|
|
26
|
+
|
|
27
|
+
// Sessions
|
|
28
|
+
const session = await authn.sessions.get('sess_01HXYZ');
|
|
29
|
+
const jwt = await authn.sessions.getToken('sess_01HXYZ', 'my-jwt-template');
|
|
30
|
+
|
|
31
|
+
// Organizations + nested managers
|
|
32
|
+
const org = await authn.organizations.create({ name: 'Acme', slug: 'acme' });
|
|
33
|
+
await authn.organizations.members(org.id).create({ userId: user.id, role: 'org:admin' });
|
|
34
|
+
await authn.organizations.invitations(org.id).create({ email_address: 'bob@acme.com', role: 'org:member' });
|
|
35
|
+
await authn.organizations.domains(org.id).create('acme.com', 'automatic_invitation');
|
|
36
|
+
|
|
37
|
+
// Social providers + phone numbers + external accounts + SMS templates
|
|
38
|
+
await authn.oauthProviders.list();
|
|
39
|
+
await authn.phoneNumbers.list({ userId: user.id } as any);
|
|
40
|
+
await authn.externalAccounts.list({ userId: user.id } as any);
|
|
41
|
+
await authn.smsTemplates.get('verification_code');
|
|
42
|
+
|
|
43
|
+
// Instance settings
|
|
44
|
+
const instance = await authn.instance.get();
|
|
45
|
+
await authn.instance.update({ multi_factor: { phone_code: { enabled: true } } });
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Errors from the API surface as `AuthnHttpError` (`status`, `code`, `requestId`, `errors[]`).
|
|
49
|
+
|
|
50
|
+
## Session-JWT verification
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { TokenVerifier } from '@authn-sh/sdk-node';
|
|
54
|
+
|
|
55
|
+
const verifier = new TokenVerifier({ publishableKey: process.env.AUTHN_PUBLISHABLE_KEY! });
|
|
56
|
+
|
|
57
|
+
// In your auth middleware:
|
|
58
|
+
const cookie = req.cookies['__session'];
|
|
59
|
+
const claims = await verifier.verify(cookie); // throws AuthnTokenInvalidError on bad token
|
|
60
|
+
|
|
61
|
+
console.log(claims.sub); // user_…
|
|
62
|
+
console.log(claims.organization?.role); // 'org:admin'
|
|
63
|
+
console.log(claims.hasPermission('org:billing:read'));
|
|
64
|
+
console.log(claims.hasVerifiedPhoneNumber());
|
|
65
|
+
console.log(claims.preferredSecondFactor()); // 'totp' | 'phone_code' | 'backup_code' | null
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
For "best-effort" auth that falls back to unauthenticated, use `tryVerify()` — returns `null` instead of throwing.
|
|
69
|
+
|
|
70
|
+
The verifier resolves the FAPI host from the `publishableKey`; pass `frontendApiUrl` explicitly when self-hosting on a custom domain. JWKS is fetched once and cached in memory (default 10 min TTL).
|
|
71
|
+
|
|
72
|
+
## Webhook signature verification
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import express from 'express';
|
|
76
|
+
import { WebhookSignatureVerifier } from '@authn-sh/sdk-node';
|
|
77
|
+
|
|
78
|
+
const app = express();
|
|
79
|
+
const verifier = new WebhookSignatureVerifier({
|
|
80
|
+
signingSecret: process.env.AUTHN_WEBHOOK_SECRET!,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
app.post('/webhooks/authn', express.raw({ type: 'application/json' }), (req, res) => {
|
|
84
|
+
try {
|
|
85
|
+
const event = verifier.verify(req.body.toString('utf8'), req.headers);
|
|
86
|
+
switch (event.type) {
|
|
87
|
+
case 'user.created': /* … */; break;
|
|
88
|
+
case 'phoneNumber.verified': /* … */; break;
|
|
89
|
+
}
|
|
90
|
+
res.status(204).end();
|
|
91
|
+
} catch {
|
|
92
|
+
res.status(400).end();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
To rotate the signing secret without downtime, pass an array — the verifier accepts a request if any provided signature matches any secret:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
new WebhookSignatureVerifier({ signingSecret: [oldSecret, newSecret] });
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Runtime support
|
|
104
|
+
|
|
105
|
+
| Runtime | Status |
|
|
106
|
+
| ----------------- | -------------------------------------------- |
|
|
107
|
+
| Node.js 18+ | ✓ first-class |
|
|
108
|
+
| Cloudflare Workers | ✓ (uses `globalThis.fetch` + `node:crypto`) |
|
|
109
|
+
| Vercel Edge | ✓ |
|
|
110
|
+
| Bun | ✓ |
|
|
111
|
+
| Deno | ✓ via `npm:` specifier |
|
|
112
|
+
|
|
113
|
+
The webhook verifier imports `node:crypto`. On edge runtimes that polyfill it (Workers, Vercel Edge), no action is needed.
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
AGPL-3.0-only — see [LICENSE](./LICENSE). For commercially licensed deployments, contact [authn.sh](https://authn.sh).
|
package/dist/errors.cjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/errors/index.ts
|
|
4
|
+
var AuthnHttpError = class extends Error {
|
|
5
|
+
constructor(status, errors, requestId, message) {
|
|
6
|
+
super(message ?? (errors[0]?.longMessage || errors[0]?.message) ?? `authn.sh API returned HTTP ${status}`);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.errors = errors;
|
|
9
|
+
this.requestId = requestId;
|
|
10
|
+
}
|
|
11
|
+
status;
|
|
12
|
+
errors;
|
|
13
|
+
requestId;
|
|
14
|
+
name = "AuthnHttpError";
|
|
15
|
+
/** The primary error code returned by the API (when present). */
|
|
16
|
+
get code() {
|
|
17
|
+
return this.errors[0]?.code ?? null;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var AuthnConfigError = class extends Error {
|
|
21
|
+
name = "AuthnConfigError";
|
|
22
|
+
};
|
|
23
|
+
var AuthnTokenInvalidError = class extends Error {
|
|
24
|
+
constructor(reason, message) {
|
|
25
|
+
super(message ?? `Token invalid: ${reason}`);
|
|
26
|
+
this.reason = reason;
|
|
27
|
+
}
|
|
28
|
+
reason;
|
|
29
|
+
name = "AuthnTokenInvalidError";
|
|
30
|
+
};
|
|
31
|
+
var AuthnWebhookSignatureInvalidError = class extends Error {
|
|
32
|
+
constructor(reason, message) {
|
|
33
|
+
super(message ?? `Webhook signature invalid: ${reason}`);
|
|
34
|
+
this.reason = reason;
|
|
35
|
+
}
|
|
36
|
+
reason;
|
|
37
|
+
name = "AuthnWebhookSignatureInvalidError";
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
exports.AuthnConfigError = AuthnConfigError;
|
|
41
|
+
exports.AuthnHttpError = AuthnHttpError;
|
|
42
|
+
exports.AuthnTokenInvalidError = AuthnTokenInvalidError;
|
|
43
|
+
exports.AuthnWebhookSignatureInvalidError = AuthnWebhookSignatureInvalidError;
|
|
44
|
+
//# sourceMappingURL=errors.cjs.map
|
|
45
|
+
//# sourceMappingURL=errors.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/index.ts"],"names":[],"mappings":";;;AAaO,IAAM,cAAA,GAAN,cAA6B,KAAA,CAAM;AAAA,EAGxC,WAAA,CACkB,MAAA,EACA,MAAA,EACA,SAAA,EAChB,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,KAAY,MAAA,CAAO,CAAC,CAAA,EAAG,WAAA,IAAe,MAAA,CAAO,CAAC,CAAA,EAAG,OAAA,CAAA,IAAY,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAE,CAAA;AALzF,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EAIlB;AAAA,EANkB,MAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EALO,IAAA,GAAM,gBAAA;AAAA;AAAA,EAY/B,IAAI,IAAA,GAAsB;AACxB,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAA;AAAA,EACjC;AACF;AAKO,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAA,EACjB,IAAA,GAAM,kBAAA;AACjC;AAMO,IAAM,sBAAA,GAAN,cAAqC,KAAA,CAAM;AAAA,EAGhD,WAAA,CACkB,QAShB,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,IAAW,CAAA,eAAA,EAAkB,MAAM,CAAA,CAAE,CAAA;AAX3B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAYlB;AAAA,EAZkB,MAAA;AAAA,EAHO,IAAA,GAAM,wBAAA;AAgBjC;AAKO,IAAM,iCAAA,GAAN,cAAgD,KAAA,CAAM;AAAA,EAG3D,WAAA,CACkB,QAMhB,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,IAAW,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAE,CAAA;AARvC,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EASlB;AAAA,EATkB,MAAA;AAAA,EAHO,IAAA,GAAM,mCAAA;AAajC","file":"errors.cjs","sourcesContent":["/**\n * Error shape emitted by the authn.sh API.\n */\nexport interface AuthnApiError {\n code: string;\n message: string;\n longMessage?: string;\n meta?: Record<string, unknown>;\n}\n\n/**\n * Thrown when a request to the BAPI returns a non-2xx response.\n */\nexport class AuthnHttpError extends Error {\n public override readonly name ='AuthnHttpError';\n\n constructor(\n public readonly status: number,\n public readonly errors: AuthnApiError[],\n public readonly requestId: string | null,\n message?: string,\n ) {\n super(message ?? (errors[0]?.longMessage || errors[0]?.message) ?? `authn.sh API returned HTTP ${status}`);\n }\n\n /** The primary error code returned by the API (when present). */\n get code(): string | null {\n return this.errors[0]?.code ?? null;\n }\n}\n\n/**\n * Thrown when the SDK is misconfigured (missing secret key, malformed URL, etc.).\n */\nexport class AuthnConfigError extends Error {\n public override readonly name ='AuthnConfigError';\n}\n\n/**\n * Thrown when a JWT can't be verified — wrong signature, expired, malformed,\n * issuer mismatch, etc. The `reason` discriminates between the failure modes.\n */\nexport class AuthnTokenInvalidError extends Error {\n public override readonly name ='AuthnTokenInvalidError';\n\n constructor(\n public readonly reason:\n | 'malformed'\n | 'signature_invalid'\n | 'expired'\n | 'not_yet_valid'\n | 'issuer_mismatch'\n | 'audience_mismatch'\n | 'key_not_found'\n | 'jwks_fetch_failed',\n message?: string,\n ) {\n super(message ?? `Token invalid: ${reason}`);\n }\n}\n\n/**\n * Thrown when a webhook signature can't be verified.\n */\nexport class AuthnWebhookSignatureInvalidError extends Error {\n public override readonly name ='AuthnWebhookSignatureInvalidError';\n\n constructor(\n public readonly reason:\n | 'missing_signature_header'\n | 'malformed_signature_header'\n | 'no_matching_signature'\n | 'timestamp_too_old'\n | 'timestamp_missing',\n message?: string,\n ) {\n super(message ?? `Webhook signature invalid: ${reason}`);\n }\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error shape emitted by the authn.sh API.
|
|
3
|
+
*/
|
|
4
|
+
interface AuthnApiError {
|
|
5
|
+
code: string;
|
|
6
|
+
message: string;
|
|
7
|
+
longMessage?: string;
|
|
8
|
+
meta?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Thrown when a request to the BAPI returns a non-2xx response.
|
|
12
|
+
*/
|
|
13
|
+
declare class AuthnHttpError extends Error {
|
|
14
|
+
readonly status: number;
|
|
15
|
+
readonly errors: AuthnApiError[];
|
|
16
|
+
readonly requestId: string | null;
|
|
17
|
+
readonly name = "AuthnHttpError";
|
|
18
|
+
constructor(status: number, errors: AuthnApiError[], requestId: string | null, message?: string);
|
|
19
|
+
/** The primary error code returned by the API (when present). */
|
|
20
|
+
get code(): string | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Thrown when the SDK is misconfigured (missing secret key, malformed URL, etc.).
|
|
24
|
+
*/
|
|
25
|
+
declare class AuthnConfigError extends Error {
|
|
26
|
+
readonly name = "AuthnConfigError";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Thrown when a JWT can't be verified — wrong signature, expired, malformed,
|
|
30
|
+
* issuer mismatch, etc. The `reason` discriminates between the failure modes.
|
|
31
|
+
*/
|
|
32
|
+
declare class AuthnTokenInvalidError extends Error {
|
|
33
|
+
readonly reason: 'malformed' | 'signature_invalid' | 'expired' | 'not_yet_valid' | 'issuer_mismatch' | 'audience_mismatch' | 'key_not_found' | 'jwks_fetch_failed';
|
|
34
|
+
readonly name = "AuthnTokenInvalidError";
|
|
35
|
+
constructor(reason: 'malformed' | 'signature_invalid' | 'expired' | 'not_yet_valid' | 'issuer_mismatch' | 'audience_mismatch' | 'key_not_found' | 'jwks_fetch_failed', message?: string);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Thrown when a webhook signature can't be verified.
|
|
39
|
+
*/
|
|
40
|
+
declare class AuthnWebhookSignatureInvalidError extends Error {
|
|
41
|
+
readonly reason: 'missing_signature_header' | 'malformed_signature_header' | 'no_matching_signature' | 'timestamp_too_old' | 'timestamp_missing';
|
|
42
|
+
readonly name = "AuthnWebhookSignatureInvalidError";
|
|
43
|
+
constructor(reason: 'missing_signature_header' | 'malformed_signature_header' | 'no_matching_signature' | 'timestamp_too_old' | 'timestamp_missing', message?: string);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { type AuthnApiError, AuthnConfigError, AuthnHttpError, AuthnTokenInvalidError, AuthnWebhookSignatureInvalidError };
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error shape emitted by the authn.sh API.
|
|
3
|
+
*/
|
|
4
|
+
interface AuthnApiError {
|
|
5
|
+
code: string;
|
|
6
|
+
message: string;
|
|
7
|
+
longMessage?: string;
|
|
8
|
+
meta?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Thrown when a request to the BAPI returns a non-2xx response.
|
|
12
|
+
*/
|
|
13
|
+
declare class AuthnHttpError extends Error {
|
|
14
|
+
readonly status: number;
|
|
15
|
+
readonly errors: AuthnApiError[];
|
|
16
|
+
readonly requestId: string | null;
|
|
17
|
+
readonly name = "AuthnHttpError";
|
|
18
|
+
constructor(status: number, errors: AuthnApiError[], requestId: string | null, message?: string);
|
|
19
|
+
/** The primary error code returned by the API (when present). */
|
|
20
|
+
get code(): string | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Thrown when the SDK is misconfigured (missing secret key, malformed URL, etc.).
|
|
24
|
+
*/
|
|
25
|
+
declare class AuthnConfigError extends Error {
|
|
26
|
+
readonly name = "AuthnConfigError";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Thrown when a JWT can't be verified — wrong signature, expired, malformed,
|
|
30
|
+
* issuer mismatch, etc. The `reason` discriminates between the failure modes.
|
|
31
|
+
*/
|
|
32
|
+
declare class AuthnTokenInvalidError extends Error {
|
|
33
|
+
readonly reason: 'malformed' | 'signature_invalid' | 'expired' | 'not_yet_valid' | 'issuer_mismatch' | 'audience_mismatch' | 'key_not_found' | 'jwks_fetch_failed';
|
|
34
|
+
readonly name = "AuthnTokenInvalidError";
|
|
35
|
+
constructor(reason: 'malformed' | 'signature_invalid' | 'expired' | 'not_yet_valid' | 'issuer_mismatch' | 'audience_mismatch' | 'key_not_found' | 'jwks_fetch_failed', message?: string);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Thrown when a webhook signature can't be verified.
|
|
39
|
+
*/
|
|
40
|
+
declare class AuthnWebhookSignatureInvalidError extends Error {
|
|
41
|
+
readonly reason: 'missing_signature_header' | 'malformed_signature_header' | 'no_matching_signature' | 'timestamp_too_old' | 'timestamp_missing';
|
|
42
|
+
readonly name = "AuthnWebhookSignatureInvalidError";
|
|
43
|
+
constructor(reason: 'missing_signature_header' | 'malformed_signature_header' | 'no_matching_signature' | 'timestamp_too_old' | 'timestamp_missing', message?: string);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { type AuthnApiError, AuthnConfigError, AuthnHttpError, AuthnTokenInvalidError, AuthnWebhookSignatureInvalidError };
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/errors/index.ts
|
|
2
|
+
var AuthnHttpError = class extends Error {
|
|
3
|
+
constructor(status, errors, requestId, message) {
|
|
4
|
+
super(message ?? (errors[0]?.longMessage || errors[0]?.message) ?? `authn.sh API returned HTTP ${status}`);
|
|
5
|
+
this.status = status;
|
|
6
|
+
this.errors = errors;
|
|
7
|
+
this.requestId = requestId;
|
|
8
|
+
}
|
|
9
|
+
status;
|
|
10
|
+
errors;
|
|
11
|
+
requestId;
|
|
12
|
+
name = "AuthnHttpError";
|
|
13
|
+
/** The primary error code returned by the API (when present). */
|
|
14
|
+
get code() {
|
|
15
|
+
return this.errors[0]?.code ?? null;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var AuthnConfigError = class extends Error {
|
|
19
|
+
name = "AuthnConfigError";
|
|
20
|
+
};
|
|
21
|
+
var AuthnTokenInvalidError = class extends Error {
|
|
22
|
+
constructor(reason, message) {
|
|
23
|
+
super(message ?? `Token invalid: ${reason}`);
|
|
24
|
+
this.reason = reason;
|
|
25
|
+
}
|
|
26
|
+
reason;
|
|
27
|
+
name = "AuthnTokenInvalidError";
|
|
28
|
+
};
|
|
29
|
+
var AuthnWebhookSignatureInvalidError = class extends Error {
|
|
30
|
+
constructor(reason, message) {
|
|
31
|
+
super(message ?? `Webhook signature invalid: ${reason}`);
|
|
32
|
+
this.reason = reason;
|
|
33
|
+
}
|
|
34
|
+
reason;
|
|
35
|
+
name = "AuthnWebhookSignatureInvalidError";
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { AuthnConfigError, AuthnHttpError, AuthnTokenInvalidError, AuthnWebhookSignatureInvalidError };
|
|
39
|
+
//# sourceMappingURL=errors.js.map
|
|
40
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/index.ts"],"names":[],"mappings":";AAaO,IAAM,cAAA,GAAN,cAA6B,KAAA,CAAM;AAAA,EAGxC,WAAA,CACkB,MAAA,EACA,MAAA,EACA,SAAA,EAChB,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,KAAY,MAAA,CAAO,CAAC,CAAA,EAAG,WAAA,IAAe,MAAA,CAAO,CAAC,CAAA,EAAG,OAAA,CAAA,IAAY,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAE,CAAA;AALzF,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EAIlB;AAAA,EANkB,MAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EALO,IAAA,GAAM,gBAAA;AAAA;AAAA,EAY/B,IAAI,IAAA,GAAsB;AACxB,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAA;AAAA,EACjC;AACF;AAKO,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAA,EACjB,IAAA,GAAM,kBAAA;AACjC;AAMO,IAAM,sBAAA,GAAN,cAAqC,KAAA,CAAM;AAAA,EAGhD,WAAA,CACkB,QAShB,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,IAAW,CAAA,eAAA,EAAkB,MAAM,CAAA,CAAE,CAAA;AAX3B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAYlB;AAAA,EAZkB,MAAA;AAAA,EAHO,IAAA,GAAM,wBAAA;AAgBjC;AAKO,IAAM,iCAAA,GAAN,cAAgD,KAAA,CAAM;AAAA,EAG3D,WAAA,CACkB,QAMhB,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,IAAW,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAE,CAAA;AARvC,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EASlB;AAAA,EATkB,MAAA;AAAA,EAHO,IAAA,GAAM,mCAAA;AAajC","file":"errors.js","sourcesContent":["/**\n * Error shape emitted by the authn.sh API.\n */\nexport interface AuthnApiError {\n code: string;\n message: string;\n longMessage?: string;\n meta?: Record<string, unknown>;\n}\n\n/**\n * Thrown when a request to the BAPI returns a non-2xx response.\n */\nexport class AuthnHttpError extends Error {\n public override readonly name ='AuthnHttpError';\n\n constructor(\n public readonly status: number,\n public readonly errors: AuthnApiError[],\n public readonly requestId: string | null,\n message?: string,\n ) {\n super(message ?? (errors[0]?.longMessage || errors[0]?.message) ?? `authn.sh API returned HTTP ${status}`);\n }\n\n /** The primary error code returned by the API (when present). */\n get code(): string | null {\n return this.errors[0]?.code ?? null;\n }\n}\n\n/**\n * Thrown when the SDK is misconfigured (missing secret key, malformed URL, etc.).\n */\nexport class AuthnConfigError extends Error {\n public override readonly name ='AuthnConfigError';\n}\n\n/**\n * Thrown when a JWT can't be verified — wrong signature, expired, malformed,\n * issuer mismatch, etc. The `reason` discriminates between the failure modes.\n */\nexport class AuthnTokenInvalidError extends Error {\n public override readonly name ='AuthnTokenInvalidError';\n\n constructor(\n public readonly reason:\n | 'malformed'\n | 'signature_invalid'\n | 'expired'\n | 'not_yet_valid'\n | 'issuer_mismatch'\n | 'audience_mismatch'\n | 'key_not_found'\n | 'jwks_fetch_failed',\n message?: string,\n ) {\n super(message ?? `Token invalid: ${reason}`);\n }\n}\n\n/**\n * Thrown when a webhook signature can't be verified.\n */\nexport class AuthnWebhookSignatureInvalidError extends Error {\n public override readonly name ='AuthnWebhookSignatureInvalidError';\n\n constructor(\n public readonly reason:\n | 'missing_signature_header'\n | 'malformed_signature_header'\n | 'no_matching_signature'\n | 'timestamp_too_old'\n | 'timestamp_missing',\n message?: string,\n ) {\n super(message ?? `Webhook signature invalid: ${reason}`);\n }\n}\n"]}
|