squarefi-bff-api-module 1.36.19 → 1.36.21
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/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { squarefi_bff_api_client } from './api';
|
|
2
2
|
export * from './utils/apiClientFactory';
|
|
3
|
-
export { setAccessTokenProvider,
|
|
3
|
+
export { setAccessTokenProvider, setOnReverificationRequired, setOnUnauthorized, type AccessTokenProvider, type ResolveTokenOptions, type ReverificationHandler, type ReverificationMeta, type UnauthorizedHandler, } from './utils/accessTokenProvider';
|
|
4
4
|
export * from './utils/tokensFactory';
|
|
5
5
|
export * from './utils/fileStorage';
|
|
6
6
|
export * from './constants';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { squarefi_bff_api_client } from './api';
|
|
2
2
|
export * from './utils/apiClientFactory';
|
|
3
|
-
export { setAccessTokenProvider,
|
|
3
|
+
export { setAccessTokenProvider, setOnReverificationRequired, setOnUnauthorized, } from './utils/accessTokenProvider';
|
|
4
4
|
export * from './utils/tokensFactory';
|
|
5
5
|
export * from './utils/fileStorage';
|
|
6
6
|
export * from './constants';
|
|
@@ -4,7 +4,14 @@ export type ResolveTokenOptions = {
|
|
|
4
4
|
};
|
|
5
5
|
export type AccessTokenProvider = (options?: ResolveTokenOptions) => Promise<string | null | undefined>;
|
|
6
6
|
export type UnauthorizedHandler = () => void;
|
|
7
|
-
|
|
7
|
+
/** Details the backend attaches to a step-up (2FA reverification) rejection. */
|
|
8
|
+
export type ReverificationMeta = Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Handler that performs a step-up reverification (e.g. re-entering an already-enrolled second
|
|
11
|
+
* factor). Resolves `true` once the user has re-verified so the original request can be retried,
|
|
12
|
+
* or `false` if the reverification was cancelled or failed.
|
|
13
|
+
*/
|
|
14
|
+
export type ReverificationHandler = (meta: ReverificationMeta) => Promise<boolean>;
|
|
8
15
|
/**
|
|
9
16
|
* Register an external source of the access token (e.g. Clerk `getToken`).
|
|
10
17
|
* When set, the API clients stop reading tokens from localStorage and delegate
|
|
@@ -18,14 +25,15 @@ export declare const setAccessTokenProvider: (provider: AccessTokenProvider | nu
|
|
|
18
25
|
*/
|
|
19
26
|
export declare const setOnUnauthorized: (handler: UnauthorizedHandler | null) => void;
|
|
20
27
|
/**
|
|
21
|
-
* Register a
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
28
|
+
* Register a handler invoked when the backend rejects a request because a step-up 2FA
|
|
29
|
+
* reverification is required (HTTP `403` with a `two_factor_reverification_required` code). The
|
|
30
|
+
* handler drives the provider-specific re-verification (e.g. Clerk) and resolves `true` on success
|
|
31
|
+
* so the API client retries the original request once. Pass `null` to unregister.
|
|
25
32
|
*/
|
|
26
|
-
export declare const
|
|
33
|
+
export declare const setOnReverificationRequired: (handler: ReverificationHandler | null) => void;
|
|
27
34
|
/** Whether an external token provider is active (Clerk mode). */
|
|
28
35
|
export declare const isExternalAuthMode: () => boolean;
|
|
29
36
|
export declare const resolveAccessToken: (options?: ResolveTokenOptions) => Promise<string | null>;
|
|
30
37
|
export declare const triggerUnauthorized: () => void;
|
|
31
|
-
|
|
38
|
+
/** Invokes the registered reverification handler; resolves `false` when none is registered. */
|
|
39
|
+
export declare const triggerReverification: (meta: ReverificationMeta) => Promise<boolean>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getFromLocalStorage } from './storage';
|
|
2
2
|
let accessTokenProvider = null;
|
|
3
3
|
let unauthorizedHandler = null;
|
|
4
|
-
let
|
|
4
|
+
let reverificationHandler = null;
|
|
5
5
|
let inFlightRefresh = null;
|
|
6
6
|
/**
|
|
7
7
|
* Register an external source of the access token (e.g. Clerk `getToken`).
|
|
@@ -20,13 +20,13 @@ export const setOnUnauthorized = (handler) => {
|
|
|
20
20
|
unauthorizedHandler = handler;
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
|
-
* Register a
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Register a handler invoked when the backend rejects a request because a step-up 2FA
|
|
24
|
+
* reverification is required (HTTP `403` with a `two_factor_reverification_required` code). The
|
|
25
|
+
* handler drives the provider-specific re-verification (e.g. Clerk) and resolves `true` on success
|
|
26
|
+
* so the API client retries the original request once. Pass `null` to unregister.
|
|
27
27
|
*/
|
|
28
|
-
export const
|
|
29
|
-
|
|
28
|
+
export const setOnReverificationRequired = (handler) => {
|
|
29
|
+
reverificationHandler = handler;
|
|
30
30
|
};
|
|
31
31
|
/** Whether an external token provider is active (Clerk mode). */
|
|
32
32
|
export const isExternalAuthMode = () => accessTokenProvider !== null;
|
|
@@ -58,6 +58,5 @@ export const resolveAccessToken = async (options) => {
|
|
|
58
58
|
export const triggerUnauthorized = () => {
|
|
59
59
|
unauthorizedHandler?.();
|
|
60
60
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
61
|
+
/** Invokes the registered reverification handler; resolves `false` when none is registered. */
|
|
62
|
+
export const triggerReverification = (meta) => reverificationHandler ? reverificationHandler(meta) : Promise.resolve(false);
|
|
@@ -3,11 +3,11 @@ import { isTMA } from '@telegram-apps/sdk-react';
|
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { telegramSignUpPath, telegramSignInPath, refreshTokenPath } from '../api/auth';
|
|
5
5
|
import { AppEnviroment, ResponseStatus } from '../constants';
|
|
6
|
-
import { isExternalAuthMode, resolveAccessToken,
|
|
6
|
+
import { isExternalAuthMode, resolveAccessToken, triggerReverification, triggerUnauthorized, } from './accessTokenProvider';
|
|
7
7
|
import { deleteTokens, getTokens, refreshTokens } from './tokensFactory';
|
|
8
8
|
// eslint-disable-next-line no-constant-condition
|
|
9
|
-
// Backend signals that a
|
|
10
|
-
const
|
|
9
|
+
// Backend signals that a sensitive request needs a fresh second-factor verification with this code.
|
|
10
|
+
const TWO_FACTOR_REVERIFICATION_CODE = 'two_factor_reverification_required';
|
|
11
11
|
const apiV1BaseURL = process.env.API_URL ?? 'ENV variable API_URL is not defined';
|
|
12
12
|
const apiV2BaseURL = process.env.API_V2_URL ?? 'ENV variable API_V2_URL is not defined';
|
|
13
13
|
const apiTOTPBaseURL = process.env.API_TOTP_URL ?? 'ENV variable API_TOTP_URL is not defined';
|
|
@@ -43,10 +43,22 @@ export const createApiClient = ({ baseURL, isBearerToken, tenantId }) => {
|
|
|
43
43
|
if (typeof window === 'undefined') {
|
|
44
44
|
return Promise.reject(error);
|
|
45
45
|
}
|
|
46
|
+
// Step-up 2FA: the backend rejects a sensitive request until the user re-verifies their
|
|
47
|
+
// second factor. Hand off to the consumer's reverification handler and retry once on success.
|
|
46
48
|
if (error?.response?.status === ResponseStatus.FORBIDDEN &&
|
|
47
|
-
error?.response?.data?.code ===
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
error?.response?.data?.code === TWO_FACTOR_REVERIFICATION_CODE &&
|
|
50
|
+
!error?.response?.config.context?.isRetryRequest) {
|
|
51
|
+
const { response, config: failedRequestConfig } = error;
|
|
52
|
+
return triggerReverification(response.data).then((didReverify) => {
|
|
53
|
+
if (!didReverify) {
|
|
54
|
+
return Promise.reject(error);
|
|
55
|
+
}
|
|
56
|
+
failedRequestConfig.context = {
|
|
57
|
+
...failedRequestConfig.context,
|
|
58
|
+
isRetryRequest: true,
|
|
59
|
+
};
|
|
60
|
+
return instance(failedRequestConfig);
|
|
61
|
+
});
|
|
50
62
|
}
|
|
51
63
|
if (error?.response?.status === ResponseStatus.UNAUTHORIZED &&
|
|
52
64
|
!error?.response?.config.context?.bypassUnauthorizedHandler) {
|
|
@@ -189,9 +201,6 @@ export const createFetchApiClient = ({ baseURL, isBearerToken, tenantId }) => {
|
|
|
189
201
|
let errorMessage = `HTTP error! status: ${response.status}`;
|
|
190
202
|
try {
|
|
191
203
|
const errorData = await response.json();
|
|
192
|
-
if (response.status === ResponseStatus.FORBIDDEN && errorData?.code === TWO_FACTOR_REQUIRED_ERROR_CODE) {
|
|
193
|
-
triggerTwoFactorRequired();
|
|
194
|
-
}
|
|
195
204
|
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
196
205
|
}
|
|
197
206
|
catch {
|