@dloizides/auth-client 3.0.0 → 3.2.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/CHANGELOG.md +40 -0
- package/dist/{AuthClient-D95OMajD.d.ts → AuthClient-Cv7btBX0.d.ts} +1 -1
- package/dist/{AuthClient-BGr8L03W.d.mts → AuthClient-D8Ul-aGa.d.mts} +1 -1
- package/dist/index.d.mts +76 -3
- package/dist/index.d.ts +76 -3
- package/dist/index.js +59 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +59 -1
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.d.ts +1 -1
- package/package.json +124 -124
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.2.0 (2026-05-22)
|
|
4
|
+
|
|
5
|
+
Additive release for Phase 3d of the unified-auth plan — event-scoped PIN
|
|
6
|
+
login. Extends `BffAuthClient` with the browser-facing PIN call so the new
|
|
7
|
+
`<PinForm>` in `@dloizides/auth-web` has a same-origin client. No breaking
|
|
8
|
+
changes.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `BffAuthClient.pinLogin({ pin, eventExternalId })` → `POST /bff/pin/login`.
|
|
13
|
+
The BFF runs the event-scoped PIN direct-grant against Keycloak server-side
|
|
14
|
+
(the `(event, pin)` pair resolves to the staff member's KC account + their
|
|
15
|
+
event-scoped role) and sets the httpOnly session cookie. Returns the
|
|
16
|
+
sanitised `BffUser`, exactly like `login` / `verifyOtp`. Throws on a non-2xx
|
|
17
|
+
(`401` for a bad / expired / locked-out PIN or an unknown event, `501` when
|
|
18
|
+
PIN login is not an enabled method). Carries the `X-BFF-Csrf` header like
|
|
19
|
+
every other state-changing call. No `username` / `password` ever leaves the
|
|
20
|
+
browser.
|
|
21
|
+
- Type: `BffPinLoginRequest`.
|
|
22
|
+
|
|
23
|
+
## 3.1.0 (2026-05-22)
|
|
24
|
+
|
|
25
|
+
Additive release for Phase 2d of the unified-auth plan — email-OTP. Extends
|
|
26
|
+
`BffAuthClient` with the two browser-facing OTP calls so the new `<OtpForm>` in
|
|
27
|
+
`@dloizides/auth-web` has a same-origin client. No breaking changes.
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- `BffAuthClient.requestOtp({ identifier })` → `POST /bff/otp/request`. The BFF
|
|
32
|
+
proxies to TenantService, which emails a short-TTL code. The endpoint is
|
|
33
|
+
anti-enumeration (a `200` is the normal path), so the method **returns** the
|
|
34
|
+
relayed `{ success, expiresIn, code }` body — the UI uses `expiresIn` for a
|
|
35
|
+
countdown. It still throws on a non-2xx (`501` OTP not enabled, `502` upstream
|
|
36
|
+
down). Carries the `X-BFF-Csrf` header like every other state-changing call.
|
|
37
|
+
- `BffAuthClient.verifyOtp({ username, otp })` → `POST /bff/otp/verify`. The BFF
|
|
38
|
+
runs the OTP direct-grant against Keycloak server-side and sets the httpOnly
|
|
39
|
+
session cookie. Returns the sanitised `BffUser`, exactly like `login`. Throws
|
|
40
|
+
on a non-2xx (e.g. `401` for a bad / expired code).
|
|
41
|
+
- Types: `BffOtpRequestRequest`, `BffOtpVerifyRequest`, `BffOtpRequestResult`.
|
|
42
|
+
|
|
3
43
|
## 3.0.0 (2026-05-19)
|
|
4
44
|
|
|
5
45
|
Major release for Phase 2 of the identity-hardening initiative. Adds the
|
|
@@ -457,4 +457,4 @@ declare class AuthClient {
|
|
|
457
457
|
private resolveScope;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
export { AuthApiClient as A, type DirectKcOptions as D, type ForgotPasswordRequest as F, type InactivityStore as I, type LoginOptions as L, type OtpLoginRequest as O, type PasswordLoginRequest as P, type
|
|
460
|
+
export { AuthApiClient as A, type DirectKcOptions as D, type ForgotPasswordRequest as F, type InactivityStore as I, type LoginOptions as L, type OtpLoginRequest as O, type PasswordLoginRequest as P, type RawAuthLoginResponse as R, type TokenStorage as T, type AuthApiClientOptions as a, AuthClient as b, type AuthClientCollaborators as c, type AuthClientConfig as d, type AuthClientFromIssuerInput as e, AuthEventEmitter as f, type AuthEventListener as g, type AuthEventName as h, type AuthEventUnsubscribe as i, type AuthSessionInfo as j, type AuthTokens as k, InactivityTracker as l, type InactivityTrackerOptions as m, type LogoutOptions as n, type RefreshFn as o, RefreshInterceptor as p, type RefreshInterceptorOptions as q, type ResetPasswordRequest as r };
|
|
@@ -457,4 +457,4 @@ declare class AuthClient {
|
|
|
457
457
|
private resolveScope;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
export { AuthApiClient as A, type DirectKcOptions as D, type ForgotPasswordRequest as F, type InactivityStore as I, type LoginOptions as L, type OtpLoginRequest as O, type PasswordLoginRequest as P, type
|
|
460
|
+
export { AuthApiClient as A, type DirectKcOptions as D, type ForgotPasswordRequest as F, type InactivityStore as I, type LoginOptions as L, type OtpLoginRequest as O, type PasswordLoginRequest as P, type RawAuthLoginResponse as R, type TokenStorage as T, type AuthApiClientOptions as a, AuthClient as b, type AuthClientCollaborators as c, type AuthClientConfig as d, type AuthClientFromIssuerInput as e, AuthEventEmitter as f, type AuthEventListener as g, type AuthEventName as h, type AuthEventUnsubscribe as i, type AuthSessionInfo as j, type AuthTokens as k, InactivityTracker as l, type InactivityTrackerOptions as m, type LogoutOptions as n, type RefreshFn as o, RefreshInterceptor as p, type RefreshInterceptorOptions as q, type ResetPasswordRequest as r };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TokenStorage,
|
|
2
|
-
export { A as AuthApiClient,
|
|
1
|
+
import { T as TokenStorage, k as AuthTokens } from './AuthClient-D8Ul-aGa.mjs';
|
|
2
|
+
export { A as AuthApiClient, a as AuthApiClientOptions, b as AuthClient, c as AuthClientCollaborators, d as AuthClientConfig, e as AuthClientFromIssuerInput, f as AuthEventEmitter, g as AuthEventListener, h as AuthEventName, i as AuthEventUnsubscribe, j as AuthSessionInfo, D as DirectKcOptions, F as ForgotPasswordRequest, I as InactivityStore, l as InactivityTracker, m as InactivityTrackerOptions, L as LoginOptions, n as LogoutOptions, O as OtpLoginRequest, P as PasswordLoginRequest, R as RawAuthLoginResponse, o as RefreshFn, p as RefreshInterceptor, q as RefreshInterceptorOptions, r as ResetPasswordRequest } from './AuthClient-D8Ul-aGa.mjs';
|
|
3
3
|
export { ExchangeAuthorizationCodeInput, FetchDiscoveryDocumentInput, OidcDiscoveryDocument, PkcePair, RefreshAccessTokenInput, clearDiscoveryCache, deriveCodeChallenge, exchangeAuthorizationCode, fetchDiscoveryDocument, generateCodeVerifier, generatePkcePair, refreshAccessToken } from './oidc/index.mjs';
|
|
4
4
|
import { H as HttpClient, R as RawTokenResponse, T as TokenResponse } from './TokenResponse-CY1CaU2l.mjs';
|
|
5
5
|
export { a as HttpRequest, b as HttpResponse, c as createFetchHttpClient } from './TokenResponse-CY1CaU2l.mjs';
|
|
@@ -342,6 +342,51 @@ interface BffResetPasswordRequest {
|
|
|
342
342
|
token: string;
|
|
343
343
|
newPassword: string;
|
|
344
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Payload for `POST /bff/otp/request` — the BFF proxies it to TenantService,
|
|
347
|
+
* which generates a short-TTL code and emails it.
|
|
348
|
+
*/
|
|
349
|
+
interface BffOtpRequestRequest {
|
|
350
|
+
/** The email address (or username) the one-time code is sent to. */
|
|
351
|
+
identifier: string;
|
|
352
|
+
}
|
|
353
|
+
/** Payload for `POST /bff/otp/verify` — the BFF exchanges it for a session. */
|
|
354
|
+
interface BffOtpVerifyRequest {
|
|
355
|
+
/** The email / username the code was requested for. */
|
|
356
|
+
username: string;
|
|
357
|
+
/** The one-time code the user entered. */
|
|
358
|
+
otp: string;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Payload for `POST /bff/pin/login` — the BFF exchanges an event-scoped PIN
|
|
362
|
+
* for a session.
|
|
363
|
+
*
|
|
364
|
+
* The `(event, pin)` pair alone identifies the staff member: no `username` /
|
|
365
|
+
* `password` ever leaves the browser. A PIN entered in an event's context
|
|
366
|
+
* grants that staff member their event-scoped role for that event only
|
|
367
|
+
* (the unified-auth plan §4.4 — event-scoped, per-individual PINs).
|
|
368
|
+
*/
|
|
369
|
+
interface BffPinLoginRequest {
|
|
370
|
+
/** The numeric PIN the staff member entered. */
|
|
371
|
+
pin: string;
|
|
372
|
+
/** External id of the event the PIN is scoped to (supplied by the page/route). */
|
|
373
|
+
eventExternalId: string;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* The body `POST /bff/otp/request` relays from TenantService.
|
|
377
|
+
*
|
|
378
|
+
* Anti-enumeration: the shape is identical whether or not the identifier is
|
|
379
|
+
* registered. `code` is non-null only outside production (a dev convenience);
|
|
380
|
+
* the UI must never depend on it being present.
|
|
381
|
+
*/
|
|
382
|
+
interface BffOtpRequestResult {
|
|
383
|
+
/** Always `true` on a relayed 200 — the request was accepted. */
|
|
384
|
+
success: boolean;
|
|
385
|
+
/** Seconds until the emitted code expires — drives a countdown in the UI. */
|
|
386
|
+
expiresIn: number;
|
|
387
|
+
/** The code itself, non-production only; `null` (or absent) in production. */
|
|
388
|
+
code: string | null;
|
|
389
|
+
}
|
|
345
390
|
/**
|
|
346
391
|
* The user object returned by `GET /bff/me` and `POST /bff/login`. The BFF
|
|
347
392
|
* returns the sanitised KC claims under a `user` envelope and **never** a
|
|
@@ -411,6 +456,34 @@ declare class BffAuthClient {
|
|
|
411
456
|
* response (e.g. `400` for an invalid / expired token).
|
|
412
457
|
*/
|
|
413
458
|
resetPassword(request: BffResetPasswordRequest): Promise<void>;
|
|
459
|
+
/**
|
|
460
|
+
* `POST /bff/otp/request` — the BFF proxies to TenantService, which generates
|
|
461
|
+
* a short-TTL code and emails it.
|
|
462
|
+
*
|
|
463
|
+
* The endpoint is anti-enumeration: a `200` is the normal path whether or not
|
|
464
|
+
* the identifier is registered. This method therefore **returns** the relayed
|
|
465
|
+
* `{ success, expiresIn, code }` body (so the UI can show the expiry) rather
|
|
466
|
+
* than treating a 200 as opaque. It still throws on a non-2xx — a `501`
|
|
467
|
+
* (OTP not enabled) or `502` (upstream down) is a real failure to surface.
|
|
468
|
+
*/
|
|
469
|
+
requestOtp(request: BffOtpRequestRequest): Promise<BffOtpRequestResult>;
|
|
470
|
+
/**
|
|
471
|
+
* `POST /bff/otp/verify` — the BFF runs the OTP direct-grant against Keycloak
|
|
472
|
+
* server-side, stores the tokens in its Redis vault, and sets the httpOnly
|
|
473
|
+
* session cookie. Returns the sanitised user, exactly like `login`. Throws on
|
|
474
|
+
* a non-2xx (e.g. `401` for a bad / expired code).
|
|
475
|
+
*/
|
|
476
|
+
verifyOtp(request: BffOtpVerifyRequest): Promise<BffUser>;
|
|
477
|
+
/**
|
|
478
|
+
* `POST /bff/pin/login` — the BFF runs the event-scoped PIN direct-grant
|
|
479
|
+
* against Keycloak server-side (the `(event, pin)` pair resolves to the
|
|
480
|
+
* staff member's KC account + event-scoped role), stores the tokens in its
|
|
481
|
+
* Redis vault, and sets the httpOnly session cookie. Returns the sanitised
|
|
482
|
+
* user, exactly like `login` / `verifyOtp`. Throws on a non-2xx — `401` for
|
|
483
|
+
* a bad / expired / locked-out PIN or an unknown event, `501` when PIN login
|
|
484
|
+
* is not an enabled method for this BFF.
|
|
485
|
+
*/
|
|
486
|
+
pinLogin(request: BffPinLoginRequest): Promise<BffUser>;
|
|
414
487
|
/**
|
|
415
488
|
* Shared POST for every state-changing `/bff/*` call: same-origin, cookie
|
|
416
489
|
* included, `X-BFF-Csrf` header attached. Throws a labelled error on non-2xx.
|
|
@@ -591,4 +664,4 @@ declare function normalizeTokenResponse(raw: RawTokenResponse): TokenResponse;
|
|
|
591
664
|
*/
|
|
592
665
|
declare function tokenResponseToAuthTokens(response: TokenResponse, now?: number): AuthTokens;
|
|
593
666
|
|
|
594
|
-
export { AuthTokens, type AuthorizationCodeBodyInput, type AuthorizationResponseLike, type AuthorizationUrlInput, BffAuthClient, type BffAuthClientOptions, type BffForgotPasswordRequest, type BffLoginRequest, type BffRegisterRequest, type BffResetPasswordRequest, type BffUser, type BiometricFlagStore, BiometricGate, type BiometricGateLike, type BiometricGateOptions, BrowserStorageTokenStorage, type BrowserStorageTokenStorageOptions, CookieTokenStorage, HttpClient, InMemoryTokenStorage, KeycloakRoles, type KeycloakUserInfo, type LocalAuthLike, type NormalizedUser, RawTokenResponse, type RefreshTokenBodyInput, type SecureStoreLike, SecureStoreTokenStorage, type SecureStoreTokenStorageOptions, type StorageLike, TokenResponse, TokenStorage, buildAuthorizationCodeBody, buildAuthorizationEndpoint, buildAuthorizationUrl, buildIssuerUrl, buildLogoutEndpoint, buildRefreshTokenBody, buildTokenEndpoint, buildUserInfoEndpoint, computeExpiresAt, decodeJwt, extractAuthCode, isKeycloakRole, isTokenExpired, normalizeKeycloakUser, normalizeTokenResponse, parseBaseUrlFromIssuer, parseRealmFromIssuer, tokenResponseToAuthTokens };
|
|
667
|
+
export { AuthTokens, type AuthorizationCodeBodyInput, type AuthorizationResponseLike, type AuthorizationUrlInput, BffAuthClient, type BffAuthClientOptions, type BffForgotPasswordRequest, type BffLoginRequest, type BffOtpRequestRequest, type BffOtpRequestResult, type BffOtpVerifyRequest, type BffPinLoginRequest, type BffRegisterRequest, type BffResetPasswordRequest, type BffUser, type BiometricFlagStore, BiometricGate, type BiometricGateLike, type BiometricGateOptions, BrowserStorageTokenStorage, type BrowserStorageTokenStorageOptions, CookieTokenStorage, HttpClient, InMemoryTokenStorage, KeycloakRoles, type KeycloakUserInfo, type LocalAuthLike, type NormalizedUser, RawTokenResponse, type RefreshTokenBodyInput, type SecureStoreLike, SecureStoreTokenStorage, type SecureStoreTokenStorageOptions, type StorageLike, TokenResponse, TokenStorage, buildAuthorizationCodeBody, buildAuthorizationEndpoint, buildAuthorizationUrl, buildIssuerUrl, buildLogoutEndpoint, buildRefreshTokenBody, buildTokenEndpoint, buildUserInfoEndpoint, computeExpiresAt, decodeJwt, extractAuthCode, isKeycloakRole, isTokenExpired, normalizeKeycloakUser, normalizeTokenResponse, parseBaseUrlFromIssuer, parseRealmFromIssuer, tokenResponseToAuthTokens };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TokenStorage,
|
|
2
|
-
export { A as AuthApiClient,
|
|
1
|
+
import { T as TokenStorage, k as AuthTokens } from './AuthClient-Cv7btBX0.js';
|
|
2
|
+
export { A as AuthApiClient, a as AuthApiClientOptions, b as AuthClient, c as AuthClientCollaborators, d as AuthClientConfig, e as AuthClientFromIssuerInput, f as AuthEventEmitter, g as AuthEventListener, h as AuthEventName, i as AuthEventUnsubscribe, j as AuthSessionInfo, D as DirectKcOptions, F as ForgotPasswordRequest, I as InactivityStore, l as InactivityTracker, m as InactivityTrackerOptions, L as LoginOptions, n as LogoutOptions, O as OtpLoginRequest, P as PasswordLoginRequest, R as RawAuthLoginResponse, o as RefreshFn, p as RefreshInterceptor, q as RefreshInterceptorOptions, r as ResetPasswordRequest } from './AuthClient-Cv7btBX0.js';
|
|
3
3
|
export { ExchangeAuthorizationCodeInput, FetchDiscoveryDocumentInput, OidcDiscoveryDocument, PkcePair, RefreshAccessTokenInput, clearDiscoveryCache, deriveCodeChallenge, exchangeAuthorizationCode, fetchDiscoveryDocument, generateCodeVerifier, generatePkcePair, refreshAccessToken } from './oidc/index.js';
|
|
4
4
|
import { H as HttpClient, R as RawTokenResponse, T as TokenResponse } from './TokenResponse-CY1CaU2l.js';
|
|
5
5
|
export { a as HttpRequest, b as HttpResponse, c as createFetchHttpClient } from './TokenResponse-CY1CaU2l.js';
|
|
@@ -342,6 +342,51 @@ interface BffResetPasswordRequest {
|
|
|
342
342
|
token: string;
|
|
343
343
|
newPassword: string;
|
|
344
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Payload for `POST /bff/otp/request` — the BFF proxies it to TenantService,
|
|
347
|
+
* which generates a short-TTL code and emails it.
|
|
348
|
+
*/
|
|
349
|
+
interface BffOtpRequestRequest {
|
|
350
|
+
/** The email address (or username) the one-time code is sent to. */
|
|
351
|
+
identifier: string;
|
|
352
|
+
}
|
|
353
|
+
/** Payload for `POST /bff/otp/verify` — the BFF exchanges it for a session. */
|
|
354
|
+
interface BffOtpVerifyRequest {
|
|
355
|
+
/** The email / username the code was requested for. */
|
|
356
|
+
username: string;
|
|
357
|
+
/** The one-time code the user entered. */
|
|
358
|
+
otp: string;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Payload for `POST /bff/pin/login` — the BFF exchanges an event-scoped PIN
|
|
362
|
+
* for a session.
|
|
363
|
+
*
|
|
364
|
+
* The `(event, pin)` pair alone identifies the staff member: no `username` /
|
|
365
|
+
* `password` ever leaves the browser. A PIN entered in an event's context
|
|
366
|
+
* grants that staff member their event-scoped role for that event only
|
|
367
|
+
* (the unified-auth plan §4.4 — event-scoped, per-individual PINs).
|
|
368
|
+
*/
|
|
369
|
+
interface BffPinLoginRequest {
|
|
370
|
+
/** The numeric PIN the staff member entered. */
|
|
371
|
+
pin: string;
|
|
372
|
+
/** External id of the event the PIN is scoped to (supplied by the page/route). */
|
|
373
|
+
eventExternalId: string;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* The body `POST /bff/otp/request` relays from TenantService.
|
|
377
|
+
*
|
|
378
|
+
* Anti-enumeration: the shape is identical whether or not the identifier is
|
|
379
|
+
* registered. `code` is non-null only outside production (a dev convenience);
|
|
380
|
+
* the UI must never depend on it being present.
|
|
381
|
+
*/
|
|
382
|
+
interface BffOtpRequestResult {
|
|
383
|
+
/** Always `true` on a relayed 200 — the request was accepted. */
|
|
384
|
+
success: boolean;
|
|
385
|
+
/** Seconds until the emitted code expires — drives a countdown in the UI. */
|
|
386
|
+
expiresIn: number;
|
|
387
|
+
/** The code itself, non-production only; `null` (or absent) in production. */
|
|
388
|
+
code: string | null;
|
|
389
|
+
}
|
|
345
390
|
/**
|
|
346
391
|
* The user object returned by `GET /bff/me` and `POST /bff/login`. The BFF
|
|
347
392
|
* returns the sanitised KC claims under a `user` envelope and **never** a
|
|
@@ -411,6 +456,34 @@ declare class BffAuthClient {
|
|
|
411
456
|
* response (e.g. `400` for an invalid / expired token).
|
|
412
457
|
*/
|
|
413
458
|
resetPassword(request: BffResetPasswordRequest): Promise<void>;
|
|
459
|
+
/**
|
|
460
|
+
* `POST /bff/otp/request` — the BFF proxies to TenantService, which generates
|
|
461
|
+
* a short-TTL code and emails it.
|
|
462
|
+
*
|
|
463
|
+
* The endpoint is anti-enumeration: a `200` is the normal path whether or not
|
|
464
|
+
* the identifier is registered. This method therefore **returns** the relayed
|
|
465
|
+
* `{ success, expiresIn, code }` body (so the UI can show the expiry) rather
|
|
466
|
+
* than treating a 200 as opaque. It still throws on a non-2xx — a `501`
|
|
467
|
+
* (OTP not enabled) or `502` (upstream down) is a real failure to surface.
|
|
468
|
+
*/
|
|
469
|
+
requestOtp(request: BffOtpRequestRequest): Promise<BffOtpRequestResult>;
|
|
470
|
+
/**
|
|
471
|
+
* `POST /bff/otp/verify` — the BFF runs the OTP direct-grant against Keycloak
|
|
472
|
+
* server-side, stores the tokens in its Redis vault, and sets the httpOnly
|
|
473
|
+
* session cookie. Returns the sanitised user, exactly like `login`. Throws on
|
|
474
|
+
* a non-2xx (e.g. `401` for a bad / expired code).
|
|
475
|
+
*/
|
|
476
|
+
verifyOtp(request: BffOtpVerifyRequest): Promise<BffUser>;
|
|
477
|
+
/**
|
|
478
|
+
* `POST /bff/pin/login` — the BFF runs the event-scoped PIN direct-grant
|
|
479
|
+
* against Keycloak server-side (the `(event, pin)` pair resolves to the
|
|
480
|
+
* staff member's KC account + event-scoped role), stores the tokens in its
|
|
481
|
+
* Redis vault, and sets the httpOnly session cookie. Returns the sanitised
|
|
482
|
+
* user, exactly like `login` / `verifyOtp`. Throws on a non-2xx — `401` for
|
|
483
|
+
* a bad / expired / locked-out PIN or an unknown event, `501` when PIN login
|
|
484
|
+
* is not an enabled method for this BFF.
|
|
485
|
+
*/
|
|
486
|
+
pinLogin(request: BffPinLoginRequest): Promise<BffUser>;
|
|
414
487
|
/**
|
|
415
488
|
* Shared POST for every state-changing `/bff/*` call: same-origin, cookie
|
|
416
489
|
* included, `X-BFF-Csrf` header attached. Throws a labelled error on non-2xx.
|
|
@@ -591,4 +664,4 @@ declare function normalizeTokenResponse(raw: RawTokenResponse): TokenResponse;
|
|
|
591
664
|
*/
|
|
592
665
|
declare function tokenResponseToAuthTokens(response: TokenResponse, now?: number): AuthTokens;
|
|
593
666
|
|
|
594
|
-
export { AuthTokens, type AuthorizationCodeBodyInput, type AuthorizationResponseLike, type AuthorizationUrlInput, BffAuthClient, type BffAuthClientOptions, type BffForgotPasswordRequest, type BffLoginRequest, type BffRegisterRequest, type BffResetPasswordRequest, type BffUser, type BiometricFlagStore, BiometricGate, type BiometricGateLike, type BiometricGateOptions, BrowserStorageTokenStorage, type BrowserStorageTokenStorageOptions, CookieTokenStorage, HttpClient, InMemoryTokenStorage, KeycloakRoles, type KeycloakUserInfo, type LocalAuthLike, type NormalizedUser, RawTokenResponse, type RefreshTokenBodyInput, type SecureStoreLike, SecureStoreTokenStorage, type SecureStoreTokenStorageOptions, type StorageLike, TokenResponse, TokenStorage, buildAuthorizationCodeBody, buildAuthorizationEndpoint, buildAuthorizationUrl, buildIssuerUrl, buildLogoutEndpoint, buildRefreshTokenBody, buildTokenEndpoint, buildUserInfoEndpoint, computeExpiresAt, decodeJwt, extractAuthCode, isKeycloakRole, isTokenExpired, normalizeKeycloakUser, normalizeTokenResponse, parseBaseUrlFromIssuer, parseRealmFromIssuer, tokenResponseToAuthTokens };
|
|
667
|
+
export { AuthTokens, type AuthorizationCodeBodyInput, type AuthorizationResponseLike, type AuthorizationUrlInput, BffAuthClient, type BffAuthClientOptions, type BffForgotPasswordRequest, type BffLoginRequest, type BffOtpRequestRequest, type BffOtpRequestResult, type BffOtpVerifyRequest, type BffPinLoginRequest, type BffRegisterRequest, type BffResetPasswordRequest, type BffUser, type BiometricFlagStore, BiometricGate, type BiometricGateLike, type BiometricGateOptions, BrowserStorageTokenStorage, type BrowserStorageTokenStorageOptions, CookieTokenStorage, HttpClient, InMemoryTokenStorage, KeycloakRoles, type KeycloakUserInfo, type LocalAuthLike, type NormalizedUser, RawTokenResponse, type RefreshTokenBodyInput, type SecureStoreLike, SecureStoreTokenStorage, type SecureStoreTokenStorageOptions, type StorageLike, TokenResponse, TokenStorage, buildAuthorizationCodeBody, buildAuthorizationEndpoint, buildAuthorizationUrl, buildIssuerUrl, buildLogoutEndpoint, buildRefreshTokenBody, buildTokenEndpoint, buildUserInfoEndpoint, computeExpiresAt, decodeJwt, extractAuthCode, isKeycloakRole, isTokenExpired, normalizeKeycloakUser, normalizeTokenResponse, parseBaseUrlFromIssuer, parseRealmFromIssuer, tokenResponseToAuthTokens };
|
package/dist/index.js
CHANGED
|
@@ -1069,7 +1069,10 @@ var ENDPOINTS = {
|
|
|
1069
1069
|
me: "/bff/me",
|
|
1070
1070
|
register: "/bff/register",
|
|
1071
1071
|
forgotPassword: "/bff/forgot-password",
|
|
1072
|
-
resetPassword: "/bff/reset-password"
|
|
1072
|
+
resetPassword: "/bff/reset-password",
|
|
1073
|
+
otpRequest: "/bff/otp/request",
|
|
1074
|
+
otpVerify: "/bff/otp/verify",
|
|
1075
|
+
pinLogin: "/bff/pin/login"
|
|
1073
1076
|
};
|
|
1074
1077
|
function isRecord(value) {
|
|
1075
1078
|
return typeof value === "object" && value !== null;
|
|
@@ -1081,6 +1084,16 @@ function extractUser(data) {
|
|
|
1081
1084
|
const envelope = data;
|
|
1082
1085
|
return isRecord(envelope.user) ? envelope.user : null;
|
|
1083
1086
|
}
|
|
1087
|
+
function toOtpRequestResult(data) {
|
|
1088
|
+
if (!isRecord(data)) {
|
|
1089
|
+
return { success: true, expiresIn: 0, code: null };
|
|
1090
|
+
}
|
|
1091
|
+
return {
|
|
1092
|
+
success: typeof data.success === "boolean" ? data.success : true,
|
|
1093
|
+
expiresIn: typeof data.expiresIn === "number" ? data.expiresIn : 0,
|
|
1094
|
+
code: typeof data.code === "string" ? data.code : null
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1084
1097
|
var BffAuthClient = class {
|
|
1085
1098
|
constructor(options) {
|
|
1086
1099
|
this.http = options.http;
|
|
@@ -1150,6 +1163,51 @@ var BffAuthClient = class {
|
|
|
1150
1163
|
async resetPassword(request) {
|
|
1151
1164
|
await this.postState(ENDPOINTS.resetPassword, request, "reset-password");
|
|
1152
1165
|
}
|
|
1166
|
+
/**
|
|
1167
|
+
* `POST /bff/otp/request` — the BFF proxies to TenantService, which generates
|
|
1168
|
+
* a short-TTL code and emails it.
|
|
1169
|
+
*
|
|
1170
|
+
* The endpoint is anti-enumeration: a `200` is the normal path whether or not
|
|
1171
|
+
* the identifier is registered. This method therefore **returns** the relayed
|
|
1172
|
+
* `{ success, expiresIn, code }` body (so the UI can show the expiry) rather
|
|
1173
|
+
* than treating a 200 as opaque. It still throws on a non-2xx — a `501`
|
|
1174
|
+
* (OTP not enabled) or `502` (upstream down) is a real failure to surface.
|
|
1175
|
+
*/
|
|
1176
|
+
async requestOtp(request) {
|
|
1177
|
+
const data = await this.postState(ENDPOINTS.otpRequest, request, "otp-request");
|
|
1178
|
+
return toOtpRequestResult(data);
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* `POST /bff/otp/verify` — the BFF runs the OTP direct-grant against Keycloak
|
|
1182
|
+
* server-side, stores the tokens in its Redis vault, and sets the httpOnly
|
|
1183
|
+
* session cookie. Returns the sanitised user, exactly like `login`. Throws on
|
|
1184
|
+
* a non-2xx (e.g. `401` for a bad / expired code).
|
|
1185
|
+
*/
|
|
1186
|
+
async verifyOtp(request) {
|
|
1187
|
+
const data = await this.postState(ENDPOINTS.otpVerify, request, "otp-verify");
|
|
1188
|
+
const user = extractUser(data);
|
|
1189
|
+
if (user === null) {
|
|
1190
|
+
throw new Error("otp-verify: BFF response missing user");
|
|
1191
|
+
}
|
|
1192
|
+
return user;
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* `POST /bff/pin/login` — the BFF runs the event-scoped PIN direct-grant
|
|
1196
|
+
* against Keycloak server-side (the `(event, pin)` pair resolves to the
|
|
1197
|
+
* staff member's KC account + event-scoped role), stores the tokens in its
|
|
1198
|
+
* Redis vault, and sets the httpOnly session cookie. Returns the sanitised
|
|
1199
|
+
* user, exactly like `login` / `verifyOtp`. Throws on a non-2xx — `401` for
|
|
1200
|
+
* a bad / expired / locked-out PIN or an unknown event, `501` when PIN login
|
|
1201
|
+
* is not an enabled method for this BFF.
|
|
1202
|
+
*/
|
|
1203
|
+
async pinLogin(request) {
|
|
1204
|
+
const data = await this.postState(ENDPOINTS.pinLogin, request, "pin-login");
|
|
1205
|
+
const user = extractUser(data);
|
|
1206
|
+
if (user === null) {
|
|
1207
|
+
throw new Error("pin-login: BFF response missing user");
|
|
1208
|
+
}
|
|
1209
|
+
return user;
|
|
1210
|
+
}
|
|
1153
1211
|
/**
|
|
1154
1212
|
* Shared POST for every state-changing `/bff/*` call: same-origin, cookie
|
|
1155
1213
|
* included, `X-BFF-Csrf` header attached. Throws a labelled error on non-2xx.
|