@authyon/auth 0.2.0-beta.12 → 0.2.0-beta.14
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/README.md +21 -0
- package/dist/{ability-B1TiHFWa.d.cts → ability-DbnbsQEX.d.cts} +109 -1
- package/dist/{ability-B1TiHFWa.d.ts → ability-DbnbsQEX.d.ts} +109 -1
- package/dist/index.cjs +83 -24
- package/dist/index.d.cts +40 -22
- package/dist/index.d.ts +40 -22
- package/dist/index.js +77 -18
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -273,6 +273,27 @@ Métodos de sessão/auth ficam soltos no client; os que giram em torno de um rec
|
|
|
273
273
|
| `sso.startUrl(provider, params)` | monta a URL de `GET /auth/sso/{provider}/start` (não faz a chamada — navegue até ela) |
|
|
274
274
|
| `sso.exchange(code)` | `POST /auth/sso/exchange` |
|
|
275
275
|
|
|
276
|
+
### `authyon.financialAuthorizations` (confirmação de transações)
|
|
277
|
+
|
|
278
|
+
O cliente aprova uma transação criada pelo seu backend com o código do app autenticador
|
|
279
|
+
ou a passkey. Guia completo: [`docs/financialStepUp.md`](../../docs/financialStepUp.md).
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
const pending = await authyon.financialAuthorizations.get(authorizationId);
|
|
283
|
+
// mostre pending.amount, pending.currency e pending.beneficiary ao cliente
|
|
284
|
+
await authyon.financialAuthorizations.confirm(authorizationId, {
|
|
285
|
+
method: "authenticator",
|
|
286
|
+
code: "123456",
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
| Método | Endpoint |
|
|
291
|
+
| --------------------------------------------- | ------------------------------------------------- |
|
|
292
|
+
| `financialAuthorizations.get(id)` | `GET /auth/authorizations/{id}` |
|
|
293
|
+
| `financialAuthorizations.webauthnOptions(id)` | `POST /auth/authorizations/{id}/webauthn/options` |
|
|
294
|
+
| `financialAuthorizations.confirm(id, input?)` | `POST /auth/authorizations/{id}/confirm` |
|
|
295
|
+
| `financialAuthorizations.reject(id)` | `POST /auth/authorizations/{id}/reject` |
|
|
296
|
+
|
|
276
297
|
## Invalidação de token
|
|
277
298
|
|
|
278
299
|
- **Sessão atual**: `logout()` revoga o refresh token atual; `logout({ everywhere: true })` revoga todos os refresh tokens do usuário.
|
|
@@ -1,3 +1,74 @@
|
|
|
1
|
+
/** Lifecycle of a transaction-bound financial authorization. */
|
|
2
|
+
type FinancialAuthorizationStatus = "pending" | "approved" | "denied" | "consumed" | "expired";
|
|
3
|
+
/**
|
|
4
|
+
* The transaction the customer approves. The API hashes a canonical form of
|
|
5
|
+
* these fields; `consume()` must resend exactly the same values (amount is
|
|
6
|
+
* normalized to four decimal places, metadata keys are sorted).
|
|
7
|
+
*/
|
|
8
|
+
interface FinancialTransaction {
|
|
9
|
+
/** Business action, e.g. `"pix.transfer"`. Max 100 characters. */
|
|
10
|
+
action: string;
|
|
11
|
+
/** Positive amount, up to 15 integer digits and 4 decimal places. */
|
|
12
|
+
amount: number;
|
|
13
|
+
/** ISO 4217 currency code, e.g. `"BRL"`. */
|
|
14
|
+
currency: string;
|
|
15
|
+
/** Human-readable beneficiary shown to the customer. Max 256 characters. */
|
|
16
|
+
beneficiary: string;
|
|
17
|
+
/** Optional JSON object bound into the hash (max 16 KiB). */
|
|
18
|
+
metadata?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/** Evidence of how the customer proved their identity when approving. */
|
|
21
|
+
interface FinancialAssurance {
|
|
22
|
+
/** `urn:authyon:loa:3` (passkey) or `urn:authyon:loa:2` (authenticator code). */
|
|
23
|
+
acr: string;
|
|
24
|
+
/** Authentication methods, e.g. `["pwd", "otp"]` or `["pwd", "webauthn"]`. */
|
|
25
|
+
amr: string[];
|
|
26
|
+
/** When the second factor was verified (ISO 8601). */
|
|
27
|
+
authTime: string;
|
|
28
|
+
}
|
|
29
|
+
interface FinancialAuthorization {
|
|
30
|
+
id: string;
|
|
31
|
+
status: FinancialAuthorizationStatus;
|
|
32
|
+
subjectId: string;
|
|
33
|
+
tenantId?: string | null;
|
|
34
|
+
action: string;
|
|
35
|
+
amount: number;
|
|
36
|
+
currency: string;
|
|
37
|
+
beneficiary: string;
|
|
38
|
+
/** SHA-256 (hex) of the canonical transaction. */
|
|
39
|
+
transactionHash: string;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
expiresAt: string;
|
|
42
|
+
decidedAt?: string | null;
|
|
43
|
+
consumedAt?: string | null;
|
|
44
|
+
/** Full canonical transaction — returned only to the customer (subject) view. */
|
|
45
|
+
transaction?: FinancialTransaction | null;
|
|
46
|
+
/** Present once approved. */
|
|
47
|
+
assurance?: FinancialAssurance | null;
|
|
48
|
+
}
|
|
49
|
+
/** Inline second factor sent with `confirm()`. */
|
|
50
|
+
type ConfirmFinancialAuthorizationInput = {
|
|
51
|
+
method: "authenticator";
|
|
52
|
+
/** Six-digit code from the customer's authenticator app. */
|
|
53
|
+
code: string;
|
|
54
|
+
} | {
|
|
55
|
+
method: "webauthn";
|
|
56
|
+
/** Assertion for the options returned by `webauthnOptions()`. */
|
|
57
|
+
webAuthn: {
|
|
58
|
+
ceremonyToken: string;
|
|
59
|
+
/** JSON-serialized `PublicKeyCredential` from `navigator.credentials.get()`. */
|
|
60
|
+
assertionJson: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/** Passkey assertion options for approving one authorization. */
|
|
64
|
+
interface FinancialWebAuthnOptions {
|
|
65
|
+
ceremonyToken: string;
|
|
66
|
+
/** JSON `PublicKeyCredentialRequestOptions` to pass to `navigator.credentials.get()`. */
|
|
67
|
+
optionsJson: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type QueryParams = object;
|
|
71
|
+
|
|
1
72
|
interface HttpAdapterRequest {
|
|
2
73
|
url: string;
|
|
3
74
|
method: string;
|
|
@@ -55,6 +126,36 @@ declare class LoggingHttpAdapter implements HttpAdapter {
|
|
|
55
126
|
private log;
|
|
56
127
|
}
|
|
57
128
|
|
|
129
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
130
|
+
interface JsonRequestOptions {
|
|
131
|
+
method?: HttpMethod;
|
|
132
|
+
body?: unknown;
|
|
133
|
+
query?: QueryParams;
|
|
134
|
+
headers?: Record<string, string>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Sends a request already authenticated as the customer (end-user bearer). */
|
|
138
|
+
type SubjectRequest = <T>(path: string, options?: JsonRequestOptions) => Promise<T>;
|
|
139
|
+
/** Customer-side operations on a financial authorization (`/auth/authorizations`). */
|
|
140
|
+
declare function subjectFinancialAuthorizations(request: SubjectRequest): {
|
|
141
|
+
/** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
|
|
142
|
+
get: (id: string) => Promise<FinancialAuthorization>;
|
|
143
|
+
/** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
|
|
144
|
+
webauthnOptions: (id: string) => Promise<FinancialWebAuthnOptions>;
|
|
145
|
+
/**
|
|
146
|
+
* POST /auth/authorizations/{id}/confirm — approves the transaction.
|
|
147
|
+
*
|
|
148
|
+
* Pass the authenticator code or passkey assertion to verify the second
|
|
149
|
+
* factor inline (recommended). Without `input`, the session itself must
|
|
150
|
+
* have used a passkey or authenticator code within the last 5 minutes,
|
|
151
|
+
* otherwise the API answers `step_up_required`.
|
|
152
|
+
*/
|
|
153
|
+
confirm: (id: string, input?: ConfirmFinancialAuthorizationInput) => Promise<FinancialAuthorization>;
|
|
154
|
+
/** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
|
|
155
|
+
reject: (id: string) => Promise<FinancialAuthorization>;
|
|
156
|
+
};
|
|
157
|
+
type SubjectFinancialAuthorizations = ReturnType<typeof subjectFinancialAuthorizations>;
|
|
158
|
+
|
|
58
159
|
interface PaginationOptions {
|
|
59
160
|
skip?: number;
|
|
60
161
|
take?: number;
|
|
@@ -518,6 +619,13 @@ declare class AuthyonClient {
|
|
|
518
619
|
assertionStart: (challengeToken: string) => Promise<WebAuthnCeremonyStart>;
|
|
519
620
|
};
|
|
520
621
|
};
|
|
622
|
+
/**
|
|
623
|
+
* Transaction-bound approvals created by your backend
|
|
624
|
+
* (`@authyon/server` → `environment.financialAuthorizations.create`).
|
|
625
|
+
* Show the transaction with `get()`, then `confirm()` with the customer's
|
|
626
|
+
* authenticator code or passkey, or `reject()`.
|
|
627
|
+
*/
|
|
628
|
+
readonly financialAuthorizations: SubjectFinancialAuthorizations;
|
|
521
629
|
/**
|
|
522
630
|
* POST /auth/introspect — lightweight token introspection (RFC 7662).
|
|
523
631
|
*
|
|
@@ -642,4 +750,4 @@ declare function hasPermissionGroup(source: AuthyonPermissionSource | readonly s
|
|
|
642
750
|
/** Converts Authyon's `subject:action` permission strings to authorization rules. */
|
|
643
751
|
declare function createAuthyonRules(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AbilityRule[];
|
|
644
752
|
|
|
645
|
-
export {
|
|
753
|
+
export { type User as $, AuthyonClient as A, type InviteMemberInput as B, type ConfirmFinancialAuthorizationInput as C, type LoginInput as D, type LoginResult as E, FetchHttpAdapter as F, type OrganizationMember as G, type HttpAdapter as H, type IntrospectResult as I, type PaginationOptions as J, type PermissionGroup as K, LoggingHttpAdapter as L, type Role as M, type SessionControllerOptions as N, type Organization as O, type Paged as P, type SessionInfo as Q, type RegisterInput as R, type Session as S, type TokenStorage as T, type SessionSnapshot as U, type SessionSnapshotListener as V, type SessionStatus as W, type SsoProvider as X, type TwoFactorChallenge as Y, type TwoFactorMethod as Z, type TwoFactorStatus as _, type HttpLoggerOptions as a, type ValidateResult as a0, type VerifyTwoFactorInput as a1, type WebAuthnAssertion as a2, type WebAuthnCeremonyStart as a3, type WebAuthnCredential as a4, createAuthyonAbility as a5, createAuthyonRules as a6, createClient as a7, hasPermission as a8, hasPermissionGroup as a9, type AbilityConditions as b, type AbilityEvent as c, type AbilityListener as d, type AbilityRule as e, type AbilitySubject as f, type Activity as g, type AuthEvent as h, type AuthState as i, type AuthStateListener as j, type AuthenticatorSetup as k, AuthyonAbility as l, AuthyonAbilityBuilder as m, type AuthyonAbilityOptions as n, type AuthyonClientOptions as o, type AuthyonPermissionSource as p, AuthyonSessionController as q, type CreateOrganizationInput as r, type FinancialAssurance as s, type FinancialAuthorization as t, type FinancialAuthorizationStatus as u, type FinancialTransaction as v, type FinancialWebAuthnOptions as w, type HttpAdapterRequest as x, type HttpLogEvent as y, type HttpLogger as z };
|
|
@@ -1,3 +1,74 @@
|
|
|
1
|
+
/** Lifecycle of a transaction-bound financial authorization. */
|
|
2
|
+
type FinancialAuthorizationStatus = "pending" | "approved" | "denied" | "consumed" | "expired";
|
|
3
|
+
/**
|
|
4
|
+
* The transaction the customer approves. The API hashes a canonical form of
|
|
5
|
+
* these fields; `consume()` must resend exactly the same values (amount is
|
|
6
|
+
* normalized to four decimal places, metadata keys are sorted).
|
|
7
|
+
*/
|
|
8
|
+
interface FinancialTransaction {
|
|
9
|
+
/** Business action, e.g. `"pix.transfer"`. Max 100 characters. */
|
|
10
|
+
action: string;
|
|
11
|
+
/** Positive amount, up to 15 integer digits and 4 decimal places. */
|
|
12
|
+
amount: number;
|
|
13
|
+
/** ISO 4217 currency code, e.g. `"BRL"`. */
|
|
14
|
+
currency: string;
|
|
15
|
+
/** Human-readable beneficiary shown to the customer. Max 256 characters. */
|
|
16
|
+
beneficiary: string;
|
|
17
|
+
/** Optional JSON object bound into the hash (max 16 KiB). */
|
|
18
|
+
metadata?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/** Evidence of how the customer proved their identity when approving. */
|
|
21
|
+
interface FinancialAssurance {
|
|
22
|
+
/** `urn:authyon:loa:3` (passkey) or `urn:authyon:loa:2` (authenticator code). */
|
|
23
|
+
acr: string;
|
|
24
|
+
/** Authentication methods, e.g. `["pwd", "otp"]` or `["pwd", "webauthn"]`. */
|
|
25
|
+
amr: string[];
|
|
26
|
+
/** When the second factor was verified (ISO 8601). */
|
|
27
|
+
authTime: string;
|
|
28
|
+
}
|
|
29
|
+
interface FinancialAuthorization {
|
|
30
|
+
id: string;
|
|
31
|
+
status: FinancialAuthorizationStatus;
|
|
32
|
+
subjectId: string;
|
|
33
|
+
tenantId?: string | null;
|
|
34
|
+
action: string;
|
|
35
|
+
amount: number;
|
|
36
|
+
currency: string;
|
|
37
|
+
beneficiary: string;
|
|
38
|
+
/** SHA-256 (hex) of the canonical transaction. */
|
|
39
|
+
transactionHash: string;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
expiresAt: string;
|
|
42
|
+
decidedAt?: string | null;
|
|
43
|
+
consumedAt?: string | null;
|
|
44
|
+
/** Full canonical transaction — returned only to the customer (subject) view. */
|
|
45
|
+
transaction?: FinancialTransaction | null;
|
|
46
|
+
/** Present once approved. */
|
|
47
|
+
assurance?: FinancialAssurance | null;
|
|
48
|
+
}
|
|
49
|
+
/** Inline second factor sent with `confirm()`. */
|
|
50
|
+
type ConfirmFinancialAuthorizationInput = {
|
|
51
|
+
method: "authenticator";
|
|
52
|
+
/** Six-digit code from the customer's authenticator app. */
|
|
53
|
+
code: string;
|
|
54
|
+
} | {
|
|
55
|
+
method: "webauthn";
|
|
56
|
+
/** Assertion for the options returned by `webauthnOptions()`. */
|
|
57
|
+
webAuthn: {
|
|
58
|
+
ceremonyToken: string;
|
|
59
|
+
/** JSON-serialized `PublicKeyCredential` from `navigator.credentials.get()`. */
|
|
60
|
+
assertionJson: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/** Passkey assertion options for approving one authorization. */
|
|
64
|
+
interface FinancialWebAuthnOptions {
|
|
65
|
+
ceremonyToken: string;
|
|
66
|
+
/** JSON `PublicKeyCredentialRequestOptions` to pass to `navigator.credentials.get()`. */
|
|
67
|
+
optionsJson: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type QueryParams = object;
|
|
71
|
+
|
|
1
72
|
interface HttpAdapterRequest {
|
|
2
73
|
url: string;
|
|
3
74
|
method: string;
|
|
@@ -55,6 +126,36 @@ declare class LoggingHttpAdapter implements HttpAdapter {
|
|
|
55
126
|
private log;
|
|
56
127
|
}
|
|
57
128
|
|
|
129
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
130
|
+
interface JsonRequestOptions {
|
|
131
|
+
method?: HttpMethod;
|
|
132
|
+
body?: unknown;
|
|
133
|
+
query?: QueryParams;
|
|
134
|
+
headers?: Record<string, string>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Sends a request already authenticated as the customer (end-user bearer). */
|
|
138
|
+
type SubjectRequest = <T>(path: string, options?: JsonRequestOptions) => Promise<T>;
|
|
139
|
+
/** Customer-side operations on a financial authorization (`/auth/authorizations`). */
|
|
140
|
+
declare function subjectFinancialAuthorizations(request: SubjectRequest): {
|
|
141
|
+
/** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
|
|
142
|
+
get: (id: string) => Promise<FinancialAuthorization>;
|
|
143
|
+
/** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
|
|
144
|
+
webauthnOptions: (id: string) => Promise<FinancialWebAuthnOptions>;
|
|
145
|
+
/**
|
|
146
|
+
* POST /auth/authorizations/{id}/confirm — approves the transaction.
|
|
147
|
+
*
|
|
148
|
+
* Pass the authenticator code or passkey assertion to verify the second
|
|
149
|
+
* factor inline (recommended). Without `input`, the session itself must
|
|
150
|
+
* have used a passkey or authenticator code within the last 5 minutes,
|
|
151
|
+
* otherwise the API answers `step_up_required`.
|
|
152
|
+
*/
|
|
153
|
+
confirm: (id: string, input?: ConfirmFinancialAuthorizationInput) => Promise<FinancialAuthorization>;
|
|
154
|
+
/** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
|
|
155
|
+
reject: (id: string) => Promise<FinancialAuthorization>;
|
|
156
|
+
};
|
|
157
|
+
type SubjectFinancialAuthorizations = ReturnType<typeof subjectFinancialAuthorizations>;
|
|
158
|
+
|
|
58
159
|
interface PaginationOptions {
|
|
59
160
|
skip?: number;
|
|
60
161
|
take?: number;
|
|
@@ -518,6 +619,13 @@ declare class AuthyonClient {
|
|
|
518
619
|
assertionStart: (challengeToken: string) => Promise<WebAuthnCeremonyStart>;
|
|
519
620
|
};
|
|
520
621
|
};
|
|
622
|
+
/**
|
|
623
|
+
* Transaction-bound approvals created by your backend
|
|
624
|
+
* (`@authyon/server` → `environment.financialAuthorizations.create`).
|
|
625
|
+
* Show the transaction with `get()`, then `confirm()` with the customer's
|
|
626
|
+
* authenticator code or passkey, or `reject()`.
|
|
627
|
+
*/
|
|
628
|
+
readonly financialAuthorizations: SubjectFinancialAuthorizations;
|
|
521
629
|
/**
|
|
522
630
|
* POST /auth/introspect — lightweight token introspection (RFC 7662).
|
|
523
631
|
*
|
|
@@ -642,4 +750,4 @@ declare function hasPermissionGroup(source: AuthyonPermissionSource | readonly s
|
|
|
642
750
|
/** Converts Authyon's `subject:action` permission strings to authorization rules. */
|
|
643
751
|
declare function createAuthyonRules(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AbilityRule[];
|
|
644
752
|
|
|
645
|
-
export {
|
|
753
|
+
export { type User as $, AuthyonClient as A, type InviteMemberInput as B, type ConfirmFinancialAuthorizationInput as C, type LoginInput as D, type LoginResult as E, FetchHttpAdapter as F, type OrganizationMember as G, type HttpAdapter as H, type IntrospectResult as I, type PaginationOptions as J, type PermissionGroup as K, LoggingHttpAdapter as L, type Role as M, type SessionControllerOptions as N, type Organization as O, type Paged as P, type SessionInfo as Q, type RegisterInput as R, type Session as S, type TokenStorage as T, type SessionSnapshot as U, type SessionSnapshotListener as V, type SessionStatus as W, type SsoProvider as X, type TwoFactorChallenge as Y, type TwoFactorMethod as Z, type TwoFactorStatus as _, type HttpLoggerOptions as a, type ValidateResult as a0, type VerifyTwoFactorInput as a1, type WebAuthnAssertion as a2, type WebAuthnCeremonyStart as a3, type WebAuthnCredential as a4, createAuthyonAbility as a5, createAuthyonRules as a6, createClient as a7, hasPermission as a8, hasPermissionGroup as a9, type AbilityConditions as b, type AbilityEvent as c, type AbilityListener as d, type AbilityRule as e, type AbilitySubject as f, type Activity as g, type AuthEvent as h, type AuthState as i, type AuthStateListener as j, type AuthenticatorSetup as k, AuthyonAbility as l, AuthyonAbilityBuilder as m, type AuthyonAbilityOptions as n, type AuthyonClientOptions as o, type AuthyonPermissionSource as p, AuthyonSessionController as q, type CreateOrganizationInput as r, type FinancialAssurance as s, type FinancialAuthorization as t, type FinancialAuthorizationStatus as u, type FinancialTransaction as v, type FinancialWebAuthnOptions as w, type HttpAdapterRequest as x, type HttpLogEvent as y, type HttpLogger as z };
|
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,32 @@ __export(index_exports, {
|
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(index_exports);
|
|
42
42
|
|
|
43
|
+
// ../../internal/core/financial/subjectFinancialAuthorizations.ts
|
|
44
|
+
function path(id, suffix = "") {
|
|
45
|
+
if (typeof id !== "string" || !id.trim())
|
|
46
|
+
throw new TypeError("Authyon: a financial authorization id is required.");
|
|
47
|
+
return `/auth/authorizations/${encodeURIComponent(id)}${suffix}`;
|
|
48
|
+
}
|
|
49
|
+
function subjectFinancialAuthorizations(request) {
|
|
50
|
+
return {
|
|
51
|
+
/** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
|
|
52
|
+
get: (id) => request(path(id)),
|
|
53
|
+
/** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
|
|
54
|
+
webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
|
|
55
|
+
/**
|
|
56
|
+
* POST /auth/authorizations/{id}/confirm — approves the transaction.
|
|
57
|
+
*
|
|
58
|
+
* Pass the authenticator code or passkey assertion to verify the second
|
|
59
|
+
* factor inline (recommended). Without `input`, the session itself must
|
|
60
|
+
* have used a passkey or authenticator code within the last 5 minutes,
|
|
61
|
+
* otherwise the API answers `step_up_required`.
|
|
62
|
+
*/
|
|
63
|
+
confirm: (id, input) => request(path(id, "/confirm"), { method: "POST", body: input }),
|
|
64
|
+
/** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
|
|
65
|
+
reject: (id) => request(path(id, "/reject"), { method: "POST" })
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
43
69
|
// ../../internal/core/errors/authyonError.ts
|
|
44
70
|
var ErrorCodes = {
|
|
45
71
|
Unknown: "unknown",
|
|
@@ -52,16 +78,37 @@ var ErrorCodes = {
|
|
|
52
78
|
EmailTaken: "user.email_taken",
|
|
53
79
|
PasswordWeak: "user.password_weak",
|
|
54
80
|
PasswordPwned: "user.password_pwned",
|
|
55
|
-
RateLimited: "rate_limited"
|
|
81
|
+
RateLimited: "rate_limited",
|
|
82
|
+
StepUpRequired: "step_up_required",
|
|
83
|
+
InvalidSecondFactorCode: "invalid_code",
|
|
84
|
+
VerificationAttemptsExhausted: "verification_attempts_exhausted",
|
|
85
|
+
MethodNotEnrolled: "method_not_enrolled",
|
|
86
|
+
InvalidAuthorizationState: "invalid_authorization_state",
|
|
87
|
+
TransactionMismatch: "transaction_mismatch",
|
|
88
|
+
AuthorizationNotConsumable: "authorization_not_consumable",
|
|
89
|
+
IdempotencyConflict: "idempotency_conflict"
|
|
56
90
|
};
|
|
91
|
+
var STANDARD_ERROR_FIELDS = /* @__PURE__ */ new Set([
|
|
92
|
+
"type",
|
|
93
|
+
"status",
|
|
94
|
+
"title",
|
|
95
|
+
"detail",
|
|
96
|
+
"code",
|
|
97
|
+
"error",
|
|
98
|
+
"error_description"
|
|
99
|
+
]);
|
|
57
100
|
var AuthyonError = class extends Error {
|
|
58
101
|
constructor(status, body, options = {}) {
|
|
59
|
-
|
|
102
|
+
const detail = body.detail ?? body.error_description;
|
|
103
|
+
super(detail ?? body.title ?? `Authyon request failed with status ${status}`);
|
|
60
104
|
this.name = "AuthyonError";
|
|
61
105
|
this.status = status;
|
|
62
|
-
this.code = body.code ?? "unknown";
|
|
106
|
+
this.code = body.code ?? body.error ?? "unknown";
|
|
63
107
|
this.title = body.title ?? "Error";
|
|
64
|
-
this.detail =
|
|
108
|
+
this.detail = detail;
|
|
109
|
+
this.extensions = Object.fromEntries(
|
|
110
|
+
Object.entries(body).filter(([key]) => !STANDARD_ERROR_FIELDS.has(key))
|
|
111
|
+
);
|
|
65
112
|
this.requestId = options.requestId;
|
|
66
113
|
this.retryAfter = options.retryAfter;
|
|
67
114
|
this.cause = options.cause;
|
|
@@ -111,6 +158,7 @@ var AuthyonError = class extends Error {
|
|
|
111
158
|
};
|
|
112
159
|
function classifyError(status, code) {
|
|
113
160
|
if (code === ErrorCodes.NetworkError) return "network";
|
|
161
|
+
if (code === ErrorCodes.StepUpRequired) return "authentication";
|
|
114
162
|
if (code === ErrorCodes.Timeout || status === 408) return "timeout";
|
|
115
163
|
if (code === ErrorCodes.RateLimited || status === 429) return "rate_limit";
|
|
116
164
|
if (code === ErrorCodes.EmailTaken || status === 409) return "conflict";
|
|
@@ -204,14 +252,14 @@ var DEFAULT_BASE_URL = "https://api.authyon.com";
|
|
|
204
252
|
var DEFAULT_EXPIRY_SKEW_MS = 3e4;
|
|
205
253
|
|
|
206
254
|
// ../../internal/core/http/query.ts
|
|
207
|
-
function appendQuery(
|
|
208
|
-
if (!params) return
|
|
255
|
+
function appendQuery(path2, params) {
|
|
256
|
+
if (!params) return path2;
|
|
209
257
|
const query = new URLSearchParams();
|
|
210
258
|
for (const [key, value2] of Object.entries(params)) {
|
|
211
259
|
if (value2 !== void 0) query.set(key, String(value2));
|
|
212
260
|
}
|
|
213
261
|
const value = query.toString();
|
|
214
|
-
return value ? `${
|
|
262
|
+
return value ? `${path2}${path2.includes("?") ? "&" : "?"}${value}` : path2;
|
|
215
263
|
}
|
|
216
264
|
|
|
217
265
|
// ../../internal/core/http/httpAdapter.ts
|
|
@@ -280,7 +328,6 @@ function sanitizeUrl(value) {
|
|
|
280
328
|
url.username = "";
|
|
281
329
|
url.password = "";
|
|
282
330
|
url.hash = "";
|
|
283
|
-
url.pathname = url.pathname.replace(/(\/platform\/workspace-invites\/)[^/]+/u, "$1REDACTED");
|
|
284
331
|
const queryKeys = /* @__PURE__ */ new Set();
|
|
285
332
|
url.searchParams.forEach((_value, key) => queryKeys.add(key));
|
|
286
333
|
url.search = queryKeys.size > 0 ? [...queryKeys].map((key) => `${encodeURIComponent(key)}=REDACTED`).join("&") : "";
|
|
@@ -310,12 +357,12 @@ function createSharedTransport(options) {
|
|
|
310
357
|
const httpAdapter = options.httpLogger ? new LoggingHttpAdapter(baseAdapter, options.httpLogger) : baseAdapter;
|
|
311
358
|
return {
|
|
312
359
|
baseUrl,
|
|
313
|
-
async request(
|
|
360
|
+
async request(path2, init) {
|
|
314
361
|
const controller = new AbortController();
|
|
315
362
|
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : void 0;
|
|
316
363
|
try {
|
|
317
364
|
return await httpAdapter.request({
|
|
318
|
-
url: `${baseUrl}${
|
|
365
|
+
url: `${baseUrl}${path2}`,
|
|
319
366
|
method: init.method ?? "GET",
|
|
320
367
|
headers: normalizeHeaders(init.headers),
|
|
321
368
|
body: init.body,
|
|
@@ -373,11 +420,11 @@ var JsonHttpClient = class {
|
|
|
373
420
|
constructor(transport) {
|
|
374
421
|
this.transport = transport;
|
|
375
422
|
}
|
|
376
|
-
async send(
|
|
423
|
+
async send(path2, options = {}) {
|
|
377
424
|
const headers = { ...options.headers };
|
|
378
425
|
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
379
426
|
try {
|
|
380
|
-
return await this.transport.request(appendQuery(
|
|
427
|
+
return await this.transport.request(appendQuery(path2, options.query), {
|
|
381
428
|
method: options.method ?? "GET",
|
|
382
429
|
headers,
|
|
383
430
|
body: options.body !== void 0 ? JSON.stringify(options.body) : void 0
|
|
@@ -391,7 +438,9 @@ var JsonHttpClient = class {
|
|
|
391
438
|
if (!response.ok) {
|
|
392
439
|
let body = {};
|
|
393
440
|
try {
|
|
394
|
-
|
|
441
|
+
const parsed = await response.json();
|
|
442
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
443
|
+
body = parsed;
|
|
395
444
|
} catch {
|
|
396
445
|
}
|
|
397
446
|
throw new AuthyonError(response.status, body, responseMetadata(response));
|
|
@@ -399,8 +448,8 @@ var JsonHttpClient = class {
|
|
|
399
448
|
if (response.status === 204) return void 0;
|
|
400
449
|
return await response.json();
|
|
401
450
|
}
|
|
402
|
-
async request(
|
|
403
|
-
return this.parse(await this.send(
|
|
451
|
+
async request(path2, options = {}) {
|
|
452
|
+
return this.parse(await this.send(path2, options));
|
|
404
453
|
}
|
|
405
454
|
};
|
|
406
455
|
|
|
@@ -638,6 +687,16 @@ var AuthyonClient = class {
|
|
|
638
687
|
})
|
|
639
688
|
}
|
|
640
689
|
};
|
|
690
|
+
// ── Financial step-up (customer side) ────────────────────────────────────
|
|
691
|
+
/**
|
|
692
|
+
* Transaction-bound approvals created by your backend
|
|
693
|
+
* (`@authyon/server` → `environment.financialAuthorizations.create`).
|
|
694
|
+
* Show the transaction with `get()`, then `confirm()` with the customer's
|
|
695
|
+
* authenticator code or passkey, or `reject()`.
|
|
696
|
+
*/
|
|
697
|
+
this.financialAuthorizations = subjectFinancialAuthorizations(
|
|
698
|
+
(path2, options) => this.request(path2, { ...options, bearer: true })
|
|
699
|
+
);
|
|
641
700
|
if (!options.envKey)
|
|
642
701
|
throw new Error("Authyon: `envKey` is required (pk_live_... / pk_test_...)");
|
|
643
702
|
this.envKey = options.envKey;
|
|
@@ -751,7 +810,7 @@ var AuthyonClient = class {
|
|
|
751
810
|
}
|
|
752
811
|
}
|
|
753
812
|
// ── HTTP core ────────────────────────────────────────────────────────────
|
|
754
|
-
async request(
|
|
813
|
+
async request(path2, options = {}, isRetry = false) {
|
|
755
814
|
const headers = {
|
|
756
815
|
"X-Authyon-Environment": this.envKey,
|
|
757
816
|
...clientIpHeaders({ clientIp: this.clientIp }),
|
|
@@ -766,7 +825,7 @@ var AuthyonClient = class {
|
|
|
766
825
|
});
|
|
767
826
|
headers.Authorization = `Bearer ${token}`;
|
|
768
827
|
}
|
|
769
|
-
const response = await this.http.send(
|
|
828
|
+
const response = await this.http.send(path2, { ...options, headers });
|
|
770
829
|
if (response.status === 401 && options.bearer && this.autoRefresh && !isRetry && this.getSession()) {
|
|
771
830
|
try {
|
|
772
831
|
await this.refresh();
|
|
@@ -774,7 +833,7 @@ var AuthyonClient = class {
|
|
|
774
833
|
this.clearSession();
|
|
775
834
|
return this.http.parse(response);
|
|
776
835
|
}
|
|
777
|
-
return this.request(
|
|
836
|
+
return this.request(path2, options, true);
|
|
778
837
|
}
|
|
779
838
|
return this.http.parse(response);
|
|
780
839
|
}
|
|
@@ -1193,18 +1252,18 @@ function matchesField(pattern, field) {
|
|
|
1193
1252
|
return pattern.endsWith(".*") && field.startsWith(pattern.slice(0, -1));
|
|
1194
1253
|
}
|
|
1195
1254
|
function matchesConditions(subject, conditions) {
|
|
1196
|
-
return Object.entries(conditions).every(([
|
|
1197
|
-
if (
|
|
1255
|
+
return Object.entries(conditions).every(([path2, expected]) => {
|
|
1256
|
+
if (path2 === "$and" && Array.isArray(expected)) {
|
|
1198
1257
|
return expected.every(
|
|
1199
1258
|
(condition) => matchesConditions(subject, condition)
|
|
1200
1259
|
);
|
|
1201
1260
|
}
|
|
1202
|
-
if (
|
|
1261
|
+
if (path2 === "$or" && Array.isArray(expected)) {
|
|
1203
1262
|
return expected.some(
|
|
1204
1263
|
(condition) => matchesConditions(subject, condition)
|
|
1205
1264
|
);
|
|
1206
1265
|
}
|
|
1207
|
-
return matchesValue(readPath(subject,
|
|
1266
|
+
return matchesValue(readPath(subject, path2), expected);
|
|
1208
1267
|
});
|
|
1209
1268
|
}
|
|
1210
1269
|
function matchesValue(actual, expected) {
|
|
@@ -1236,8 +1295,8 @@ function matchesValue(actual, expected) {
|
|
|
1236
1295
|
}
|
|
1237
1296
|
});
|
|
1238
1297
|
}
|
|
1239
|
-
function readPath(value,
|
|
1240
|
-
return
|
|
1298
|
+
function readPath(value, path2) {
|
|
1299
|
+
return path2.split(".").reduce((current, part) => isRecord(current) ? current[part] : void 0, value);
|
|
1241
1300
|
}
|
|
1242
1301
|
function defaultSubjectType(subject) {
|
|
1243
1302
|
const explicit = subject.__type ?? subject.type ?? subject.kind;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,19 +1,5 @@
|
|
|
1
|
-
import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-
|
|
2
|
-
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as CreateOrganizationInput, F as FetchHttpAdapter,
|
|
3
|
-
|
|
4
|
-
/** Builds an Authyon browser client through explicit, progressive configuration. */
|
|
5
|
-
declare class AuthyonClientBuilder {
|
|
6
|
-
private readonly options;
|
|
7
|
-
constructor(envKey: string);
|
|
8
|
-
withBaseUrl(baseUrl: string, allowInsecureHttp?: boolean): this;
|
|
9
|
-
withStorage(storage: TokenStorage): this;
|
|
10
|
-
withAutomaticRefresh(enabled?: boolean): this;
|
|
11
|
-
withClientIp(clientIp: string): this;
|
|
12
|
-
withTimeout(timeoutMs: number): this;
|
|
13
|
-
withHttpAdapter(httpAdapter: HttpAdapter): this;
|
|
14
|
-
withHttpLogger(httpLogger: HttpLoggerOptions): this;
|
|
15
|
-
build(): AuthyonClient;
|
|
16
|
-
}
|
|
1
|
+
import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-DbnbsQEX.cjs';
|
|
2
|
+
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as ConfirmFinancialAuthorizationInput, r as CreateOrganizationInput, F as FetchHttpAdapter, s as FinancialAssurance, t as FinancialAuthorization, u as FinancialAuthorizationStatus, v as FinancialTransaction, w as FinancialWebAuthnOptions, x as HttpAdapterRequest, y as HttpLogEvent, z as HttpLogger, I as IntrospectResult, B as InviteMemberInput, L as LoggingHttpAdapter, D as LoginInput, E as LoginResult, O as Organization, G as OrganizationMember, P as Paged, J as PaginationOptions, K as PermissionGroup, R as RegisterInput, M as Role, S as Session, N as SessionControllerOptions, Q as SessionInfo, U as SessionSnapshot, V as SessionSnapshotListener, W as SessionStatus, X as SsoProvider, Y as TwoFactorChallenge, Z as TwoFactorMethod, _ as TwoFactorStatus, $ as User, a0 as ValidateResult, a1 as VerifyTwoFactorInput, a2 as WebAuthnAssertion, a3 as WebAuthnCeremonyStart, a4 as WebAuthnCredential, a5 as createAuthyonAbility, a6 as createAuthyonRules, a7 as createClient, a8 as hasPermission, a9 as hasPermissionGroup } from './ability-DbnbsQEX.cjs';
|
|
17
3
|
|
|
18
4
|
declare const ErrorCodes: {
|
|
19
5
|
readonly Unknown: "unknown";
|
|
@@ -27,6 +13,14 @@ declare const ErrorCodes: {
|
|
|
27
13
|
readonly PasswordWeak: "user.password_weak";
|
|
28
14
|
readonly PasswordPwned: "user.password_pwned";
|
|
29
15
|
readonly RateLimited: "rate_limited";
|
|
16
|
+
readonly StepUpRequired: "step_up_required";
|
|
17
|
+
readonly InvalidSecondFactorCode: "invalid_code";
|
|
18
|
+
readonly VerificationAttemptsExhausted: "verification_attempts_exhausted";
|
|
19
|
+
readonly MethodNotEnrolled: "method_not_enrolled";
|
|
20
|
+
readonly InvalidAuthorizationState: "invalid_authorization_state";
|
|
21
|
+
readonly TransactionMismatch: "transaction_mismatch";
|
|
22
|
+
readonly AuthorizationNotConsumable: "authorization_not_consumable";
|
|
23
|
+
readonly IdempotencyConflict: "idempotency_conflict";
|
|
30
24
|
};
|
|
31
25
|
type KnownErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
32
26
|
type AuthyonErrorCategory = "network" | "timeout" | "authentication" | "authorization" | "validation" | "not_found" | "conflict" | "rate_limit" | "server" | "unknown";
|
|
@@ -38,6 +32,14 @@ interface AuthyonErrorInterpretation {
|
|
|
38
32
|
retryAfter?: number;
|
|
39
33
|
requestId?: string;
|
|
40
34
|
}
|
|
35
|
+
/** Error body as sent by the API: RFC 7807, or OAuth-style `error`/`error_description`. */
|
|
36
|
+
type AuthyonErrorBody = Partial<{
|
|
37
|
+
title: string;
|
|
38
|
+
detail: string;
|
|
39
|
+
code: string;
|
|
40
|
+
error: string;
|
|
41
|
+
error_description: string;
|
|
42
|
+
}> & Record<string, unknown>;
|
|
41
43
|
/** Shared RFC 7807 error implementation used by both public SDKs. */
|
|
42
44
|
declare class AuthyonError extends Error {
|
|
43
45
|
readonly status: number;
|
|
@@ -47,11 +49,13 @@ declare class AuthyonError extends Error {
|
|
|
47
49
|
readonly requestId?: string;
|
|
48
50
|
readonly retryAfter?: number;
|
|
49
51
|
readonly cause?: unknown;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Extra fields from the error body beyond code/title/detail — e.g.
|
|
54
|
+
* `attemptsRemaining` on `invalid_code` or `requiredMethods` on
|
|
55
|
+
* `step_up_required`. Not included in {@link toJSON}.
|
|
56
|
+
*/
|
|
57
|
+
readonly extensions: Readonly<Record<string, unknown>>;
|
|
58
|
+
constructor(status: number, body: AuthyonErrorBody, options?: {
|
|
55
59
|
requestId?: string;
|
|
56
60
|
retryAfter?: number;
|
|
57
61
|
cause?: unknown;
|
|
@@ -67,10 +71,24 @@ declare class AuthyonError extends Error {
|
|
|
67
71
|
toJSON(): Record<string, unknown>;
|
|
68
72
|
}
|
|
69
73
|
|
|
74
|
+
/** Builds an Authyon browser client through explicit, progressive configuration. */
|
|
75
|
+
declare class AuthyonClientBuilder {
|
|
76
|
+
private readonly options;
|
|
77
|
+
constructor(envKey: string);
|
|
78
|
+
withBaseUrl(baseUrl: string, allowInsecureHttp?: boolean): this;
|
|
79
|
+
withStorage(storage: TokenStorage): this;
|
|
80
|
+
withAutomaticRefresh(enabled?: boolean): this;
|
|
81
|
+
withClientIp(clientIp: string): this;
|
|
82
|
+
withTimeout(timeoutMs: number): this;
|
|
83
|
+
withHttpAdapter(httpAdapter: HttpAdapter): this;
|
|
84
|
+
withHttpLogger(httpLogger: HttpLoggerOptions): this;
|
|
85
|
+
build(): AuthyonClient;
|
|
86
|
+
}
|
|
87
|
+
|
|
70
88
|
/** Keeps the session in memory only (lost on page reload). */
|
|
71
89
|
declare function createMemoryStorage(): TokenStorage;
|
|
72
90
|
/** Persists the session in `localStorage` under a namespaced key. */
|
|
73
91
|
declare function createLocalStorage(key?: string): TokenStorage;
|
|
74
92
|
declare function createDefaultStorage(): TokenStorage;
|
|
75
93
|
|
|
76
|
-
export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
|
|
94
|
+
export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,5 @@
|
|
|
1
|
-
import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-
|
|
2
|
-
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as CreateOrganizationInput, F as FetchHttpAdapter,
|
|
3
|
-
|
|
4
|
-
/** Builds an Authyon browser client through explicit, progressive configuration. */
|
|
5
|
-
declare class AuthyonClientBuilder {
|
|
6
|
-
private readonly options;
|
|
7
|
-
constructor(envKey: string);
|
|
8
|
-
withBaseUrl(baseUrl: string, allowInsecureHttp?: boolean): this;
|
|
9
|
-
withStorage(storage: TokenStorage): this;
|
|
10
|
-
withAutomaticRefresh(enabled?: boolean): this;
|
|
11
|
-
withClientIp(clientIp: string): this;
|
|
12
|
-
withTimeout(timeoutMs: number): this;
|
|
13
|
-
withHttpAdapter(httpAdapter: HttpAdapter): this;
|
|
14
|
-
withHttpLogger(httpLogger: HttpLoggerOptions): this;
|
|
15
|
-
build(): AuthyonClient;
|
|
16
|
-
}
|
|
1
|
+
import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-DbnbsQEX.js';
|
|
2
|
+
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as ConfirmFinancialAuthorizationInput, r as CreateOrganizationInput, F as FetchHttpAdapter, s as FinancialAssurance, t as FinancialAuthorization, u as FinancialAuthorizationStatus, v as FinancialTransaction, w as FinancialWebAuthnOptions, x as HttpAdapterRequest, y as HttpLogEvent, z as HttpLogger, I as IntrospectResult, B as InviteMemberInput, L as LoggingHttpAdapter, D as LoginInput, E as LoginResult, O as Organization, G as OrganizationMember, P as Paged, J as PaginationOptions, K as PermissionGroup, R as RegisterInput, M as Role, S as Session, N as SessionControllerOptions, Q as SessionInfo, U as SessionSnapshot, V as SessionSnapshotListener, W as SessionStatus, X as SsoProvider, Y as TwoFactorChallenge, Z as TwoFactorMethod, _ as TwoFactorStatus, $ as User, a0 as ValidateResult, a1 as VerifyTwoFactorInput, a2 as WebAuthnAssertion, a3 as WebAuthnCeremonyStart, a4 as WebAuthnCredential, a5 as createAuthyonAbility, a6 as createAuthyonRules, a7 as createClient, a8 as hasPermission, a9 as hasPermissionGroup } from './ability-DbnbsQEX.js';
|
|
17
3
|
|
|
18
4
|
declare const ErrorCodes: {
|
|
19
5
|
readonly Unknown: "unknown";
|
|
@@ -27,6 +13,14 @@ declare const ErrorCodes: {
|
|
|
27
13
|
readonly PasswordWeak: "user.password_weak";
|
|
28
14
|
readonly PasswordPwned: "user.password_pwned";
|
|
29
15
|
readonly RateLimited: "rate_limited";
|
|
16
|
+
readonly StepUpRequired: "step_up_required";
|
|
17
|
+
readonly InvalidSecondFactorCode: "invalid_code";
|
|
18
|
+
readonly VerificationAttemptsExhausted: "verification_attempts_exhausted";
|
|
19
|
+
readonly MethodNotEnrolled: "method_not_enrolled";
|
|
20
|
+
readonly InvalidAuthorizationState: "invalid_authorization_state";
|
|
21
|
+
readonly TransactionMismatch: "transaction_mismatch";
|
|
22
|
+
readonly AuthorizationNotConsumable: "authorization_not_consumable";
|
|
23
|
+
readonly IdempotencyConflict: "idempotency_conflict";
|
|
30
24
|
};
|
|
31
25
|
type KnownErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
32
26
|
type AuthyonErrorCategory = "network" | "timeout" | "authentication" | "authorization" | "validation" | "not_found" | "conflict" | "rate_limit" | "server" | "unknown";
|
|
@@ -38,6 +32,14 @@ interface AuthyonErrorInterpretation {
|
|
|
38
32
|
retryAfter?: number;
|
|
39
33
|
requestId?: string;
|
|
40
34
|
}
|
|
35
|
+
/** Error body as sent by the API: RFC 7807, or OAuth-style `error`/`error_description`. */
|
|
36
|
+
type AuthyonErrorBody = Partial<{
|
|
37
|
+
title: string;
|
|
38
|
+
detail: string;
|
|
39
|
+
code: string;
|
|
40
|
+
error: string;
|
|
41
|
+
error_description: string;
|
|
42
|
+
}> & Record<string, unknown>;
|
|
41
43
|
/** Shared RFC 7807 error implementation used by both public SDKs. */
|
|
42
44
|
declare class AuthyonError extends Error {
|
|
43
45
|
readonly status: number;
|
|
@@ -47,11 +49,13 @@ declare class AuthyonError extends Error {
|
|
|
47
49
|
readonly requestId?: string;
|
|
48
50
|
readonly retryAfter?: number;
|
|
49
51
|
readonly cause?: unknown;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Extra fields from the error body beyond code/title/detail — e.g.
|
|
54
|
+
* `attemptsRemaining` on `invalid_code` or `requiredMethods` on
|
|
55
|
+
* `step_up_required`. Not included in {@link toJSON}.
|
|
56
|
+
*/
|
|
57
|
+
readonly extensions: Readonly<Record<string, unknown>>;
|
|
58
|
+
constructor(status: number, body: AuthyonErrorBody, options?: {
|
|
55
59
|
requestId?: string;
|
|
56
60
|
retryAfter?: number;
|
|
57
61
|
cause?: unknown;
|
|
@@ -67,10 +71,24 @@ declare class AuthyonError extends Error {
|
|
|
67
71
|
toJSON(): Record<string, unknown>;
|
|
68
72
|
}
|
|
69
73
|
|
|
74
|
+
/** Builds an Authyon browser client through explicit, progressive configuration. */
|
|
75
|
+
declare class AuthyonClientBuilder {
|
|
76
|
+
private readonly options;
|
|
77
|
+
constructor(envKey: string);
|
|
78
|
+
withBaseUrl(baseUrl: string, allowInsecureHttp?: boolean): this;
|
|
79
|
+
withStorage(storage: TokenStorage): this;
|
|
80
|
+
withAutomaticRefresh(enabled?: boolean): this;
|
|
81
|
+
withClientIp(clientIp: string): this;
|
|
82
|
+
withTimeout(timeoutMs: number): this;
|
|
83
|
+
withHttpAdapter(httpAdapter: HttpAdapter): this;
|
|
84
|
+
withHttpLogger(httpLogger: HttpLoggerOptions): this;
|
|
85
|
+
build(): AuthyonClient;
|
|
86
|
+
}
|
|
87
|
+
|
|
70
88
|
/** Keeps the session in memory only (lost on page reload). */
|
|
71
89
|
declare function createMemoryStorage(): TokenStorage;
|
|
72
90
|
/** Persists the session in `localStorage` under a namespaced key. */
|
|
73
91
|
declare function createLocalStorage(key?: string): TokenStorage;
|
|
74
92
|
declare function createDefaultStorage(): TokenStorage;
|
|
75
93
|
|
|
76
|
-
export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
|
|
94
|
+
export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,32 @@ import {
|
|
|
8
8
|
hasPermissionGroup
|
|
9
9
|
} from "./chunk-3XJY6BCI.js";
|
|
10
10
|
|
|
11
|
+
// ../../internal/core/financial/subjectFinancialAuthorizations.ts
|
|
12
|
+
function path(id, suffix = "") {
|
|
13
|
+
if (typeof id !== "string" || !id.trim())
|
|
14
|
+
throw new TypeError("Authyon: a financial authorization id is required.");
|
|
15
|
+
return `/auth/authorizations/${encodeURIComponent(id)}${suffix}`;
|
|
16
|
+
}
|
|
17
|
+
function subjectFinancialAuthorizations(request) {
|
|
18
|
+
return {
|
|
19
|
+
/** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
|
|
20
|
+
get: (id) => request(path(id)),
|
|
21
|
+
/** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
|
|
22
|
+
webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
|
|
23
|
+
/**
|
|
24
|
+
* POST /auth/authorizations/{id}/confirm — approves the transaction.
|
|
25
|
+
*
|
|
26
|
+
* Pass the authenticator code or passkey assertion to verify the second
|
|
27
|
+
* factor inline (recommended). Without `input`, the session itself must
|
|
28
|
+
* have used a passkey or authenticator code within the last 5 minutes,
|
|
29
|
+
* otherwise the API answers `step_up_required`.
|
|
30
|
+
*/
|
|
31
|
+
confirm: (id, input) => request(path(id, "/confirm"), { method: "POST", body: input }),
|
|
32
|
+
/** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
|
|
33
|
+
reject: (id) => request(path(id, "/reject"), { method: "POST" })
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
11
37
|
// ../../internal/core/errors/authyonError.ts
|
|
12
38
|
var ErrorCodes = {
|
|
13
39
|
Unknown: "unknown",
|
|
@@ -20,16 +46,37 @@ var ErrorCodes = {
|
|
|
20
46
|
EmailTaken: "user.email_taken",
|
|
21
47
|
PasswordWeak: "user.password_weak",
|
|
22
48
|
PasswordPwned: "user.password_pwned",
|
|
23
|
-
RateLimited: "rate_limited"
|
|
49
|
+
RateLimited: "rate_limited",
|
|
50
|
+
StepUpRequired: "step_up_required",
|
|
51
|
+
InvalidSecondFactorCode: "invalid_code",
|
|
52
|
+
VerificationAttemptsExhausted: "verification_attempts_exhausted",
|
|
53
|
+
MethodNotEnrolled: "method_not_enrolled",
|
|
54
|
+
InvalidAuthorizationState: "invalid_authorization_state",
|
|
55
|
+
TransactionMismatch: "transaction_mismatch",
|
|
56
|
+
AuthorizationNotConsumable: "authorization_not_consumable",
|
|
57
|
+
IdempotencyConflict: "idempotency_conflict"
|
|
24
58
|
};
|
|
59
|
+
var STANDARD_ERROR_FIELDS = /* @__PURE__ */ new Set([
|
|
60
|
+
"type",
|
|
61
|
+
"status",
|
|
62
|
+
"title",
|
|
63
|
+
"detail",
|
|
64
|
+
"code",
|
|
65
|
+
"error",
|
|
66
|
+
"error_description"
|
|
67
|
+
]);
|
|
25
68
|
var AuthyonError = class extends Error {
|
|
26
69
|
constructor(status, body, options = {}) {
|
|
27
|
-
|
|
70
|
+
const detail = body.detail ?? body.error_description;
|
|
71
|
+
super(detail ?? body.title ?? `Authyon request failed with status ${status}`);
|
|
28
72
|
this.name = "AuthyonError";
|
|
29
73
|
this.status = status;
|
|
30
|
-
this.code = body.code ?? "unknown";
|
|
74
|
+
this.code = body.code ?? body.error ?? "unknown";
|
|
31
75
|
this.title = body.title ?? "Error";
|
|
32
|
-
this.detail =
|
|
76
|
+
this.detail = detail;
|
|
77
|
+
this.extensions = Object.fromEntries(
|
|
78
|
+
Object.entries(body).filter(([key]) => !STANDARD_ERROR_FIELDS.has(key))
|
|
79
|
+
);
|
|
33
80
|
this.requestId = options.requestId;
|
|
34
81
|
this.retryAfter = options.retryAfter;
|
|
35
82
|
this.cause = options.cause;
|
|
@@ -79,6 +126,7 @@ var AuthyonError = class extends Error {
|
|
|
79
126
|
};
|
|
80
127
|
function classifyError(status, code) {
|
|
81
128
|
if (code === ErrorCodes.NetworkError) return "network";
|
|
129
|
+
if (code === ErrorCodes.StepUpRequired) return "authentication";
|
|
82
130
|
if (code === ErrorCodes.Timeout || status === 408) return "timeout";
|
|
83
131
|
if (code === ErrorCodes.RateLimited || status === 429) return "rate_limit";
|
|
84
132
|
if (code === ErrorCodes.EmailTaken || status === 409) return "conflict";
|
|
@@ -172,14 +220,14 @@ var DEFAULT_BASE_URL = "https://api.authyon.com";
|
|
|
172
220
|
var DEFAULT_EXPIRY_SKEW_MS = 3e4;
|
|
173
221
|
|
|
174
222
|
// ../../internal/core/http/query.ts
|
|
175
|
-
function appendQuery(
|
|
176
|
-
if (!params) return
|
|
223
|
+
function appendQuery(path2, params) {
|
|
224
|
+
if (!params) return path2;
|
|
177
225
|
const query = new URLSearchParams();
|
|
178
226
|
for (const [key, value2] of Object.entries(params)) {
|
|
179
227
|
if (value2 !== void 0) query.set(key, String(value2));
|
|
180
228
|
}
|
|
181
229
|
const value = query.toString();
|
|
182
|
-
return value ? `${
|
|
230
|
+
return value ? `${path2}${path2.includes("?") ? "&" : "?"}${value}` : path2;
|
|
183
231
|
}
|
|
184
232
|
|
|
185
233
|
// ../../internal/core/http/httpAdapter.ts
|
|
@@ -248,7 +296,6 @@ function sanitizeUrl(value) {
|
|
|
248
296
|
url.username = "";
|
|
249
297
|
url.password = "";
|
|
250
298
|
url.hash = "";
|
|
251
|
-
url.pathname = url.pathname.replace(/(\/platform\/workspace-invites\/)[^/]+/u, "$1REDACTED");
|
|
252
299
|
const queryKeys = /* @__PURE__ */ new Set();
|
|
253
300
|
url.searchParams.forEach((_value, key) => queryKeys.add(key));
|
|
254
301
|
url.search = queryKeys.size > 0 ? [...queryKeys].map((key) => `${encodeURIComponent(key)}=REDACTED`).join("&") : "";
|
|
@@ -278,12 +325,12 @@ function createSharedTransport(options) {
|
|
|
278
325
|
const httpAdapter = options.httpLogger ? new LoggingHttpAdapter(baseAdapter, options.httpLogger) : baseAdapter;
|
|
279
326
|
return {
|
|
280
327
|
baseUrl,
|
|
281
|
-
async request(
|
|
328
|
+
async request(path2, init) {
|
|
282
329
|
const controller = new AbortController();
|
|
283
330
|
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : void 0;
|
|
284
331
|
try {
|
|
285
332
|
return await httpAdapter.request({
|
|
286
|
-
url: `${baseUrl}${
|
|
333
|
+
url: `${baseUrl}${path2}`,
|
|
287
334
|
method: init.method ?? "GET",
|
|
288
335
|
headers: normalizeHeaders(init.headers),
|
|
289
336
|
body: init.body,
|
|
@@ -341,11 +388,11 @@ var JsonHttpClient = class {
|
|
|
341
388
|
constructor(transport) {
|
|
342
389
|
this.transport = transport;
|
|
343
390
|
}
|
|
344
|
-
async send(
|
|
391
|
+
async send(path2, options = {}) {
|
|
345
392
|
const headers = { ...options.headers };
|
|
346
393
|
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
347
394
|
try {
|
|
348
|
-
return await this.transport.request(appendQuery(
|
|
395
|
+
return await this.transport.request(appendQuery(path2, options.query), {
|
|
349
396
|
method: options.method ?? "GET",
|
|
350
397
|
headers,
|
|
351
398
|
body: options.body !== void 0 ? JSON.stringify(options.body) : void 0
|
|
@@ -359,7 +406,9 @@ var JsonHttpClient = class {
|
|
|
359
406
|
if (!response.ok) {
|
|
360
407
|
let body = {};
|
|
361
408
|
try {
|
|
362
|
-
|
|
409
|
+
const parsed = await response.json();
|
|
410
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
411
|
+
body = parsed;
|
|
363
412
|
} catch {
|
|
364
413
|
}
|
|
365
414
|
throw new AuthyonError(response.status, body, responseMetadata(response));
|
|
@@ -367,8 +416,8 @@ var JsonHttpClient = class {
|
|
|
367
416
|
if (response.status === 204) return void 0;
|
|
368
417
|
return await response.json();
|
|
369
418
|
}
|
|
370
|
-
async request(
|
|
371
|
-
return this.parse(await this.send(
|
|
419
|
+
async request(path2, options = {}) {
|
|
420
|
+
return this.parse(await this.send(path2, options));
|
|
372
421
|
}
|
|
373
422
|
};
|
|
374
423
|
|
|
@@ -606,6 +655,16 @@ var AuthyonClient = class {
|
|
|
606
655
|
})
|
|
607
656
|
}
|
|
608
657
|
};
|
|
658
|
+
// ── Financial step-up (customer side) ────────────────────────────────────
|
|
659
|
+
/**
|
|
660
|
+
* Transaction-bound approvals created by your backend
|
|
661
|
+
* (`@authyon/server` → `environment.financialAuthorizations.create`).
|
|
662
|
+
* Show the transaction with `get()`, then `confirm()` with the customer's
|
|
663
|
+
* authenticator code or passkey, or `reject()`.
|
|
664
|
+
*/
|
|
665
|
+
this.financialAuthorizations = subjectFinancialAuthorizations(
|
|
666
|
+
(path2, options) => this.request(path2, { ...options, bearer: true })
|
|
667
|
+
);
|
|
609
668
|
if (!options.envKey)
|
|
610
669
|
throw new Error("Authyon: `envKey` is required (pk_live_... / pk_test_...)");
|
|
611
670
|
this.envKey = options.envKey;
|
|
@@ -719,7 +778,7 @@ var AuthyonClient = class {
|
|
|
719
778
|
}
|
|
720
779
|
}
|
|
721
780
|
// ── HTTP core ────────────────────────────────────────────────────────────
|
|
722
|
-
async request(
|
|
781
|
+
async request(path2, options = {}, isRetry = false) {
|
|
723
782
|
const headers = {
|
|
724
783
|
"X-Authyon-Environment": this.envKey,
|
|
725
784
|
...clientIpHeaders({ clientIp: this.clientIp }),
|
|
@@ -734,7 +793,7 @@ var AuthyonClient = class {
|
|
|
734
793
|
});
|
|
735
794
|
headers.Authorization = `Bearer ${token}`;
|
|
736
795
|
}
|
|
737
|
-
const response = await this.http.send(
|
|
796
|
+
const response = await this.http.send(path2, { ...options, headers });
|
|
738
797
|
if (response.status === 401 && options.bearer && this.autoRefresh && !isRetry && this.getSession()) {
|
|
739
798
|
try {
|
|
740
799
|
await this.refresh();
|
|
@@ -742,7 +801,7 @@ var AuthyonClient = class {
|
|
|
742
801
|
this.clearSession();
|
|
743
802
|
return this.http.parse(response);
|
|
744
803
|
}
|
|
745
|
-
return this.request(
|
|
804
|
+
return this.request(path2, options, true);
|
|
746
805
|
}
|
|
747
806
|
return this.http.parse(response);
|
|
748
807
|
}
|
package/dist/react/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { q as AuthyonSessionController,
|
|
3
|
+
import { $ as User, N as SessionControllerOptions, A as AuthyonClient, U as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-DbnbsQEX.cjs';
|
|
4
|
+
export { q as AuthyonSessionController, V as SessionSnapshotListener, W as SessionStatus } from '../ability-DbnbsQEX.cjs';
|
|
5
5
|
|
|
6
6
|
interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
|
|
7
7
|
client: AuthyonClient;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { q as AuthyonSessionController,
|
|
3
|
+
import { $ as User, N as SessionControllerOptions, A as AuthyonClient, U as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-DbnbsQEX.js';
|
|
4
|
+
export { q as AuthyonSessionController, V as SessionSnapshotListener, W as SessionStatus } from '../ability-DbnbsQEX.js';
|
|
5
5
|
|
|
6
6
|
interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
|
|
7
7
|
client: AuthyonClient;
|