@heyatom/bastion-client 0.7.0 → 0.7.2
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 +1 -1
- package/dist/cjs/core/api-client.d.ts +12 -3
- package/dist/cjs/core/api-client.js +11 -5
- package/dist/cjs/core/types.d.ts +6 -0
- package/dist/esm/core/api-client.d.ts +12 -3
- package/dist/esm/core/api-client.js +11 -5
- package/dist/esm/core/types.d.ts +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Consumer SDK for [Bastion](https://github.com/heyatomdev/bastion), the HeyAtom i
|
|
|
4
4
|
Replaces the `src/modules/bastion/` boilerplate every service used to copy by hand.
|
|
5
5
|
|
|
6
6
|
- `@heyatom/bastion-client` — framework-free core: `JwksVerifier` (kid-indexed cache, unknown-kid refetch with cooldown, stale-on-error), `BastionHttp` (`POST /auth/client`, `POST /events`, any other route), `ServiceTokenProvider` (single-flight refresh ahead of `exp`), payload types.
|
|
7
|
-
- `@heyatom/bastion-client` also carries Bastion's user-API contract: `BastionApiClient` (login, register, OAuth exchange, 2FA, single-flight refresh, logout, sessions, `/me`, profile, social accounts, email/password flows, export, delete), its types (`BastionMe`, `BastionTokenPair`, …) and `BastionErrorCode` (a stable code on every `BastionHttpError`: credentials, app context, refresh token, OAuth code, age gate, OAuth flow, unavailable, upstream). `refreshMemoryMs` tunes how long a refresh answer is remembered per token (default 60 s).
|
|
7
|
+
- `@heyatom/bastion-client` also carries Bastion's user-API contract: `BastionApiClient` (login, register, OAuth exchange, 2FA, single-flight refresh, logout, sessions, `/me`, profile, social accounts, email/password flows, export, delete), its types (`BastionMe`, `BastionTokenPair`, …) and `BastionErrorCode` (a stable code on every `BastionHttpError`: credentials, app context, refresh token, OAuth code, age gate, OAuth flow, unavailable, upstream). `refreshMemoryMs` tunes how long a refresh answer is remembered per token (default 60 s). Since 0.7.2 `completeAgeVerification(token, birthDate, { currentPassword?, twoFactorCode? })` sends the step-up Bastion requires (as `deleteSelf`), and `UserJwtPayload.ageVerificationRequired?: true` is set only while the account owes the app's age screen: a consumer API can refuse it from the token alone.
|
|
8
8
|
- `@heyatom/bastion-client/webhooks` — `verifyWebhookSignature` (`X-Bastion-Signature-V2` with timestamp + delivery id, legacy fallback only with `allowLegacySignature: true` (off by default since 0.7.0), secret rotation on both sides), header constants, payload type.
|
|
9
9
|
- `@heyatom/bastion-client/nest` — NestJS: `BastionModule`, `ServiceClientJwtGuard`, `BastionUserGuard`, `BastionAuditService`, `AuditInterceptor` (attributes to `req.adminUser`, any `AuditActor` shape: `sub` plus optional `tenantId`/`tenantSlug`/`role`/`appSlug`), `@Public()`, `@RequireScope()`, `@Audit()`, `@CurrentClient()`, `@CurrentAdminUser()`.
|
|
10
10
|
|
|
@@ -50,8 +50,13 @@ export declare class BastionApiClient {
|
|
|
50
50
|
register(input: BastionRegisterInput, ctx?: BastionClientContext): Promise<{
|
|
51
51
|
message: string;
|
|
52
52
|
}>;
|
|
53
|
-
/**
|
|
54
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Trades the one-time OAuth code for tokens. `state` is the value the app put
|
|
55
|
+
* on the initiate URL, read back from its own cookie/session (never from the
|
|
56
|
+
* callback query): Bastion refuses a code minted under a different one, which
|
|
57
|
+
* is what stops an attacker's code from being redeemed in a victim's browser.
|
|
58
|
+
*/
|
|
59
|
+
exchange(code: string, ctx?: BastionClientContext, state?: string): Promise<BastionLoginResult>;
|
|
55
60
|
completeTwoFactor(twoFactorToken: string, code: string, ctx?: BastionClientContext): Promise<BastionTokenPair>;
|
|
56
61
|
refresh(refreshToken: string, ctx?: BastionClientContext): Promise<BastionTokenPair>;
|
|
57
62
|
/** Revokes the token and any successor issued through `refresh` within the memory window. Never throws. */
|
|
@@ -64,7 +69,11 @@ export declare class BastionApiClient {
|
|
|
64
69
|
me(accessToken: string): Promise<BastionMe>;
|
|
65
70
|
/** Answers the updated columns only (`BastionProfile`), not the full `BastionMe`. */
|
|
66
71
|
updateProfile(accessToken: string, update: BastionProfileUpdate): Promise<BastionProfile>;
|
|
67
|
-
|
|
72
|
+
/** Step-up as `deleteSelf`: `currentPassword` when the account has one, `twoFactorCode` when 2FA is on. */
|
|
73
|
+
completeAgeVerification(accessToken: string, birthDate: string, stepUp?: {
|
|
74
|
+
currentPassword?: string;
|
|
75
|
+
twoFactorCode?: string;
|
|
76
|
+
}): Promise<BastionAgeVerificationResult>;
|
|
68
77
|
/** Cached 5 min; a failed refetch serves the cached answer. */
|
|
69
78
|
getAuthMethods(): Promise<BastionAuthMethods>;
|
|
70
79
|
twoFactorStatus(accessToken: string): Promise<BastionTwoFactorStatus>;
|
|
@@ -61,9 +61,14 @@ class BastionApiClient {
|
|
|
61
61
|
register(input, ctx) {
|
|
62
62
|
return this.call('POST', '/auth/register', { ...input, ...this.appContext }, { headers: BastionApiClient.clientHeaders(ctx) });
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Trades the one-time OAuth code for tokens. `state` is the value the app put
|
|
66
|
+
* on the initiate URL, read back from its own cookie/session (never from the
|
|
67
|
+
* callback query): Bastion refuses a code minted under a different one, which
|
|
68
|
+
* is what stops an attacker's code from being redeemed in a victim's browser.
|
|
69
|
+
*/
|
|
70
|
+
exchange(code, ctx, state) {
|
|
71
|
+
return this.call('POST', '/auth/exchange', { code, appSlug: this.appSlug, ...(state !== undefined ? { state } : {}) }, { headers: BastionApiClient.clientHeaders(ctx) });
|
|
67
72
|
}
|
|
68
73
|
completeTwoFactor(twoFactorToken, code, ctx) {
|
|
69
74
|
return this.call('POST', '/auth/2fa/authenticate', { twoFactorToken, code }, { headers: BastionApiClient.clientHeaders(ctx) });
|
|
@@ -113,8 +118,9 @@ class BastionApiClient {
|
|
|
113
118
|
updateProfile(accessToken, update) {
|
|
114
119
|
return this.call('PATCH', '/auth/me', update, { token: accessToken });
|
|
115
120
|
}
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
/** Step-up as `deleteSelf`: `currentPassword` when the account has one, `twoFactorCode` when 2FA is on. */
|
|
122
|
+
completeAgeVerification(accessToken, birthDate, stepUp = {}) {
|
|
123
|
+
return this.call('POST', '/auth/age-verification', { birthDate, ...stepUp }, { token: accessToken });
|
|
118
124
|
}
|
|
119
125
|
/** Cached 5 min; a failed refetch serves the cached answer. */
|
|
120
126
|
async getAuthMethods() {
|
package/dist/cjs/core/types.d.ts
CHANGED
|
@@ -20,6 +20,12 @@ export interface UserJwtPayload extends CommonClaims {
|
|
|
20
20
|
role: string;
|
|
21
21
|
permissions: string[];
|
|
22
22
|
sessionId?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Present (always `true`) only while the app has a minimum age and the account hasn't cleared
|
|
25
|
+
* it — an OAuth signup that hasn't answered `completeAgeVerification`. Absent on every other
|
|
26
|
+
* token. Recomputed at each issuance: refresh after the screen.
|
|
27
|
+
*/
|
|
28
|
+
ageVerificationRequired?: true;
|
|
23
29
|
}
|
|
24
30
|
/** A machine token from `POST /auth/client`. Discriminated by `type`. */
|
|
25
31
|
export interface ServiceClientJwtPayload extends CommonClaims {
|
|
@@ -50,8 +50,13 @@ export declare class BastionApiClient {
|
|
|
50
50
|
register(input: BastionRegisterInput, ctx?: BastionClientContext): Promise<{
|
|
51
51
|
message: string;
|
|
52
52
|
}>;
|
|
53
|
-
/**
|
|
54
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Trades the one-time OAuth code for tokens. `state` is the value the app put
|
|
55
|
+
* on the initiate URL, read back from its own cookie/session (never from the
|
|
56
|
+
* callback query): Bastion refuses a code minted under a different one, which
|
|
57
|
+
* is what stops an attacker's code from being redeemed in a victim's browser.
|
|
58
|
+
*/
|
|
59
|
+
exchange(code: string, ctx?: BastionClientContext, state?: string): Promise<BastionLoginResult>;
|
|
55
60
|
completeTwoFactor(twoFactorToken: string, code: string, ctx?: BastionClientContext): Promise<BastionTokenPair>;
|
|
56
61
|
refresh(refreshToken: string, ctx?: BastionClientContext): Promise<BastionTokenPair>;
|
|
57
62
|
/** Revokes the token and any successor issued through `refresh` within the memory window. Never throws. */
|
|
@@ -64,7 +69,11 @@ export declare class BastionApiClient {
|
|
|
64
69
|
me(accessToken: string): Promise<BastionMe>;
|
|
65
70
|
/** Answers the updated columns only (`BastionProfile`), not the full `BastionMe`. */
|
|
66
71
|
updateProfile(accessToken: string, update: BastionProfileUpdate): Promise<BastionProfile>;
|
|
67
|
-
|
|
72
|
+
/** Step-up as `deleteSelf`: `currentPassword` when the account has one, `twoFactorCode` when 2FA is on. */
|
|
73
|
+
completeAgeVerification(accessToken: string, birthDate: string, stepUp?: {
|
|
74
|
+
currentPassword?: string;
|
|
75
|
+
twoFactorCode?: string;
|
|
76
|
+
}): Promise<BastionAgeVerificationResult>;
|
|
68
77
|
/** Cached 5 min; a failed refetch serves the cached answer. */
|
|
69
78
|
getAuthMethods(): Promise<BastionAuthMethods>;
|
|
70
79
|
twoFactorStatus(accessToken: string): Promise<BastionTwoFactorStatus>;
|
|
@@ -58,9 +58,14 @@ export class BastionApiClient {
|
|
|
58
58
|
register(input, ctx) {
|
|
59
59
|
return this.call('POST', '/auth/register', { ...input, ...this.appContext }, { headers: BastionApiClient.clientHeaders(ctx) });
|
|
60
60
|
}
|
|
61
|
-
/**
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Trades the one-time OAuth code for tokens. `state` is the value the app put
|
|
63
|
+
* on the initiate URL, read back from its own cookie/session (never from the
|
|
64
|
+
* callback query): Bastion refuses a code minted under a different one, which
|
|
65
|
+
* is what stops an attacker's code from being redeemed in a victim's browser.
|
|
66
|
+
*/
|
|
67
|
+
exchange(code, ctx, state) {
|
|
68
|
+
return this.call('POST', '/auth/exchange', { code, appSlug: this.appSlug, ...(state !== undefined ? { state } : {}) }, { headers: BastionApiClient.clientHeaders(ctx) });
|
|
64
69
|
}
|
|
65
70
|
completeTwoFactor(twoFactorToken, code, ctx) {
|
|
66
71
|
return this.call('POST', '/auth/2fa/authenticate', { twoFactorToken, code }, { headers: BastionApiClient.clientHeaders(ctx) });
|
|
@@ -110,8 +115,9 @@ export class BastionApiClient {
|
|
|
110
115
|
updateProfile(accessToken, update) {
|
|
111
116
|
return this.call('PATCH', '/auth/me', update, { token: accessToken });
|
|
112
117
|
}
|
|
113
|
-
|
|
114
|
-
|
|
118
|
+
/** Step-up as `deleteSelf`: `currentPassword` when the account has one, `twoFactorCode` when 2FA is on. */
|
|
119
|
+
completeAgeVerification(accessToken, birthDate, stepUp = {}) {
|
|
120
|
+
return this.call('POST', '/auth/age-verification', { birthDate, ...stepUp }, { token: accessToken });
|
|
115
121
|
}
|
|
116
122
|
/** Cached 5 min; a failed refetch serves the cached answer. */
|
|
117
123
|
async getAuthMethods() {
|
package/dist/esm/core/types.d.ts
CHANGED
|
@@ -20,6 +20,12 @@ export interface UserJwtPayload extends CommonClaims {
|
|
|
20
20
|
role: string;
|
|
21
21
|
permissions: string[];
|
|
22
22
|
sessionId?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Present (always `true`) only while the app has a minimum age and the account hasn't cleared
|
|
25
|
+
* it — an OAuth signup that hasn't answered `completeAgeVerification`. Absent on every other
|
|
26
|
+
* token. Recomputed at each issuance: refresh after the screen.
|
|
27
|
+
*/
|
|
28
|
+
ageVerificationRequired?: true;
|
|
23
29
|
}
|
|
24
30
|
/** A machine token from `POST /auth/client`. Discriminated by `type`. */
|
|
25
31
|
export interface ServiceClientJwtPayload extends CommonClaims {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heyatom/bastion-client",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Consumer SDK for the Bastion identity provider: JWKS verification, service-client auth, audit writes, NestJS guards",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andrea Tombolato <hey@heyatom.dev> (https://heyatom.dev)",
|