@metamask-previews/profile-sync-controller 26.0.0-preview-dabf9bd8 → 26.0.0-preview-f4ab1511
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 +8 -0
- package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs +57 -3
- package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.cts +4 -0
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.mts +4 -0
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.mjs +35 -4
- package/dist/sdk/authentication-jwt-bearer/flow-srp.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.cjs +71 -10
- package/dist/sdk/authentication-jwt-bearer/services.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.mjs +72 -11
- package/dist/sdk/authentication-jwt-bearer/services.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/utils/time.cjs +17 -0
- package/dist/sdk/authentication-jwt-bearer/utils/time.cjs.map +1 -0
- package/dist/sdk/authentication-jwt-bearer/utils/time.d.cts +8 -0
- package/dist/sdk/authentication-jwt-bearer/utils/time.d.cts.map +1 -0
- package/dist/sdk/authentication-jwt-bearer/utils/time.d.mts +8 -0
- package/dist/sdk/authentication-jwt-bearer/utils/time.d.mts.map +1 -0
- package/dist/sdk/authentication-jwt-bearer/utils/time.mjs +13 -0
- package/dist/sdk/authentication-jwt-bearer/utils/time.mjs.map +1 -0
- package/dist/sdk/constants.cjs +7 -0
- package/dist/sdk/constants.cjs.map +1 -0
- package/dist/sdk/constants.d.cts +4 -0
- package/dist/sdk/constants.d.cts.map +1 -0
- package/dist/sdk/constants.d.mts +4 -0
- package/dist/sdk/constants.d.mts.map +1 -0
- package/dist/sdk/constants.mjs +4 -0
- package/dist/sdk/constants.mjs.map +1 -0
- package/dist/sdk/errors.cjs +24 -1
- package/dist/sdk/errors.cjs.map +1 -1
- package/dist/sdk/errors.d.cts +12 -0
- package/dist/sdk/errors.d.cts.map +1 -1
- package/dist/sdk/errors.d.mts +12 -0
- package/dist/sdk/errors.d.mts.map +1 -1
- package/dist/sdk/errors.mjs +22 -0
- package/dist/sdk/errors.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Add rate limit (429) handling with automatic retry in authentication flow ([#6993](https://github.com/MetaMask/core/pull/6993))
|
|
13
|
+
- Update authentication services to throw `RateLimitedError` when encountering 429 responses.
|
|
14
|
+
- Improve Authentication errors by adding the HTTP code in error messages.
|
|
15
|
+
- Add rate limit retry logic to `SRPJwtBearerAuth` with configurable cooldown via `rateLimitRetry.cooldownDefaultMs` option (defaults to 10 seconds).
|
|
16
|
+
- Non-429 errors are thrown immediately without retry, delegating retry logic to consumers.
|
|
17
|
+
|
|
10
18
|
## [26.0.0]
|
|
11
19
|
|
|
12
20
|
### Changed
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
26
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
27
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
@@ -10,10 +33,11 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
33
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
34
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
35
|
};
|
|
13
|
-
var _SRPJwtBearerAuth_instances, _SRPJwtBearerAuth_config, _SRPJwtBearerAuth_options, _SRPJwtBearerAuth_metametrics, _SRPJwtBearerAuth_ongoingLogins, _SRPJwtBearerAuth_customProvider, _SRPJwtBearerAuth_getAuthSession, _SRPJwtBearerAuth_login, _SRPJwtBearerAuth_performLogin, _SRPJwtBearerAuth_deferredLogin, _SRPJwtBearerAuth_createSrpLoginRawMessage;
|
|
36
|
+
var _SRPJwtBearerAuth_instances, _SRPJwtBearerAuth_config, _SRPJwtBearerAuth_options, _SRPJwtBearerAuth_metametrics, _SRPJwtBearerAuth_ongoingLogins, _SRPJwtBearerAuth_cooldownDefaultMs, _SRPJwtBearerAuth_maxLoginRetries, _SRPJwtBearerAuth_customProvider, _SRPJwtBearerAuth_getAuthSession, _SRPJwtBearerAuth_login, _SRPJwtBearerAuth_performLogin, _SRPJwtBearerAuth_deferredLogin, _SRPJwtBearerAuth_loginWithRetry, _SRPJwtBearerAuth_createSrpLoginRawMessage;
|
|
14
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
38
|
exports.SRPJwtBearerAuth = void 0;
|
|
16
39
|
const services_1 = require("./services.cjs");
|
|
40
|
+
const timeUtils = __importStar(require("./utils/time.cjs"));
|
|
17
41
|
const errors_1 = require("../errors.cjs");
|
|
18
42
|
const eip_6963_metamask_provider_1 = require("../utils/eip-6963-metamask-provider.cjs");
|
|
19
43
|
const messaging_signing_snap_requests_1 = require("../utils/messaging-signing-snap-requests.cjs");
|
|
@@ -44,6 +68,10 @@ class SRPJwtBearerAuth {
|
|
|
44
68
|
_SRPJwtBearerAuth_metametrics.set(this, void 0);
|
|
45
69
|
// Map to store ongoing login promises by entropySourceId
|
|
46
70
|
_SRPJwtBearerAuth_ongoingLogins.set(this, new Map());
|
|
71
|
+
// Default cooldown when 429 has no Retry-After header
|
|
72
|
+
_SRPJwtBearerAuth_cooldownDefaultMs.set(this, void 0);
|
|
73
|
+
// Maximum number of login retries on rate limit errors
|
|
74
|
+
_SRPJwtBearerAuth_maxLoginRetries.set(this, void 0);
|
|
47
75
|
_SRPJwtBearerAuth_customProvider.set(this, void 0);
|
|
48
76
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_config, config, "f");
|
|
49
77
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_customProvider, options.customProvider, "f");
|
|
@@ -53,6 +81,9 @@ class SRPJwtBearerAuth {
|
|
|
53
81
|
getDefaultEIP6963SigningOptions(__classPrivateFieldGet(this, _SRPJwtBearerAuth_customProvider, "f")),
|
|
54
82
|
}, "f");
|
|
55
83
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_metametrics, options.metametrics, "f");
|
|
84
|
+
// Apply rate limit retry config if provided
|
|
85
|
+
__classPrivateFieldSet(this, _SRPJwtBearerAuth_cooldownDefaultMs, options.rateLimitRetry?.cooldownDefaultMs ?? 10000, "f");
|
|
86
|
+
__classPrivateFieldSet(this, _SRPJwtBearerAuth_maxLoginRetries, options.rateLimitRetry?.maxLoginRetries ?? 1, "f");
|
|
56
87
|
}
|
|
57
88
|
setCustomProvider(provider) {
|
|
58
89
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_customProvider, provider, "f");
|
|
@@ -100,7 +131,7 @@ class SRPJwtBearerAuth {
|
|
|
100
131
|
}
|
|
101
132
|
}
|
|
102
133
|
exports.SRPJwtBearerAuth = SRPJwtBearerAuth;
|
|
103
|
-
_SRPJwtBearerAuth_config = new WeakMap(), _SRPJwtBearerAuth_options = new WeakMap(), _SRPJwtBearerAuth_metametrics = new WeakMap(), _SRPJwtBearerAuth_ongoingLogins = new WeakMap(), _SRPJwtBearerAuth_customProvider = new WeakMap(), _SRPJwtBearerAuth_instances = new WeakSet(), _SRPJwtBearerAuth_getAuthSession =
|
|
134
|
+
_SRPJwtBearerAuth_config = new WeakMap(), _SRPJwtBearerAuth_options = new WeakMap(), _SRPJwtBearerAuth_metametrics = new WeakMap(), _SRPJwtBearerAuth_ongoingLogins = new WeakMap(), _SRPJwtBearerAuth_cooldownDefaultMs = new WeakMap(), _SRPJwtBearerAuth_maxLoginRetries = new WeakMap(), _SRPJwtBearerAuth_customProvider = new WeakMap(), _SRPJwtBearerAuth_instances = new WeakSet(), _SRPJwtBearerAuth_getAuthSession =
|
|
104
135
|
// convert expiresIn from seconds to milliseconds and use 90% of expiresIn
|
|
105
136
|
async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
106
137
|
const auth = await __classPrivateFieldGet(this, _SRPJwtBearerAuth_options, "f").storage.getLoginResponse(entropySourceId);
|
|
@@ -143,7 +174,7 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
143
174
|
return existingLogin;
|
|
144
175
|
}
|
|
145
176
|
// Create a new login promise
|
|
146
|
-
const loginPromise = __classPrivateFieldGet(this, _SRPJwtBearerAuth_instances, "m",
|
|
177
|
+
const loginPromise = __classPrivateFieldGet(this, _SRPJwtBearerAuth_instances, "m", _SRPJwtBearerAuth_loginWithRetry).call(this, entropySourceId);
|
|
147
178
|
// Store the promise in the map
|
|
148
179
|
__classPrivateFieldGet(this, _SRPJwtBearerAuth_ongoingLogins, "f").set(loginKey, loginPromise);
|
|
149
180
|
try {
|
|
@@ -155,6 +186,29 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
155
186
|
// Always clean up the ongoing login promise when done
|
|
156
187
|
__classPrivateFieldGet(this, _SRPJwtBearerAuth_ongoingLogins, "f").delete(loginKey);
|
|
157
188
|
}
|
|
189
|
+
}, _SRPJwtBearerAuth_loginWithRetry = async function _SRPJwtBearerAuth_loginWithRetry(entropySourceId) {
|
|
190
|
+
// Allow max attempts: initial + maxLoginRetries on 429
|
|
191
|
+
for (let attempt = 0; attempt < 1 + __classPrivateFieldGet(this, _SRPJwtBearerAuth_maxLoginRetries, "f"); attempt += 1) {
|
|
192
|
+
try {
|
|
193
|
+
return await __classPrivateFieldGet(this, _SRPJwtBearerAuth_instances, "m", _SRPJwtBearerAuth_performLogin).call(this, entropySourceId);
|
|
194
|
+
}
|
|
195
|
+
catch (e) {
|
|
196
|
+
// Only retry on rate-limit (429) errors
|
|
197
|
+
if (!errors_1.RateLimitedError.isRateLimitError(e)) {
|
|
198
|
+
throw e;
|
|
199
|
+
}
|
|
200
|
+
// If we've exhausted attempts, rethrow
|
|
201
|
+
if (attempt >= __classPrivateFieldGet(this, _SRPJwtBearerAuth_maxLoginRetries, "f")) {
|
|
202
|
+
throw e;
|
|
203
|
+
}
|
|
204
|
+
// Wait for Retry-After or default cooldown
|
|
205
|
+
const waitMs = e.retryAfterMs ?? __classPrivateFieldGet(this, _SRPJwtBearerAuth_cooldownDefaultMs, "f");
|
|
206
|
+
await timeUtils.delay(waitMs);
|
|
207
|
+
// Loop continues to retry
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Should never reach here due to loop logic, but TypeScript needs a return
|
|
211
|
+
throw new Error('Unexpected: login loop exhausted without result');
|
|
158
212
|
}, _SRPJwtBearerAuth_createSrpLoginRawMessage = function _SRPJwtBearerAuth_createSrpLoginRawMessage(nonce, publicKey) {
|
|
159
213
|
return `metamask:${nonce}:${publicKey}`;
|
|
160
214
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Eip1193Provider } from 'ethers';\n\nimport {\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthSigningOptions,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { ValidationError } from '../errors';\nimport { getMetaMaskProviderEIP6963 } from '../utils/eip-6963-metamask-provider';\nimport {\n MESSAGE_SIGNING_SNAP,\n assertMessageStartsWithMetamask,\n connectSnap,\n isSnapConnected,\n} from '../utils/messaging-signing-snap-requests';\nimport { validateLoginResponse } from '../utils/validate-login-response';\n\ntype JwtBearerAuth_SRP_Options = {\n storage: AuthStorageOptions;\n signing?: AuthSigningOptions;\n};\n\nconst getDefaultEIP6963Provider = async () => {\n const provider = await getMetaMaskProviderEIP6963();\n if (!provider) {\n throw new ValidationError('No MetaMask wallet connected');\n }\n return provider;\n};\n\nconst getDefaultEIP6963SigningOptions = (\n customProvider?: Eip1193Provider,\n): AuthSigningOptions => ({\n getIdentifier: async (entropySourceId?: string): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n return await MESSAGE_SIGNING_SNAP.getPublicKey(provider, entropySourceId);\n },\n signMessage: async (\n message: string,\n entropySourceId?: string,\n ): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n assertMessageStartsWithMetamask(message);\n return await MESSAGE_SIGNING_SNAP.signMessage(\n provider,\n message,\n entropySourceId,\n );\n },\n});\n\nexport class SRPJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: Required<JwtBearerAuth_SRP_Options>;\n\n readonly #metametrics?: MetaMetricsAuth;\n\n // Map to store ongoing login promises by entropySourceId\n readonly #ongoingLogins = new Map<string, Promise<LoginResponse>>();\n\n #customProvider?: Eip1193Provider;\n\n constructor(\n config: AuthConfig & { type: AuthType.SRP },\n options: JwtBearerAuth_SRP_Options & {\n customProvider?: Eip1193Provider;\n metametrics?: MetaMetricsAuth;\n },\n ) {\n this.#config = config;\n this.#customProvider = options.customProvider;\n this.#options = {\n storage: options.storage,\n signing:\n options.signing ??\n getDefaultEIP6963SigningOptions(this.#customProvider),\n };\n this.#metametrics = options.metametrics;\n }\n\n setCustomProvider(provider: Eip1193Provider) {\n this.#customProvider = provider;\n this.#options.signing = getDefaultEIP6963SigningOptions(provider);\n }\n\n // TODO: might be easier to keep entropySourceId as a class param and use multiple SRPJwtBearerAuth instances where needed\n async getAccessToken(entropySourceId?: string): Promise<string> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.token.accessToken;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.token.accessToken;\n }\n\n async getUserProfile(entropySourceId?: string): Promise<UserProfile> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.profile;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.profile;\n }\n\n async getIdentifier(entropySourceId?: string): Promise<string> {\n return await this.#options.signing.getIdentifier(entropySourceId);\n }\n\n async getUserProfileLineage(): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken();\n return await getUserProfileLineage(this.#config.env, accessToken);\n }\n\n async signMessage(\n message: string,\n entropySourceId?: string,\n ): Promise<string> {\n return await this.#options.signing.signMessage(message, entropySourceId);\n }\n\n async isSnapConnected(): Promise<boolean> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n if (!provider) {\n return false;\n }\n\n const isConnected = await isSnapConnected(provider);\n return isConnected;\n }\n\n async connectSnap(): Promise<string> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n\n const res = await connectSnap(provider);\n return res;\n }\n\n // convert expiresIn from seconds to milliseconds and use 90% of expiresIn\n async #getAuthSession(\n entropySourceId?: string,\n ): Promise<LoginResponse | null> {\n const auth = await this.#options.storage.getLoginResponse(entropySourceId);\n if (!validateLoginResponse(auth)) {\n return null;\n }\n\n const currentTime = Date.now();\n const sessionAge = currentTime - auth.token.obtainedAt;\n const refreshThreshold = auth.token.expiresIn * 1000 * 0.9;\n\n if (sessionAge < refreshThreshold) {\n return auth;\n }\n return null;\n }\n\n async #login(entropySourceId?: string): Promise<LoginResponse> {\n // Use a deferred login to avoid race conditions\n return await this.#deferredLogin(entropySourceId);\n }\n\n async #performLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Nonce\n const publicKey = await this.getIdentifier(entropySourceId);\n const nonceRes = await getNonce(publicKey, this.#config.env);\n\n const rawMessage = this.#createSrpLoginRawMessage(\n nonceRes.nonce,\n publicKey,\n );\n const signature = await this.signMessage(rawMessage, entropySourceId);\n\n // Authenticate\n const authResponse = await authenticate(\n rawMessage,\n signature,\n this.#config.type,\n this.#config.env,\n this.#metametrics,\n );\n\n // Authorize\n const tokenResponse = await authorizeOIDC(\n authResponse.token,\n this.#config.env,\n this.#config.platform,\n );\n\n // Save\n const result: LoginResponse = {\n profile: authResponse.profile,\n token: tokenResponse,\n };\n\n await this.#options.storage.setLoginResponse(result, entropySourceId);\n\n return result;\n }\n\n async #deferredLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Use a key that accounts for undefined entropySourceId\n const loginKey = entropySourceId ?? '__default__';\n\n // Check if there's already an ongoing login for this entropySourceId\n const existingLogin = this.#ongoingLogins.get(loginKey);\n if (existingLogin) {\n return existingLogin;\n }\n\n // Create a new login promise\n const loginPromise = this.#performLogin(entropySourceId);\n\n // Store the promise in the map\n this.#ongoingLogins.set(loginKey, loginPromise);\n\n try {\n // Wait for the login to complete\n const result = await loginPromise;\n return result;\n } finally {\n // Always clean up the ongoing login promise when done\n this.#ongoingLogins.delete(loginKey);\n }\n }\n\n #createSrpLoginRawMessage(\n nonce: string,\n publicKey: string,\n ): `metamask:${string}:${string}` {\n return `metamask:${nonce}:${publicKey}` as const;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"flow-srp.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Eip1193Provider } from 'ethers';\n\nimport {\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthSigningOptions,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport * as timeUtils from './utils/time';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { ValidationError, RateLimitedError } from '../errors';\nimport { getMetaMaskProviderEIP6963 } from '../utils/eip-6963-metamask-provider';\nimport {\n MESSAGE_SIGNING_SNAP,\n assertMessageStartsWithMetamask,\n connectSnap,\n isSnapConnected,\n} from '../utils/messaging-signing-snap-requests';\nimport { validateLoginResponse } from '../utils/validate-login-response';\n\ntype JwtBearerAuth_SRP_Options = {\n storage: AuthStorageOptions;\n signing?: AuthSigningOptions;\n rateLimitRetry?: {\n cooldownDefaultMs?: number; // default cooldown when 429 has no Retry-After\n maxLoginRetries?: number; // maximum number of login retries on rate limit\n };\n};\n\nconst getDefaultEIP6963Provider = async () => {\n const provider = await getMetaMaskProviderEIP6963();\n if (!provider) {\n throw new ValidationError('No MetaMask wallet connected');\n }\n return provider;\n};\n\nconst getDefaultEIP6963SigningOptions = (\n customProvider?: Eip1193Provider,\n): AuthSigningOptions => ({\n getIdentifier: async (entropySourceId?: string): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n return await MESSAGE_SIGNING_SNAP.getPublicKey(provider, entropySourceId);\n },\n signMessage: async (\n message: string,\n entropySourceId?: string,\n ): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n assertMessageStartsWithMetamask(message);\n return await MESSAGE_SIGNING_SNAP.signMessage(\n provider,\n message,\n entropySourceId,\n );\n },\n});\n\nexport class SRPJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: {\n storage: AuthStorageOptions;\n signing: AuthSigningOptions;\n };\n\n readonly #metametrics?: MetaMetricsAuth;\n\n // Map to store ongoing login promises by entropySourceId\n readonly #ongoingLogins = new Map<string, Promise<LoginResponse>>();\n\n // Default cooldown when 429 has no Retry-After header\n readonly #cooldownDefaultMs: number;\n\n // Maximum number of login retries on rate limit errors\n readonly #maxLoginRetries: number;\n\n #customProvider?: Eip1193Provider;\n\n constructor(\n config: AuthConfig & { type: AuthType.SRP },\n options: JwtBearerAuth_SRP_Options & {\n customProvider?: Eip1193Provider;\n metametrics?: MetaMetricsAuth;\n },\n ) {\n this.#config = config;\n this.#customProvider = options.customProvider;\n this.#options = {\n storage: options.storage,\n signing:\n options.signing ??\n getDefaultEIP6963SigningOptions(this.#customProvider),\n };\n this.#metametrics = options.metametrics;\n\n // Apply rate limit retry config if provided\n this.#cooldownDefaultMs =\n options.rateLimitRetry?.cooldownDefaultMs ?? 10000;\n this.#maxLoginRetries = options.rateLimitRetry?.maxLoginRetries ?? 1;\n }\n\n setCustomProvider(provider: Eip1193Provider) {\n this.#customProvider = provider;\n this.#options.signing = getDefaultEIP6963SigningOptions(provider);\n }\n\n // TODO: might be easier to keep entropySourceId as a class param and use multiple SRPJwtBearerAuth instances where needed\n async getAccessToken(entropySourceId?: string): Promise<string> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.token.accessToken;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.token.accessToken;\n }\n\n async getUserProfile(entropySourceId?: string): Promise<UserProfile> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.profile;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.profile;\n }\n\n async getIdentifier(entropySourceId?: string): Promise<string> {\n return await this.#options.signing.getIdentifier(entropySourceId);\n }\n\n async getUserProfileLineage(): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken();\n return await getUserProfileLineage(this.#config.env, accessToken);\n }\n\n async signMessage(\n message: string,\n entropySourceId?: string,\n ): Promise<string> {\n return await this.#options.signing.signMessage(message, entropySourceId);\n }\n\n async isSnapConnected(): Promise<boolean> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n if (!provider) {\n return false;\n }\n\n const isConnected = await isSnapConnected(provider);\n return isConnected;\n }\n\n async connectSnap(): Promise<string> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n\n const res = await connectSnap(provider);\n return res;\n }\n\n // convert expiresIn from seconds to milliseconds and use 90% of expiresIn\n async #getAuthSession(\n entropySourceId?: string,\n ): Promise<LoginResponse | null> {\n const auth = await this.#options.storage.getLoginResponse(entropySourceId);\n if (!validateLoginResponse(auth)) {\n return null;\n }\n\n const currentTime = Date.now();\n const sessionAge = currentTime - auth.token.obtainedAt;\n const refreshThreshold = auth.token.expiresIn * 1000 * 0.9;\n\n if (sessionAge < refreshThreshold) {\n return auth;\n }\n return null;\n }\n\n async #login(entropySourceId?: string): Promise<LoginResponse> {\n // Use a deferred login to avoid race conditions\n return await this.#deferredLogin(entropySourceId);\n }\n\n async #performLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Nonce\n const publicKey = await this.getIdentifier(entropySourceId);\n const nonceRes = await getNonce(publicKey, this.#config.env);\n\n const rawMessage = this.#createSrpLoginRawMessage(\n nonceRes.nonce,\n publicKey,\n );\n const signature = await this.signMessage(rawMessage, entropySourceId);\n\n // Authenticate\n const authResponse = await authenticate(\n rawMessage,\n signature,\n this.#config.type,\n this.#config.env,\n this.#metametrics,\n );\n\n // Authorize\n const tokenResponse = await authorizeOIDC(\n authResponse.token,\n this.#config.env,\n this.#config.platform,\n );\n\n // Save\n const result: LoginResponse = {\n profile: authResponse.profile,\n token: tokenResponse,\n };\n\n await this.#options.storage.setLoginResponse(result, entropySourceId);\n\n return result;\n }\n\n async #deferredLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Use a key that accounts for undefined entropySourceId\n const loginKey = entropySourceId ?? '__default__';\n\n // Check if there's already an ongoing login for this entropySourceId\n const existingLogin = this.#ongoingLogins.get(loginKey);\n if (existingLogin) {\n return existingLogin;\n }\n\n // Create a new login promise\n const loginPromise = this.#loginWithRetry(entropySourceId);\n\n // Store the promise in the map\n this.#ongoingLogins.set(loginKey, loginPromise);\n\n try {\n // Wait for the login to complete\n const result = await loginPromise;\n return result;\n } finally {\n // Always clean up the ongoing login promise when done\n this.#ongoingLogins.delete(loginKey);\n }\n }\n\n async #loginWithRetry(entropySourceId?: string): Promise<LoginResponse> {\n // Allow max attempts: initial + maxLoginRetries on 429\n for (let attempt = 0; attempt < 1 + this.#maxLoginRetries; attempt += 1) {\n try {\n return await this.#performLogin(entropySourceId);\n } catch (e) {\n // Only retry on rate-limit (429) errors\n if (!RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n\n // If we've exhausted attempts, rethrow\n if (attempt >= this.#maxLoginRetries) {\n throw e;\n }\n\n // Wait for Retry-After or default cooldown\n const waitMs = e.retryAfterMs ?? this.#cooldownDefaultMs;\n await timeUtils.delay(waitMs);\n\n // Loop continues to retry\n }\n }\n\n // Should never reach here due to loop logic, but TypeScript needs a return\n throw new Error('Unexpected: login loop exhausted without result');\n }\n\n #createSrpLoginRawMessage(\n nonce: string,\n publicKey: string,\n ): `metamask:${string}:${string}` {\n return `metamask:${nonce}:${publicKey}` as const;\n }\n}\n"]}
|
|
@@ -4,6 +4,10 @@ import type { MetaMetricsAuth } from "../../shared/types/services.cjs";
|
|
|
4
4
|
type JwtBearerAuth_SRP_Options = {
|
|
5
5
|
storage: AuthStorageOptions;
|
|
6
6
|
signing?: AuthSigningOptions;
|
|
7
|
+
rateLimitRetry?: {
|
|
8
|
+
cooldownDefaultMs?: number;
|
|
9
|
+
maxLoginRetries?: number;
|
|
10
|
+
};
|
|
7
11
|
};
|
|
8
12
|
export declare class SRPJwtBearerAuth implements IBaseAuth {
|
|
9
13
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;AAQ9C,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;
|
|
1
|
+
{"version":3,"file":"flow-srp.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;AAQ9C,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AAEjB,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAWnE,KAAK,yBAAyB,GAAG;IAC/B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,cAAc,CAAC,EAAE;QACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH,CAAC;AA+BF,qBAAa,gBAAiB,YAAW,SAAS;;gBAsB9C,MAAM,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAA;KAAE,EAC3C,OAAO,EAAE,yBAAyB,GAAG;QACnC,cAAc,CAAC,EAAE,eAAe,CAAC;QACjC,WAAW,CAAC,EAAE,eAAe,CAAC;KAC/B;IAkBH,iBAAiB,CAAC,QAAQ,EAAE,eAAe;IAMrC,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUzD,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAU9D,aAAa,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxD,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKpD,WAAW,CACf,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC;IAIZ,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAWnC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;CAkIrC"}
|
|
@@ -4,6 +4,10 @@ import type { MetaMetricsAuth } from "../../shared/types/services.mjs";
|
|
|
4
4
|
type JwtBearerAuth_SRP_Options = {
|
|
5
5
|
storage: AuthStorageOptions;
|
|
6
6
|
signing?: AuthSigningOptions;
|
|
7
|
+
rateLimitRetry?: {
|
|
8
|
+
cooldownDefaultMs?: number;
|
|
9
|
+
maxLoginRetries?: number;
|
|
10
|
+
};
|
|
7
11
|
};
|
|
8
12
|
export declare class SRPJwtBearerAuth implements IBaseAuth {
|
|
9
13
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;AAQ9C,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;
|
|
1
|
+
{"version":3,"file":"flow-srp.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;AAQ9C,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AAEjB,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAWnE,KAAK,yBAAyB,GAAG;IAC/B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,cAAc,CAAC,EAAE;QACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH,CAAC;AA+BF,qBAAa,gBAAiB,YAAW,SAAS;;gBAsB9C,MAAM,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAA;KAAE,EAC3C,OAAO,EAAE,yBAAyB,GAAG;QACnC,cAAc,CAAC,EAAE,eAAe,CAAC;QACjC,WAAW,CAAC,EAAE,eAAe,CAAC;KAC/B;IAkBH,iBAAiB,CAAC,QAAQ,EAAE,eAAe;IAMrC,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUzD,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAU9D,aAAa,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxD,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKpD,WAAW,CACf,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC;IAIZ,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAWnC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;CAkIrC"}
|
|
@@ -9,9 +9,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _SRPJwtBearerAuth_instances, _SRPJwtBearerAuth_config, _SRPJwtBearerAuth_options, _SRPJwtBearerAuth_metametrics, _SRPJwtBearerAuth_ongoingLogins, _SRPJwtBearerAuth_customProvider, _SRPJwtBearerAuth_getAuthSession, _SRPJwtBearerAuth_login, _SRPJwtBearerAuth_performLogin, _SRPJwtBearerAuth_deferredLogin, _SRPJwtBearerAuth_createSrpLoginRawMessage;
|
|
12
|
+
var _SRPJwtBearerAuth_instances, _SRPJwtBearerAuth_config, _SRPJwtBearerAuth_options, _SRPJwtBearerAuth_metametrics, _SRPJwtBearerAuth_ongoingLogins, _SRPJwtBearerAuth_cooldownDefaultMs, _SRPJwtBearerAuth_maxLoginRetries, _SRPJwtBearerAuth_customProvider, _SRPJwtBearerAuth_getAuthSession, _SRPJwtBearerAuth_login, _SRPJwtBearerAuth_performLogin, _SRPJwtBearerAuth_deferredLogin, _SRPJwtBearerAuth_loginWithRetry, _SRPJwtBearerAuth_createSrpLoginRawMessage;
|
|
13
13
|
import { authenticate, authorizeOIDC, getNonce, getUserProfileLineage } from "./services.mjs";
|
|
14
|
-
import
|
|
14
|
+
import * as timeUtils from "./utils/time.mjs";
|
|
15
|
+
import { ValidationError, RateLimitedError } from "../errors.mjs";
|
|
15
16
|
import { getMetaMaskProviderEIP6963 } from "../utils/eip-6963-metamask-provider.mjs";
|
|
16
17
|
import { MESSAGE_SIGNING_SNAP, assertMessageStartsWithMetamask, connectSnap, isSnapConnected } from "../utils/messaging-signing-snap-requests.mjs";
|
|
17
18
|
import { validateLoginResponse } from "../utils/validate-login-response.mjs";
|
|
@@ -41,6 +42,10 @@ export class SRPJwtBearerAuth {
|
|
|
41
42
|
_SRPJwtBearerAuth_metametrics.set(this, void 0);
|
|
42
43
|
// Map to store ongoing login promises by entropySourceId
|
|
43
44
|
_SRPJwtBearerAuth_ongoingLogins.set(this, new Map());
|
|
45
|
+
// Default cooldown when 429 has no Retry-After header
|
|
46
|
+
_SRPJwtBearerAuth_cooldownDefaultMs.set(this, void 0);
|
|
47
|
+
// Maximum number of login retries on rate limit errors
|
|
48
|
+
_SRPJwtBearerAuth_maxLoginRetries.set(this, void 0);
|
|
44
49
|
_SRPJwtBearerAuth_customProvider.set(this, void 0);
|
|
45
50
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_config, config, "f");
|
|
46
51
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_customProvider, options.customProvider, "f");
|
|
@@ -50,6 +55,9 @@ export class SRPJwtBearerAuth {
|
|
|
50
55
|
getDefaultEIP6963SigningOptions(__classPrivateFieldGet(this, _SRPJwtBearerAuth_customProvider, "f")),
|
|
51
56
|
}, "f");
|
|
52
57
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_metametrics, options.metametrics, "f");
|
|
58
|
+
// Apply rate limit retry config if provided
|
|
59
|
+
__classPrivateFieldSet(this, _SRPJwtBearerAuth_cooldownDefaultMs, options.rateLimitRetry?.cooldownDefaultMs ?? 10000, "f");
|
|
60
|
+
__classPrivateFieldSet(this, _SRPJwtBearerAuth_maxLoginRetries, options.rateLimitRetry?.maxLoginRetries ?? 1, "f");
|
|
53
61
|
}
|
|
54
62
|
setCustomProvider(provider) {
|
|
55
63
|
__classPrivateFieldSet(this, _SRPJwtBearerAuth_customProvider, provider, "f");
|
|
@@ -96,7 +104,7 @@ export class SRPJwtBearerAuth {
|
|
|
96
104
|
return res;
|
|
97
105
|
}
|
|
98
106
|
}
|
|
99
|
-
_SRPJwtBearerAuth_config = new WeakMap(), _SRPJwtBearerAuth_options = new WeakMap(), _SRPJwtBearerAuth_metametrics = new WeakMap(), _SRPJwtBearerAuth_ongoingLogins = new WeakMap(), _SRPJwtBearerAuth_customProvider = new WeakMap(), _SRPJwtBearerAuth_instances = new WeakSet(), _SRPJwtBearerAuth_getAuthSession =
|
|
107
|
+
_SRPJwtBearerAuth_config = new WeakMap(), _SRPJwtBearerAuth_options = new WeakMap(), _SRPJwtBearerAuth_metametrics = new WeakMap(), _SRPJwtBearerAuth_ongoingLogins = new WeakMap(), _SRPJwtBearerAuth_cooldownDefaultMs = new WeakMap(), _SRPJwtBearerAuth_maxLoginRetries = new WeakMap(), _SRPJwtBearerAuth_customProvider = new WeakMap(), _SRPJwtBearerAuth_instances = new WeakSet(), _SRPJwtBearerAuth_getAuthSession =
|
|
100
108
|
// convert expiresIn from seconds to milliseconds and use 90% of expiresIn
|
|
101
109
|
async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
102
110
|
const auth = await __classPrivateFieldGet(this, _SRPJwtBearerAuth_options, "f").storage.getLoginResponse(entropySourceId);
|
|
@@ -139,7 +147,7 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
139
147
|
return existingLogin;
|
|
140
148
|
}
|
|
141
149
|
// Create a new login promise
|
|
142
|
-
const loginPromise = __classPrivateFieldGet(this, _SRPJwtBearerAuth_instances, "m",
|
|
150
|
+
const loginPromise = __classPrivateFieldGet(this, _SRPJwtBearerAuth_instances, "m", _SRPJwtBearerAuth_loginWithRetry).call(this, entropySourceId);
|
|
143
151
|
// Store the promise in the map
|
|
144
152
|
__classPrivateFieldGet(this, _SRPJwtBearerAuth_ongoingLogins, "f").set(loginKey, loginPromise);
|
|
145
153
|
try {
|
|
@@ -151,6 +159,29 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
151
159
|
// Always clean up the ongoing login promise when done
|
|
152
160
|
__classPrivateFieldGet(this, _SRPJwtBearerAuth_ongoingLogins, "f").delete(loginKey);
|
|
153
161
|
}
|
|
162
|
+
}, _SRPJwtBearerAuth_loginWithRetry = async function _SRPJwtBearerAuth_loginWithRetry(entropySourceId) {
|
|
163
|
+
// Allow max attempts: initial + maxLoginRetries on 429
|
|
164
|
+
for (let attempt = 0; attempt < 1 + __classPrivateFieldGet(this, _SRPJwtBearerAuth_maxLoginRetries, "f"); attempt += 1) {
|
|
165
|
+
try {
|
|
166
|
+
return await __classPrivateFieldGet(this, _SRPJwtBearerAuth_instances, "m", _SRPJwtBearerAuth_performLogin).call(this, entropySourceId);
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
// Only retry on rate-limit (429) errors
|
|
170
|
+
if (!RateLimitedError.isRateLimitError(e)) {
|
|
171
|
+
throw e;
|
|
172
|
+
}
|
|
173
|
+
// If we've exhausted attempts, rethrow
|
|
174
|
+
if (attempt >= __classPrivateFieldGet(this, _SRPJwtBearerAuth_maxLoginRetries, "f")) {
|
|
175
|
+
throw e;
|
|
176
|
+
}
|
|
177
|
+
// Wait for Retry-After or default cooldown
|
|
178
|
+
const waitMs = e.retryAfterMs ?? __classPrivateFieldGet(this, _SRPJwtBearerAuth_cooldownDefaultMs, "f");
|
|
179
|
+
await timeUtils.delay(waitMs);
|
|
180
|
+
// Loop continues to retry
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Should never reach here due to loop logic, but TypeScript needs a return
|
|
184
|
+
throw new Error('Unexpected: login loop exhausted without result');
|
|
154
185
|
}, _SRPJwtBearerAuth_createSrpLoginRawMessage = function _SRPJwtBearerAuth_createSrpLoginRawMessage(nonce, publicKey) {
|
|
155
186
|
return `metamask:${nonce}:${publicKey}`;
|
|
156
187
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Eip1193Provider } from 'ethers';\n\nimport {\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthSigningOptions,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { ValidationError } from '../errors';\nimport { getMetaMaskProviderEIP6963 } from '../utils/eip-6963-metamask-provider';\nimport {\n MESSAGE_SIGNING_SNAP,\n assertMessageStartsWithMetamask,\n connectSnap,\n isSnapConnected,\n} from '../utils/messaging-signing-snap-requests';\nimport { validateLoginResponse } from '../utils/validate-login-response';\n\ntype JwtBearerAuth_SRP_Options = {\n storage: AuthStorageOptions;\n signing?: AuthSigningOptions;\n};\n\nconst getDefaultEIP6963Provider = async () => {\n const provider = await getMetaMaskProviderEIP6963();\n if (!provider) {\n throw new ValidationError('No MetaMask wallet connected');\n }\n return provider;\n};\n\nconst getDefaultEIP6963SigningOptions = (\n customProvider?: Eip1193Provider,\n): AuthSigningOptions => ({\n getIdentifier: async (entropySourceId?: string): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n return await MESSAGE_SIGNING_SNAP.getPublicKey(provider, entropySourceId);\n },\n signMessage: async (\n message: string,\n entropySourceId?: string,\n ): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n assertMessageStartsWithMetamask(message);\n return await MESSAGE_SIGNING_SNAP.signMessage(\n provider,\n message,\n entropySourceId,\n );\n },\n});\n\nexport class SRPJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: Required<JwtBearerAuth_SRP_Options>;\n\n readonly #metametrics?: MetaMetricsAuth;\n\n // Map to store ongoing login promises by entropySourceId\n readonly #ongoingLogins = new Map<string, Promise<LoginResponse>>();\n\n #customProvider?: Eip1193Provider;\n\n constructor(\n config: AuthConfig & { type: AuthType.SRP },\n options: JwtBearerAuth_SRP_Options & {\n customProvider?: Eip1193Provider;\n metametrics?: MetaMetricsAuth;\n },\n ) {\n this.#config = config;\n this.#customProvider = options.customProvider;\n this.#options = {\n storage: options.storage,\n signing:\n options.signing ??\n getDefaultEIP6963SigningOptions(this.#customProvider),\n };\n this.#metametrics = options.metametrics;\n }\n\n setCustomProvider(provider: Eip1193Provider) {\n this.#customProvider = provider;\n this.#options.signing = getDefaultEIP6963SigningOptions(provider);\n }\n\n // TODO: might be easier to keep entropySourceId as a class param and use multiple SRPJwtBearerAuth instances where needed\n async getAccessToken(entropySourceId?: string): Promise<string> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.token.accessToken;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.token.accessToken;\n }\n\n async getUserProfile(entropySourceId?: string): Promise<UserProfile> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.profile;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.profile;\n }\n\n async getIdentifier(entropySourceId?: string): Promise<string> {\n return await this.#options.signing.getIdentifier(entropySourceId);\n }\n\n async getUserProfileLineage(): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken();\n return await getUserProfileLineage(this.#config.env, accessToken);\n }\n\n async signMessage(\n message: string,\n entropySourceId?: string,\n ): Promise<string> {\n return await this.#options.signing.signMessage(message, entropySourceId);\n }\n\n async isSnapConnected(): Promise<boolean> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n if (!provider) {\n return false;\n }\n\n const isConnected = await isSnapConnected(provider);\n return isConnected;\n }\n\n async connectSnap(): Promise<string> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n\n const res = await connectSnap(provider);\n return res;\n }\n\n // convert expiresIn from seconds to milliseconds and use 90% of expiresIn\n async #getAuthSession(\n entropySourceId?: string,\n ): Promise<LoginResponse | null> {\n const auth = await this.#options.storage.getLoginResponse(entropySourceId);\n if (!validateLoginResponse(auth)) {\n return null;\n }\n\n const currentTime = Date.now();\n const sessionAge = currentTime - auth.token.obtainedAt;\n const refreshThreshold = auth.token.expiresIn * 1000 * 0.9;\n\n if (sessionAge < refreshThreshold) {\n return auth;\n }\n return null;\n }\n\n async #login(entropySourceId?: string): Promise<LoginResponse> {\n // Use a deferred login to avoid race conditions\n return await this.#deferredLogin(entropySourceId);\n }\n\n async #performLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Nonce\n const publicKey = await this.getIdentifier(entropySourceId);\n const nonceRes = await getNonce(publicKey, this.#config.env);\n\n const rawMessage = this.#createSrpLoginRawMessage(\n nonceRes.nonce,\n publicKey,\n );\n const signature = await this.signMessage(rawMessage, entropySourceId);\n\n // Authenticate\n const authResponse = await authenticate(\n rawMessage,\n signature,\n this.#config.type,\n this.#config.env,\n this.#metametrics,\n );\n\n // Authorize\n const tokenResponse = await authorizeOIDC(\n authResponse.token,\n this.#config.env,\n this.#config.platform,\n );\n\n // Save\n const result: LoginResponse = {\n profile: authResponse.profile,\n token: tokenResponse,\n };\n\n await this.#options.storage.setLoginResponse(result, entropySourceId);\n\n return result;\n }\n\n async #deferredLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Use a key that accounts for undefined entropySourceId\n const loginKey = entropySourceId ?? '__default__';\n\n // Check if there's already an ongoing login for this entropySourceId\n const existingLogin = this.#ongoingLogins.get(loginKey);\n if (existingLogin) {\n return existingLogin;\n }\n\n // Create a new login promise\n const loginPromise = this.#performLogin(entropySourceId);\n\n // Store the promise in the map\n this.#ongoingLogins.set(loginKey, loginPromise);\n\n try {\n // Wait for the login to complete\n const result = await loginPromise;\n return result;\n } finally {\n // Always clean up the ongoing login promise when done\n this.#ongoingLogins.delete(loginKey);\n }\n }\n\n #createSrpLoginRawMessage(\n nonce: string,\n publicKey: string,\n ): `metamask:${string}:${string}` {\n return `metamask:${nonce}:${publicKey}` as const;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"flow-srp.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,qBAAqB,EACtB,uBAAmB;AAWpB,OAAO,KAAK,SAAS,yBAAqB;AAE1C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,sBAAkB;AAC9D,OAAO,EAAE,0BAA0B,EAAE,gDAA4C;AACjF,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,WAAW,EACX,eAAe,EAChB,qDAAiD;AAClD,OAAO,EAAE,qBAAqB,EAAE,6CAAyC;AAWzE,MAAM,yBAAyB,GAAG,KAAK,IAAI,EAAE;IAC3C,MAAM,QAAQ,GAAG,MAAM,0BAA0B,EAAE,CAAC;IACpD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,eAAe,CAAC,8BAA8B,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,+BAA+B,GAAG,CACtC,cAAgC,EACZ,EAAE,CAAC,CAAC;IACxB,aAAa,EAAE,KAAK,EAAE,eAAwB,EAAmB,EAAE;QACjE,MAAM,QAAQ,GAAG,cAAc,IAAI,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC;QACvE,OAAO,MAAM,oBAAoB,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC5E,CAAC;IACD,WAAW,EAAE,KAAK,EAChB,OAAe,EACf,eAAwB,EACP,EAAE;QACnB,MAAM,QAAQ,GAAG,cAAc,IAAI,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC;QACvE,+BAA+B,CAAC,OAAO,CAAC,CAAC;QACzC,OAAO,MAAM,oBAAoB,CAAC,WAAW,CAC3C,QAAQ,EACR,OAAO,EACP,eAAe,CAChB,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,OAAO,gBAAgB;IAqB3B,YACE,MAA2C,EAC3C,OAGC;;QAzBM,2CAAoB;QAEpB,4CAGP;QAEO,gDAA+B;QAExC,yDAAyD;QAChD,0CAAiB,IAAI,GAAG,EAAkC,EAAC;QAEpE,sDAAsD;QAC7C,sDAA2B;QAEpC,uDAAuD;QAC9C,oDAAyB;QAElC,mDAAkC;QAShC,uBAAA,IAAI,4BAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,oCAAmB,OAAO,CAAC,cAAc,MAAA,CAAC;QAC9C,uBAAA,IAAI,6BAAY;YACd,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EACL,OAAO,CAAC,OAAO;gBACf,+BAA+B,CAAC,uBAAA,IAAI,wCAAgB,CAAC;SACxD,MAAA,CAAC;QACF,uBAAA,IAAI,iCAAgB,OAAO,CAAC,WAAW,MAAA,CAAC;QAExC,4CAA4C;QAC5C,uBAAA,IAAI,uCACF,OAAO,CAAC,cAAc,EAAE,iBAAiB,IAAI,KAAK,MAAA,CAAC;QACrD,uBAAA,IAAI,qCAAoB,OAAO,CAAC,cAAc,EAAE,eAAe,IAAI,CAAC,MAAA,CAAC;IACvE,CAAC;IAED,iBAAiB,CAAC,QAAyB;QACzC,uBAAA,IAAI,oCAAmB,QAAQ,MAAA,CAAC;QAChC,uBAAA,IAAI,iCAAS,CAAC,OAAO,GAAG,+BAA+B,CAAC,QAAQ,CAAC,CAAC;IACpE,CAAC;IAED,0HAA0H;IAC1H,KAAK,CAAC,cAAc,CAAC,eAAwB;QAC3C,MAAM,OAAO,GAAG,MAAM,uBAAA,IAAI,qEAAgB,MAApB,IAAI,EAAiB,eAAe,CAAC,CAAC;QAC5D,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC;QACnC,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,4DAAO,MAAX,IAAI,EAAQ,eAAe,CAAC,CAAC;QACzD,OAAO,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,eAAwB;QAC3C,MAAM,OAAO,GAAG,MAAM,uBAAA,IAAI,qEAAgB,MAApB,IAAI,EAAiB,eAAe,CAAC,CAAC;QAC5D,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC,OAAO,CAAC;QACzB,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,4DAAO,MAAX,IAAI,EAAQ,eAAe,CAAC,CAAC;QACzD,OAAO,aAAa,CAAC,OAAO,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,eAAwB;QAC1C,OAAO,MAAM,uBAAA,IAAI,iCAAS,CAAC,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAChD,OAAO,MAAM,qBAAqB,CAAC,uBAAA,IAAI,gCAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,WAAW,CACf,OAAe,EACf,eAAwB;QAExB,OAAO,MAAM,uBAAA,IAAI,iCAAS,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,QAAQ,GACZ,uBAAA,IAAI,wCAAgB,IAAI,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;QACpD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,QAAQ,GACZ,uBAAA,IAAI,wCAAgB,IAAI,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC;QAE9D,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;QACxC,OAAO,GAAG,CAAC;IACb,CAAC;CA4HF;;AA1HC,0EAA0E;AAC1E,KAAK,2CACH,eAAwB;IAExB,MAAM,IAAI,GAAG,MAAM,uBAAA,IAAI,iCAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAC3E,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;IACvD,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,GAAG,GAAG,CAAC;IAE3D,IAAI,UAAU,GAAG,gBAAgB,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,4BAED,KAAK,kCAAQ,eAAwB;IACnC,gDAAgD;IAChD,OAAO,MAAM,uBAAA,IAAI,oEAAe,MAAnB,IAAI,EAAgB,eAAe,CAAC,CAAC;AACpD,CAAC,mCAED,KAAK,yCAAe,eAAwB;IAC1C,QAAQ;IACR,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,uBAAA,IAAI,gCAAQ,CAAC,GAAG,CAAC,CAAC;IAE7D,MAAM,UAAU,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,EACrB,QAAQ,CAAC,KAAK,EACd,SAAS,CACV,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAEtE,eAAe;IACf,MAAM,YAAY,GAAG,MAAM,YAAY,CACrC,UAAU,EACV,SAAS,EACT,uBAAA,IAAI,gCAAQ,CAAC,IAAI,EACjB,uBAAA,IAAI,gCAAQ,CAAC,GAAG,EAChB,uBAAA,IAAI,qCAAa,CAClB,CAAC;IAEF,YAAY;IACZ,MAAM,aAAa,GAAG,MAAM,aAAa,CACvC,YAAY,CAAC,KAAK,EAClB,uBAAA,IAAI,gCAAQ,CAAC,GAAG,EAChB,uBAAA,IAAI,gCAAQ,CAAC,QAAQ,CACtB,CAAC;IAEF,OAAO;IACP,MAAM,MAAM,GAAkB;QAC5B,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,KAAK,EAAE,aAAa;KACrB,CAAC;IAEF,MAAM,uBAAA,IAAI,iCAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAEtE,OAAO,MAAM,CAAC;AAChB,CAAC,oCAED,KAAK,0CAAgB,eAAwB;IAC3C,wDAAwD;IACxD,MAAM,QAAQ,GAAG,eAAe,IAAI,aAAa,CAAC;IAElD,qEAAqE;IACrE,MAAM,aAAa,GAAG,uBAAA,IAAI,uCAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,6BAA6B;IAC7B,MAAM,YAAY,GAAG,uBAAA,IAAI,qEAAgB,MAApB,IAAI,EAAiB,eAAe,CAAC,CAAC;IAE3D,+BAA+B;IAC/B,uBAAA,IAAI,uCAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEhD,IAAI,CAAC;QACH,iCAAiC;QACjC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,sDAAsD;QACtD,uBAAA,IAAI,uCAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;AACH,CAAC,qCAED,KAAK,2CAAiB,eAAwB;IAC5C,uDAAuD;IACvD,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,GAAG,uBAAA,IAAI,yCAAiB,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACxE,IAAI,CAAC;YACH,OAAO,MAAM,uBAAA,IAAI,mEAAc,MAAlB,IAAI,EAAe,eAAe,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,wCAAwC;YACxC,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1C,MAAM,CAAC,CAAC;YACV,CAAC;YAED,uCAAuC;YACvC,IAAI,OAAO,IAAI,uBAAA,IAAI,yCAAiB,EAAE,CAAC;gBACrC,MAAM,CAAC,CAAC;YACV,CAAC;YAED,2CAA2C;YAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,IAAI,uBAAA,IAAI,2CAAmB,CAAC;YACzD,MAAM,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAE9B,0BAA0B;QAC5B,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AACrE,CAAC,mGAGC,KAAa,EACb,SAAiB;IAEjB,OAAO,YAAY,KAAK,IAAI,SAAS,EAAW,CAAC;AACnD,CAAC","sourcesContent":["import type { Eip1193Provider } from 'ethers';\n\nimport {\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthSigningOptions,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport * as timeUtils from './utils/time';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { ValidationError, RateLimitedError } from '../errors';\nimport { getMetaMaskProviderEIP6963 } from '../utils/eip-6963-metamask-provider';\nimport {\n MESSAGE_SIGNING_SNAP,\n assertMessageStartsWithMetamask,\n connectSnap,\n isSnapConnected,\n} from '../utils/messaging-signing-snap-requests';\nimport { validateLoginResponse } from '../utils/validate-login-response';\n\ntype JwtBearerAuth_SRP_Options = {\n storage: AuthStorageOptions;\n signing?: AuthSigningOptions;\n rateLimitRetry?: {\n cooldownDefaultMs?: number; // default cooldown when 429 has no Retry-After\n maxLoginRetries?: number; // maximum number of login retries on rate limit\n };\n};\n\nconst getDefaultEIP6963Provider = async () => {\n const provider = await getMetaMaskProviderEIP6963();\n if (!provider) {\n throw new ValidationError('No MetaMask wallet connected');\n }\n return provider;\n};\n\nconst getDefaultEIP6963SigningOptions = (\n customProvider?: Eip1193Provider,\n): AuthSigningOptions => ({\n getIdentifier: async (entropySourceId?: string): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n return await MESSAGE_SIGNING_SNAP.getPublicKey(provider, entropySourceId);\n },\n signMessage: async (\n message: string,\n entropySourceId?: string,\n ): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n assertMessageStartsWithMetamask(message);\n return await MESSAGE_SIGNING_SNAP.signMessage(\n provider,\n message,\n entropySourceId,\n );\n },\n});\n\nexport class SRPJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: {\n storage: AuthStorageOptions;\n signing: AuthSigningOptions;\n };\n\n readonly #metametrics?: MetaMetricsAuth;\n\n // Map to store ongoing login promises by entropySourceId\n readonly #ongoingLogins = new Map<string, Promise<LoginResponse>>();\n\n // Default cooldown when 429 has no Retry-After header\n readonly #cooldownDefaultMs: number;\n\n // Maximum number of login retries on rate limit errors\n readonly #maxLoginRetries: number;\n\n #customProvider?: Eip1193Provider;\n\n constructor(\n config: AuthConfig & { type: AuthType.SRP },\n options: JwtBearerAuth_SRP_Options & {\n customProvider?: Eip1193Provider;\n metametrics?: MetaMetricsAuth;\n },\n ) {\n this.#config = config;\n this.#customProvider = options.customProvider;\n this.#options = {\n storage: options.storage,\n signing:\n options.signing ??\n getDefaultEIP6963SigningOptions(this.#customProvider),\n };\n this.#metametrics = options.metametrics;\n\n // Apply rate limit retry config if provided\n this.#cooldownDefaultMs =\n options.rateLimitRetry?.cooldownDefaultMs ?? 10000;\n this.#maxLoginRetries = options.rateLimitRetry?.maxLoginRetries ?? 1;\n }\n\n setCustomProvider(provider: Eip1193Provider) {\n this.#customProvider = provider;\n this.#options.signing = getDefaultEIP6963SigningOptions(provider);\n }\n\n // TODO: might be easier to keep entropySourceId as a class param and use multiple SRPJwtBearerAuth instances where needed\n async getAccessToken(entropySourceId?: string): Promise<string> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.token.accessToken;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.token.accessToken;\n }\n\n async getUserProfile(entropySourceId?: string): Promise<UserProfile> {\n const session = await this.#getAuthSession(entropySourceId);\n if (session) {\n return session.profile;\n }\n\n const loginResponse = await this.#login(entropySourceId);\n return loginResponse.profile;\n }\n\n async getIdentifier(entropySourceId?: string): Promise<string> {\n return await this.#options.signing.getIdentifier(entropySourceId);\n }\n\n async getUserProfileLineage(): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken();\n return await getUserProfileLineage(this.#config.env, accessToken);\n }\n\n async signMessage(\n message: string,\n entropySourceId?: string,\n ): Promise<string> {\n return await this.#options.signing.signMessage(message, entropySourceId);\n }\n\n async isSnapConnected(): Promise<boolean> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n if (!provider) {\n return false;\n }\n\n const isConnected = await isSnapConnected(provider);\n return isConnected;\n }\n\n async connectSnap(): Promise<string> {\n const provider =\n this.#customProvider ?? (await getDefaultEIP6963Provider());\n\n const res = await connectSnap(provider);\n return res;\n }\n\n // convert expiresIn from seconds to milliseconds and use 90% of expiresIn\n async #getAuthSession(\n entropySourceId?: string,\n ): Promise<LoginResponse | null> {\n const auth = await this.#options.storage.getLoginResponse(entropySourceId);\n if (!validateLoginResponse(auth)) {\n return null;\n }\n\n const currentTime = Date.now();\n const sessionAge = currentTime - auth.token.obtainedAt;\n const refreshThreshold = auth.token.expiresIn * 1000 * 0.9;\n\n if (sessionAge < refreshThreshold) {\n return auth;\n }\n return null;\n }\n\n async #login(entropySourceId?: string): Promise<LoginResponse> {\n // Use a deferred login to avoid race conditions\n return await this.#deferredLogin(entropySourceId);\n }\n\n async #performLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Nonce\n const publicKey = await this.getIdentifier(entropySourceId);\n const nonceRes = await getNonce(publicKey, this.#config.env);\n\n const rawMessage = this.#createSrpLoginRawMessage(\n nonceRes.nonce,\n publicKey,\n );\n const signature = await this.signMessage(rawMessage, entropySourceId);\n\n // Authenticate\n const authResponse = await authenticate(\n rawMessage,\n signature,\n this.#config.type,\n this.#config.env,\n this.#metametrics,\n );\n\n // Authorize\n const tokenResponse = await authorizeOIDC(\n authResponse.token,\n this.#config.env,\n this.#config.platform,\n );\n\n // Save\n const result: LoginResponse = {\n profile: authResponse.profile,\n token: tokenResponse,\n };\n\n await this.#options.storage.setLoginResponse(result, entropySourceId);\n\n return result;\n }\n\n async #deferredLogin(entropySourceId?: string): Promise<LoginResponse> {\n // Use a key that accounts for undefined entropySourceId\n const loginKey = entropySourceId ?? '__default__';\n\n // Check if there's already an ongoing login for this entropySourceId\n const existingLogin = this.#ongoingLogins.get(loginKey);\n if (existingLogin) {\n return existingLogin;\n }\n\n // Create a new login promise\n const loginPromise = this.#loginWithRetry(entropySourceId);\n\n // Store the promise in the map\n this.#ongoingLogins.set(loginKey, loginPromise);\n\n try {\n // Wait for the login to complete\n const result = await loginPromise;\n return result;\n } finally {\n // Always clean up the ongoing login promise when done\n this.#ongoingLogins.delete(loginKey);\n }\n }\n\n async #loginWithRetry(entropySourceId?: string): Promise<LoginResponse> {\n // Allow max attempts: initial + maxLoginRetries on 429\n for (let attempt = 0; attempt < 1 + this.#maxLoginRetries; attempt += 1) {\n try {\n return await this.#performLogin(entropySourceId);\n } catch (e) {\n // Only retry on rate-limit (429) errors\n if (!RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n\n // If we've exhausted attempts, rethrow\n if (attempt >= this.#maxLoginRetries) {\n throw e;\n }\n\n // Wait for Retry-After or default cooldown\n const waitMs = e.retryAfterMs ?? this.#cooldownDefaultMs;\n await timeUtils.delay(waitMs);\n\n // Loop continues to retry\n }\n }\n\n // Should never reach here due to loop logic, but TypeScript needs a return\n throw new Error('Unexpected: login loop exhausted without result');\n }\n\n #createSrpLoginRawMessage(\n nonce: string,\n publicKey: string,\n ): `metamask:${string}:${string}` {\n return `metamask:${nonce}:${publicKey}` as const;\n }\n}\n"]}
|
|
@@ -3,7 +3,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getUserProfileLineage = exports.authenticate = exports.authorizeOIDC = exports.getNonce = exports.pairIdentifiers = exports.PROFILE_LINEAGE_URL = exports.SIWE_LOGIN_URL = exports.SRP_LOGIN_URL = exports.OIDC_TOKEN_URL = exports.PAIR_IDENTIFIERS = exports.NONCE_URL = void 0;
|
|
4
4
|
const types_1 = require("./types.cjs");
|
|
5
5
|
const env_1 = require("../../shared/env.cjs");
|
|
6
|
+
const constants_1 = require("../constants.cjs");
|
|
6
7
|
const errors_1 = require("../errors.cjs");
|
|
8
|
+
/**
|
|
9
|
+
* Parse Retry-After header into milliseconds if possible.
|
|
10
|
+
* Supports seconds or HTTP-date formats.
|
|
11
|
+
*
|
|
12
|
+
* @param retryAfterHeader - The Retry-After header value (seconds or HTTP-date)
|
|
13
|
+
* @returns The retry delay in milliseconds, or null if parsing fails
|
|
14
|
+
*/
|
|
15
|
+
function parseRetryAfter(retryAfterHeader) {
|
|
16
|
+
if (!retryAfterHeader) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const seconds = Number(retryAfterHeader);
|
|
20
|
+
if (!Number.isNaN(seconds)) {
|
|
21
|
+
return seconds * 1000;
|
|
22
|
+
}
|
|
23
|
+
const date = Date.parse(retryAfterHeader);
|
|
24
|
+
if (!Number.isNaN(date)) {
|
|
25
|
+
const diff = date - Date.now();
|
|
26
|
+
return diff > 0 ? diff : null;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Handle HTTP error responses with rate limiting support.
|
|
32
|
+
*
|
|
33
|
+
* @param response - The HTTP response object
|
|
34
|
+
* @param errorPrefix - Optional prefix for the error message
|
|
35
|
+
* @throws RateLimitedError for 429 responses
|
|
36
|
+
* @throws Error for other error responses
|
|
37
|
+
*/
|
|
38
|
+
async function handleErrorResponse(response, errorPrefix) {
|
|
39
|
+
const { status } = response;
|
|
40
|
+
const retryAfterHeader = response.headers.get('Retry-After');
|
|
41
|
+
const retryAfterMs = parseRetryAfter(retryAfterHeader);
|
|
42
|
+
const responseBody = (await response.json());
|
|
43
|
+
const message = 'message' in responseBody
|
|
44
|
+
? responseBody.message
|
|
45
|
+
: responseBody.error_description;
|
|
46
|
+
const { error } = responseBody;
|
|
47
|
+
if (status === constants_1.HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
|
|
48
|
+
throw new errors_1.RateLimitedError(`HTTP ${constants_1.HTTP_STATUS_CODES.TOO_MANY_REQUESTS}: ${message} (error: ${error})`, retryAfterMs ?? undefined);
|
|
49
|
+
}
|
|
50
|
+
const prefix = errorPrefix ? `${errorPrefix} ` : '';
|
|
51
|
+
throw new Error(`${prefix}HTTP ${status} error: ${message}, error: ${error}`);
|
|
52
|
+
}
|
|
7
53
|
const NONCE_URL = (env) => `${(0, env_1.getEnvUrls)(env).authApiUrl}/api/v2/nonce`;
|
|
8
54
|
exports.NONCE_URL = NONCE_URL;
|
|
9
55
|
const PAIR_IDENTIFIERS = (env) => `${(0, env_1.getEnvUrls)(env).authApiUrl}/api/v2/identifiers/pair`;
|
|
@@ -51,11 +97,14 @@ async function pairIdentifiers(nonce, logins, accessToken, env) {
|
|
|
51
97
|
}),
|
|
52
98
|
});
|
|
53
99
|
if (!response.ok) {
|
|
54
|
-
|
|
55
|
-
throw new Error(`HTTP error message: ${responseBody.message}, error: ${responseBody.error}`);
|
|
100
|
+
await handleErrorResponse(response);
|
|
56
101
|
}
|
|
57
102
|
}
|
|
58
103
|
catch (e) {
|
|
104
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
105
|
+
if (errors_1.RateLimitedError.isRateLimitError(e)) {
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
59
108
|
/* istanbul ignore next */
|
|
60
109
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
61
110
|
throw new errors_1.PairError(`unable to pair identifiers: ${errorMessage}`);
|
|
@@ -75,8 +124,7 @@ async function getNonce(id, env) {
|
|
|
75
124
|
try {
|
|
76
125
|
const nonceResponse = await fetch(nonceUrl.toString());
|
|
77
126
|
if (!nonceResponse.ok) {
|
|
78
|
-
|
|
79
|
-
throw new Error(`HTTP error message: ${responseBody.message}, error: ${responseBody.error}`);
|
|
127
|
+
await handleErrorResponse(nonceResponse);
|
|
80
128
|
}
|
|
81
129
|
const nonceJson = await nonceResponse.json();
|
|
82
130
|
return {
|
|
@@ -86,6 +134,10 @@ async function getNonce(id, env) {
|
|
|
86
134
|
};
|
|
87
135
|
}
|
|
88
136
|
catch (e) {
|
|
137
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
138
|
+
if (errors_1.RateLimitedError.isRateLimitError(e)) {
|
|
139
|
+
throw e;
|
|
140
|
+
}
|
|
89
141
|
/* istanbul ignore next */
|
|
90
142
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
91
143
|
throw new errors_1.NonceRetrievalError(`failed to generate nonce: ${errorMessage}`);
|
|
@@ -116,8 +168,7 @@ async function authorizeOIDC(jwtToken, env, platform) {
|
|
|
116
168
|
body: urlEncodedBody.toString(),
|
|
117
169
|
});
|
|
118
170
|
if (!response.ok) {
|
|
119
|
-
|
|
120
|
-
throw new Error(`HTTP error: ${responseBody.error_description}, error code: ${responseBody.error}`);
|
|
171
|
+
await handleErrorResponse(response);
|
|
121
172
|
}
|
|
122
173
|
const accessTokenResponse = await response.json();
|
|
123
174
|
return {
|
|
@@ -127,6 +178,10 @@ async function authorizeOIDC(jwtToken, env, platform) {
|
|
|
127
178
|
};
|
|
128
179
|
}
|
|
129
180
|
catch (e) {
|
|
181
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
182
|
+
if (errors_1.RateLimitedError.isRateLimitError(e)) {
|
|
183
|
+
throw e;
|
|
184
|
+
}
|
|
130
185
|
/* istanbul ignore next */
|
|
131
186
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
132
187
|
throw new errors_1.SignInError(`unable to get access token: ${errorMessage}`);
|
|
@@ -165,8 +220,7 @@ async function authenticate(rawMessage, signature, authType, env, metametrics) {
|
|
|
165
220
|
}),
|
|
166
221
|
});
|
|
167
222
|
if (!response.ok) {
|
|
168
|
-
|
|
169
|
-
throw new Error(`${authType} login HTTP error: ${responseBody.message}, error code: ${responseBody.error}`);
|
|
223
|
+
await handleErrorResponse(response, `${authType} login`);
|
|
170
224
|
}
|
|
171
225
|
const loginResponse = await response.json();
|
|
172
226
|
return {
|
|
@@ -180,6 +234,10 @@ async function authenticate(rawMessage, signature, authType, env, metametrics) {
|
|
|
180
234
|
};
|
|
181
235
|
}
|
|
182
236
|
catch (e) {
|
|
237
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
238
|
+
if (errors_1.RateLimitedError.isRateLimitError(e)) {
|
|
239
|
+
throw e;
|
|
240
|
+
}
|
|
183
241
|
/* istanbul ignore next */
|
|
184
242
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
185
243
|
throw new errors_1.SignInError(`unable to perform SRP login: ${errorMessage}`);
|
|
@@ -203,13 +261,16 @@ async function getUserProfileLineage(env, accessToken) {
|
|
|
203
261
|
},
|
|
204
262
|
});
|
|
205
263
|
if (!response.ok) {
|
|
206
|
-
|
|
207
|
-
throw new Error(`HTTP error message: ${responseBody.message}, error: ${responseBody.error}`);
|
|
264
|
+
await handleErrorResponse(response, 'profile lineage');
|
|
208
265
|
}
|
|
209
266
|
const profileJson = await response.json();
|
|
210
267
|
return profileJson;
|
|
211
268
|
}
|
|
212
269
|
catch (e) {
|
|
270
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
271
|
+
if (errors_1.RateLimitedError.isRateLimitError(e)) {
|
|
272
|
+
throw e;
|
|
273
|
+
}
|
|
213
274
|
/* istanbul ignore next */
|
|
214
275
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
215
276
|
throw new errors_1.SignInError(`failed to get profile lineage: ${errorMessage}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccessToken,\n ErrorMessage,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\nimport type { Env, Platform } from '../../shared/env';\nimport { getEnvUrls, getOidcClientId } from '../../shared/env';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport {\n NonceRetrievalError,\n PairError,\n SignInError,\n ValidationError,\n} from '../errors';\n\nexport const NONCE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env) =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/profile/lineage`;\n\nconst getAuthenticationUrl = (authType: AuthType, env: Env): string => {\n switch (authType) {\n case AuthType.SRP:\n return SRP_LOGIN_URL(env);\n case AuthType.SiWE:\n return SIWE_LOGIN_URL(env);\n /* istanbul ignore next */\n default:\n throw new ValidationError(\n `Invalid AuthType: ${authType as number} - unable to create Auth URL`,\n );\n }\n};\n\ntype NonceResponse = {\n nonce: string;\n identifier: string;\n expiresIn: number;\n};\n\ntype PairRequest = {\n signature: string;\n raw_message: string;\n encrypted_storage_key: string;\n identifier_type: 'SIWE' | 'SRP';\n};\n\n/**\n * Pair multiple identifiers under a single profile\n *\n * @param nonce - session nonce\n * @param logins - pairing request payload\n * @param accessToken - JWT access token used to access protected resources\n * @param env - server environment\n * @returns void.\n */\nexport async function pairIdentifiers(\n nonce: string,\n logins: PairRequest[],\n accessToken: string,\n env: Env,\n): Promise<void> {\n const pairUrl = new URL(PAIR_IDENTIFIERS(env));\n\n try {\n const response = await fetch(pairUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n nonce,\n logins,\n }),\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new PairError(`unable to pair identifiers: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Get Nonce for JWT Bearer Flow\n *\n * @param id - identifier ID\n * @param env - server environment\n * @returns the nonce.\n */\nexport async function getNonce(id: string, env: Env): Promise<NonceResponse> {\n const nonceUrl = new URL(NONCE_URL(env));\n nonceUrl.searchParams.set('identifier', id);\n\n try {\n const nonceResponse = await fetch(nonceUrl.toString());\n if (!nonceResponse.ok) {\n const responseBody = (await nonceResponse.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const nonceJson = await nonceResponse.json();\n return {\n nonce: nonceJson.nonce,\n identifier: nonceJson.identifier,\n expiresIn: nonceJson.expires_in,\n };\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new NonceRetrievalError(`failed to generate nonce: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Authorize And perform OIDC Flow to get the Access Token\n *\n * @param jwtToken - The original token received from Authentication. This is traded for the Access Token. (the authentication token is single-use)\n * @param env - server environment\n * @param platform - SDK platform\n * @returns Access Token from Authorization server\n */\nexport async function authorizeOIDC(\n jwtToken: string,\n env: Env,\n platform: Platform,\n): Promise<AccessToken> {\n const grantType = 'urn:ietf:params:oauth:grant-type:jwt-bearer';\n const headers = new Headers({\n 'Content-Type': 'application/x-www-form-urlencoded',\n });\n\n const urlEncodedBody = new URLSearchParams();\n urlEncodedBody.append('grant_type', grantType);\n urlEncodedBody.append('client_id', getOidcClientId(env, platform));\n urlEncodedBody.append('assertion', jwtToken);\n\n try {\n const response = await fetch(OIDC_TOKEN_URL(env), {\n method: 'POST',\n headers,\n body: urlEncodedBody.toString(),\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as {\n error_description: string;\n error: string;\n };\n throw new Error(\n `HTTP error: ${responseBody.error_description}, error code: ${responseBody.error}`,\n );\n }\n\n const accessTokenResponse = await response.json();\n return {\n accessToken: accessTokenResponse.access_token,\n expiresIn: accessTokenResponse.expires_in,\n obtainedAt: Date.now(),\n };\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to get access token: ${errorMessage}`);\n }\n}\n\ntype Authentication = {\n token: string;\n expiresIn: number;\n profile: UserProfile;\n};\n/**\n * Service to Authenticate/Login a user via SIWE or SRP derived key.\n *\n * @param rawMessage - raw message for validation when authenticating\n * @param signature - signed raw message\n * @param authType - authentication type/flow used\n * @param env - server environment\n * @param metametrics - optional metametrics\n * @returns Authentication Token\n */\nexport async function authenticate(\n rawMessage: string,\n signature: string,\n authType: AuthType,\n env: Env,\n metametrics?: MetaMetricsAuth,\n): Promise<Authentication> {\n const authenticationUrl = getAuthenticationUrl(authType, env);\n\n try {\n const response = await fetch(authenticationUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n signature,\n raw_message: rawMessage,\n ...(metametrics\n ? {\n metametrics: {\n metametrics_id: await metametrics.getMetaMetricsId(),\n agent: metametrics.agent,\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `${authType} login HTTP error: ${responseBody.message}, error code: ${responseBody.error}`,\n );\n }\n\n const loginResponse = await response.json();\n return {\n token: loginResponse.token,\n expiresIn: loginResponse.expires_in,\n profile: {\n identifierId: loginResponse.profile.identifier_id,\n metaMetricsId: loginResponse.profile.metametrics_id,\n profileId: loginResponse.profile.profile_id,\n },\n };\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to perform SRP login: ${errorMessage}`);\n }\n}\n\n/**\n * Service to get the Profile Lineage\n *\n * @param env - server environment\n * @param accessToken - JWT access token used to access protected resources\n * @returns Profile Lineage information.\n */\nexport async function getUserProfileLineage(\n env: Env,\n accessToken: string,\n): Promise<UserProfileLineage> {\n const profileLineageUrl = new URL(PROFILE_LINEAGE_URL(env));\n\n try {\n const response = await fetch(profileLineageUrl, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const profileJson: UserProfileLineage = await response.json();\n\n return profileJson;\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`failed to get profile lineage: ${errorMessage}`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"services.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccessToken,\n ErrorMessage,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\nimport type { Env, Platform } from '../../shared/env';\nimport { getEnvUrls, getOidcClientId } from '../../shared/env';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { HTTP_STATUS_CODES } from '../constants';\nimport {\n NonceRetrievalError,\n PairError,\n SignInError,\n ValidationError,\n RateLimitedError,\n} from '../errors';\n\n/**\n * Parse Retry-After header into milliseconds if possible.\n * Supports seconds or HTTP-date formats.\n *\n * @param retryAfterHeader - The Retry-After header value (seconds or HTTP-date)\n * @returns The retry delay in milliseconds, or null if parsing fails\n */\nfunction parseRetryAfter(retryAfterHeader: string | null): number | null {\n if (!retryAfterHeader) {\n return null;\n }\n const seconds = Number(retryAfterHeader);\n if (!Number.isNaN(seconds)) {\n return seconds * 1000;\n }\n const date = Date.parse(retryAfterHeader);\n if (!Number.isNaN(date)) {\n const diff = date - Date.now();\n return diff > 0 ? diff : null;\n }\n return null;\n}\n\n/**\n * Handle HTTP error responses with rate limiting support.\n *\n * @param response - The HTTP response object\n * @param errorPrefix - Optional prefix for the error message\n * @throws RateLimitedError for 429 responses\n * @throws Error for other error responses\n */\nasync function handleErrorResponse(\n response: Response,\n errorPrefix?: string,\n): Promise<never> {\n const { status } = response;\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfterMs = parseRetryAfter(retryAfterHeader);\n\n const responseBody = (await response.json()) as\n | ErrorMessage\n | { error_description: string; error: string };\n\n const message =\n 'message' in responseBody\n ? responseBody.message\n : responseBody.error_description;\n const { error } = responseBody;\n\n if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {\n throw new RateLimitedError(\n `HTTP ${HTTP_STATUS_CODES.TOO_MANY_REQUESTS}: ${message} (error: ${error})`,\n retryAfterMs ?? undefined,\n );\n }\n\n const prefix = errorPrefix ? `${errorPrefix} ` : '';\n throw new Error(`${prefix}HTTP ${status} error: ${message}, error: ${error}`);\n}\n\nexport const NONCE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env) =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/profile/lineage`;\n\nconst getAuthenticationUrl = (authType: AuthType, env: Env): string => {\n switch (authType) {\n case AuthType.SRP:\n return SRP_LOGIN_URL(env);\n case AuthType.SiWE:\n return SIWE_LOGIN_URL(env);\n /* istanbul ignore next */\n default:\n throw new ValidationError(\n `Invalid AuthType: ${authType as number} - unable to create Auth URL`,\n );\n }\n};\n\ntype NonceResponse = {\n nonce: string;\n identifier: string;\n expiresIn: number;\n};\n\ntype PairRequest = {\n signature: string;\n raw_message: string;\n encrypted_storage_key: string;\n identifier_type: 'SIWE' | 'SRP';\n};\n\n/**\n * Pair multiple identifiers under a single profile\n *\n * @param nonce - session nonce\n * @param logins - pairing request payload\n * @param accessToken - JWT access token used to access protected resources\n * @param env - server environment\n * @returns void.\n */\nexport async function pairIdentifiers(\n nonce: string,\n logins: PairRequest[],\n accessToken: string,\n env: Env,\n): Promise<void> {\n const pairUrl = new URL(PAIR_IDENTIFIERS(env));\n\n try {\n const response = await fetch(pairUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n nonce,\n logins,\n }),\n });\n\n if (!response.ok) {\n await handleErrorResponse(response);\n }\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new PairError(`unable to pair identifiers: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Get Nonce for JWT Bearer Flow\n *\n * @param id - identifier ID\n * @param env - server environment\n * @returns the nonce.\n */\nexport async function getNonce(id: string, env: Env): Promise<NonceResponse> {\n const nonceUrl = new URL(NONCE_URL(env));\n nonceUrl.searchParams.set('identifier', id);\n\n try {\n const nonceResponse = await fetch(nonceUrl.toString());\n if (!nonceResponse.ok) {\n await handleErrorResponse(nonceResponse);\n }\n\n const nonceJson = await nonceResponse.json();\n return {\n nonce: nonceJson.nonce,\n identifier: nonceJson.identifier,\n expiresIn: nonceJson.expires_in,\n };\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new NonceRetrievalError(`failed to generate nonce: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Authorize And perform OIDC Flow to get the Access Token\n *\n * @param jwtToken - The original token received from Authentication. This is traded for the Access Token. (the authentication token is single-use)\n * @param env - server environment\n * @param platform - SDK platform\n * @returns Access Token from Authorization server\n */\nexport async function authorizeOIDC(\n jwtToken: string,\n env: Env,\n platform: Platform,\n): Promise<AccessToken> {\n const grantType = 'urn:ietf:params:oauth:grant-type:jwt-bearer';\n const headers = new Headers({\n 'Content-Type': 'application/x-www-form-urlencoded',\n });\n\n const urlEncodedBody = new URLSearchParams();\n urlEncodedBody.append('grant_type', grantType);\n urlEncodedBody.append('client_id', getOidcClientId(env, platform));\n urlEncodedBody.append('assertion', jwtToken);\n\n try {\n const response = await fetch(OIDC_TOKEN_URL(env), {\n method: 'POST',\n headers,\n body: urlEncodedBody.toString(),\n });\n\n if (!response.ok) {\n await handleErrorResponse(response);\n }\n\n const accessTokenResponse = await response.json();\n return {\n accessToken: accessTokenResponse.access_token,\n expiresIn: accessTokenResponse.expires_in,\n obtainedAt: Date.now(),\n };\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to get access token: ${errorMessage}`);\n }\n}\n\ntype Authentication = {\n token: string;\n expiresIn: number;\n profile: UserProfile;\n};\n/**\n * Service to Authenticate/Login a user via SIWE or SRP derived key.\n *\n * @param rawMessage - raw message for validation when authenticating\n * @param signature - signed raw message\n * @param authType - authentication type/flow used\n * @param env - server environment\n * @param metametrics - optional metametrics\n * @returns Authentication Token\n */\nexport async function authenticate(\n rawMessage: string,\n signature: string,\n authType: AuthType,\n env: Env,\n metametrics?: MetaMetricsAuth,\n): Promise<Authentication> {\n const authenticationUrl = getAuthenticationUrl(authType, env);\n\n try {\n const response = await fetch(authenticationUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n signature,\n raw_message: rawMessage,\n ...(metametrics\n ? {\n metametrics: {\n metametrics_id: await metametrics.getMetaMetricsId(),\n agent: metametrics.agent,\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n await handleErrorResponse(response, `${authType} login`);\n }\n\n const loginResponse = await response.json();\n return {\n token: loginResponse.token,\n expiresIn: loginResponse.expires_in,\n profile: {\n identifierId: loginResponse.profile.identifier_id,\n metaMetricsId: loginResponse.profile.metametrics_id,\n profileId: loginResponse.profile.profile_id,\n },\n };\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to perform SRP login: ${errorMessage}`);\n }\n}\n\n/**\n * Service to get the Profile Lineage\n *\n * @param env - server environment\n * @param accessToken - JWT access token used to access protected resources\n * @returns Profile Lineage information.\n */\nexport async function getUserProfileLineage(\n env: Env,\n accessToken: string,\n): Promise<UserProfileLineage> {\n const profileLineageUrl = new URL(PROFILE_LINEAGE_URL(env));\n\n try {\n const response = await fetch(profileLineageUrl, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n await handleErrorResponse(response, 'profile lineage');\n }\n\n const profileJson: UserProfileLineage = await response.json();\n\n return profileJson;\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`failed to get profile lineage: ${errorMessage}`);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AACjB,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,6BAAyB;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;
|
|
1
|
+
{"version":3,"file":"services.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AACjB,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,6BAAyB;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAsEnE,eAAO,MAAM,SAAS,QAAS,GAAG,WACY,CAAC;AAE/C,eAAO,MAAM,gBAAgB,QAAS,GAAG,WACgB,CAAC;AAE1D,eAAO,MAAM,cAAc,QAAS,GAAG,WACO,CAAC;AAE/C,eAAO,MAAM,aAAa,QAAS,GAAG,WACY,CAAC;AAEnD,eAAO,MAAM,cAAc,QAAS,GAAG,WACY,CAAC;AAEpD,eAAO,MAAM,mBAAmB,QAAS,GAAG,WACY,CAAC;AAgBzD,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,KAAK,CAAC;CACjC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CA0B3E;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,WAAW,CAAC,CAsCtB;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;CACtB,CAAC;AACF;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,eAAe,GAC5B,OAAO,CAAC,cAAc,CAAC,CA+CzB;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4B7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AACjB,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,6BAAyB;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;
|
|
1
|
+
{"version":3,"file":"services.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AACjB,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,6BAAyB;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAsEnE,eAAO,MAAM,SAAS,QAAS,GAAG,WACY,CAAC;AAE/C,eAAO,MAAM,gBAAgB,QAAS,GAAG,WACgB,CAAC;AAE1D,eAAO,MAAM,cAAc,QAAS,GAAG,WACO,CAAC;AAE/C,eAAO,MAAM,aAAa,QAAS,GAAG,WACY,CAAC;AAEnD,eAAO,MAAM,cAAc,QAAS,GAAG,WACY,CAAC;AAEpD,eAAO,MAAM,mBAAmB,QAAS,GAAG,WACY,CAAC;AAgBzD,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,KAAK,CAAC;CACjC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CA0B3E;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,WAAW,CAAC,CAsCtB;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;CACtB,CAAC;AACF;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,eAAe,GAC5B,OAAO,CAAC,cAAc,CAAC,CA+CzB;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4B7B"}
|
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
import { AuthType } from "./types.mjs";
|
|
2
2
|
import { getEnvUrls, getOidcClientId } from "../../shared/env.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { HTTP_STATUS_CODES } from "../constants.mjs";
|
|
4
|
+
import { NonceRetrievalError, PairError, SignInError, ValidationError, RateLimitedError } from "../errors.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* Parse Retry-After header into milliseconds if possible.
|
|
7
|
+
* Supports seconds or HTTP-date formats.
|
|
8
|
+
*
|
|
9
|
+
* @param retryAfterHeader - The Retry-After header value (seconds or HTTP-date)
|
|
10
|
+
* @returns The retry delay in milliseconds, or null if parsing fails
|
|
11
|
+
*/
|
|
12
|
+
function parseRetryAfter(retryAfterHeader) {
|
|
13
|
+
if (!retryAfterHeader) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const seconds = Number(retryAfterHeader);
|
|
17
|
+
if (!Number.isNaN(seconds)) {
|
|
18
|
+
return seconds * 1000;
|
|
19
|
+
}
|
|
20
|
+
const date = Date.parse(retryAfterHeader);
|
|
21
|
+
if (!Number.isNaN(date)) {
|
|
22
|
+
const diff = date - Date.now();
|
|
23
|
+
return diff > 0 ? diff : null;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Handle HTTP error responses with rate limiting support.
|
|
29
|
+
*
|
|
30
|
+
* @param response - The HTTP response object
|
|
31
|
+
* @param errorPrefix - Optional prefix for the error message
|
|
32
|
+
* @throws RateLimitedError for 429 responses
|
|
33
|
+
* @throws Error for other error responses
|
|
34
|
+
*/
|
|
35
|
+
async function handleErrorResponse(response, errorPrefix) {
|
|
36
|
+
const { status } = response;
|
|
37
|
+
const retryAfterHeader = response.headers.get('Retry-After');
|
|
38
|
+
const retryAfterMs = parseRetryAfter(retryAfterHeader);
|
|
39
|
+
const responseBody = (await response.json());
|
|
40
|
+
const message = 'message' in responseBody
|
|
41
|
+
? responseBody.message
|
|
42
|
+
: responseBody.error_description;
|
|
43
|
+
const { error } = responseBody;
|
|
44
|
+
if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
|
|
45
|
+
throw new RateLimitedError(`HTTP ${HTTP_STATUS_CODES.TOO_MANY_REQUESTS}: ${message} (error: ${error})`, retryAfterMs ?? undefined);
|
|
46
|
+
}
|
|
47
|
+
const prefix = errorPrefix ? `${errorPrefix} ` : '';
|
|
48
|
+
throw new Error(`${prefix}HTTP ${status} error: ${message}, error: ${error}`);
|
|
49
|
+
}
|
|
4
50
|
export const NONCE_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;
|
|
5
51
|
export const PAIR_IDENTIFIERS = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;
|
|
6
52
|
export const OIDC_TOKEN_URL = (env) => `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;
|
|
@@ -42,11 +88,14 @@ export async function pairIdentifiers(nonce, logins, accessToken, env) {
|
|
|
42
88
|
}),
|
|
43
89
|
});
|
|
44
90
|
if (!response.ok) {
|
|
45
|
-
|
|
46
|
-
throw new Error(`HTTP error message: ${responseBody.message}, error: ${responseBody.error}`);
|
|
91
|
+
await handleErrorResponse(response);
|
|
47
92
|
}
|
|
48
93
|
}
|
|
49
94
|
catch (e) {
|
|
95
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
96
|
+
if (RateLimitedError.isRateLimitError(e)) {
|
|
97
|
+
throw e;
|
|
98
|
+
}
|
|
50
99
|
/* istanbul ignore next */
|
|
51
100
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
52
101
|
throw new PairError(`unable to pair identifiers: ${errorMessage}`);
|
|
@@ -65,8 +114,7 @@ export async function getNonce(id, env) {
|
|
|
65
114
|
try {
|
|
66
115
|
const nonceResponse = await fetch(nonceUrl.toString());
|
|
67
116
|
if (!nonceResponse.ok) {
|
|
68
|
-
|
|
69
|
-
throw new Error(`HTTP error message: ${responseBody.message}, error: ${responseBody.error}`);
|
|
117
|
+
await handleErrorResponse(nonceResponse);
|
|
70
118
|
}
|
|
71
119
|
const nonceJson = await nonceResponse.json();
|
|
72
120
|
return {
|
|
@@ -76,6 +124,10 @@ export async function getNonce(id, env) {
|
|
|
76
124
|
};
|
|
77
125
|
}
|
|
78
126
|
catch (e) {
|
|
127
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
128
|
+
if (RateLimitedError.isRateLimitError(e)) {
|
|
129
|
+
throw e;
|
|
130
|
+
}
|
|
79
131
|
/* istanbul ignore next */
|
|
80
132
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
81
133
|
throw new NonceRetrievalError(`failed to generate nonce: ${errorMessage}`);
|
|
@@ -105,8 +157,7 @@ export async function authorizeOIDC(jwtToken, env, platform) {
|
|
|
105
157
|
body: urlEncodedBody.toString(),
|
|
106
158
|
});
|
|
107
159
|
if (!response.ok) {
|
|
108
|
-
|
|
109
|
-
throw new Error(`HTTP error: ${responseBody.error_description}, error code: ${responseBody.error}`);
|
|
160
|
+
await handleErrorResponse(response);
|
|
110
161
|
}
|
|
111
162
|
const accessTokenResponse = await response.json();
|
|
112
163
|
return {
|
|
@@ -116,6 +167,10 @@ export async function authorizeOIDC(jwtToken, env, platform) {
|
|
|
116
167
|
};
|
|
117
168
|
}
|
|
118
169
|
catch (e) {
|
|
170
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
171
|
+
if (RateLimitedError.isRateLimitError(e)) {
|
|
172
|
+
throw e;
|
|
173
|
+
}
|
|
119
174
|
/* istanbul ignore next */
|
|
120
175
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
121
176
|
throw new SignInError(`unable to get access token: ${errorMessage}`);
|
|
@@ -153,8 +208,7 @@ export async function authenticate(rawMessage, signature, authType, env, metamet
|
|
|
153
208
|
}),
|
|
154
209
|
});
|
|
155
210
|
if (!response.ok) {
|
|
156
|
-
|
|
157
|
-
throw new Error(`${authType} login HTTP error: ${responseBody.message}, error code: ${responseBody.error}`);
|
|
211
|
+
await handleErrorResponse(response, `${authType} login`);
|
|
158
212
|
}
|
|
159
213
|
const loginResponse = await response.json();
|
|
160
214
|
return {
|
|
@@ -168,6 +222,10 @@ export async function authenticate(rawMessage, signature, authType, env, metamet
|
|
|
168
222
|
};
|
|
169
223
|
}
|
|
170
224
|
catch (e) {
|
|
225
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
226
|
+
if (RateLimitedError.isRateLimitError(e)) {
|
|
227
|
+
throw e;
|
|
228
|
+
}
|
|
171
229
|
/* istanbul ignore next */
|
|
172
230
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
173
231
|
throw new SignInError(`unable to perform SRP login: ${errorMessage}`);
|
|
@@ -190,13 +248,16 @@ export async function getUserProfileLineage(env, accessToken) {
|
|
|
190
248
|
},
|
|
191
249
|
});
|
|
192
250
|
if (!response.ok) {
|
|
193
|
-
|
|
194
|
-
throw new Error(`HTTP error message: ${responseBody.message}, error: ${responseBody.error}`);
|
|
251
|
+
await handleErrorResponse(response, 'profile lineage');
|
|
195
252
|
}
|
|
196
253
|
const profileJson = await response.json();
|
|
197
254
|
return profileJson;
|
|
198
255
|
}
|
|
199
256
|
catch (e) {
|
|
257
|
+
// Re-throw RateLimitedError to preserve 429 status and retry metadata
|
|
258
|
+
if (RateLimitedError.isRateLimitError(e)) {
|
|
259
|
+
throw e;
|
|
260
|
+
}
|
|
200
261
|
/* istanbul ignore next */
|
|
201
262
|
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e ?? '');
|
|
202
263
|
throw new SignInError(`failed to get profile lineage: ${errorMessage}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AAEnC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,6BAAyB;AAE/D,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,WAAW,EACX,eAAe,EAChB,sBAAkB;AAEnB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAQ,EAAE,EAAE,CACpC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAQ,EAAE,EAAE,CAC3C,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,0BAA0B,CAAC;AAE1D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAQ,EAAE,EAAE,CACzC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAQ,EAAE,EAAE,CACxC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,mBAAmB,CAAC;AAEnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAQ,EAAE,EAAE,CACzC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,oBAAoB,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAQ,EAAE,EAAE,CAC9C,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,yBAAyB,CAAC;AAEzD,MAAM,oBAAoB,GAAG,CAAC,QAAkB,EAAE,GAAQ,EAAU,EAAE;IACpE,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,GAAG;YACf,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5B,KAAK,QAAQ,CAAC,IAAI;YAChB,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;QAC7B,0BAA0B;QAC1B;YACE,MAAM,IAAI,eAAe,CACvB,qBAAqB,QAAkB,8BAA8B,CACtE,CAAC;IACN,CAAC;AACH,CAAC,CAAC;AAeF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAa,EACb,MAAqB,EACrB,WAAmB,EACnB,GAAQ;IAER,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;IAE/C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE;YACpC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,WAAW,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK;gBACL,MAAM;aACP,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,YAAY,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;YAC7D,MAAM,IAAI,KAAK,CACb,uBAAuB,YAAY,CAAC,OAAO,YAAY,YAAY,CAAC,KAAK,EAAE,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0BAA0B;QAC1B,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,SAAS,CAAC,+BAA+B,YAAY,EAAE,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAU,EAAE,GAAQ;IACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAE5C,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;YACtB,MAAM,YAAY,GAAG,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,CAAiB,CAAC;YAClE,MAAM,IAAI,KAAK,CACb,uBAAuB,YAAY,CAAC,OAAO,YAAY,YAAY,CAAC,KAAK,EAAE,CAC5E,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QAC7C,OAAO;YACL,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,SAAS,EAAE,SAAS,CAAC,UAAU;SAChC,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0BAA0B;QAC1B,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,mBAAmB,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,GAAQ,EACR,QAAkB;IAElB,MAAM,SAAS,GAAG,6CAA6C,CAAC;IAChE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;QAC1B,cAAc,EAAE,mCAAmC;KACpD,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,IAAI,eAAe,EAAE,CAAC;IAC7C,cAAc,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAC/C,cAAc,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnE,cAAc,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,YAAY,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAG1C,CAAC;YACF,MAAM,IAAI,KAAK,CACb,eAAe,YAAY,CAAC,iBAAiB,iBAAiB,YAAY,CAAC,KAAK,EAAE,CACnF,CAAC;QACJ,CAAC;QAED,MAAM,mBAAmB,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClD,OAAO;YACL,WAAW,EAAE,mBAAmB,CAAC,YAAY;YAC7C,SAAS,EAAE,mBAAmB,CAAC,UAAU;YACzC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;SACvB,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0BAA0B;QAC1B,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,WAAW,CAAC,+BAA+B,YAAY,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAOD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB,EAClB,SAAiB,EACjB,QAAkB,EAClB,GAAQ,EACR,WAA6B;IAE7B,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAE9D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,SAAS;gBACT,WAAW,EAAE,UAAU;gBACvB,GAAG,CAAC,WAAW;oBACb,CAAC,CAAC;wBACE,WAAW,EAAE;4BACX,cAAc,EAAE,MAAM,WAAW,CAAC,gBAAgB,EAAE;4BACpD,KAAK,EAAE,WAAW,CAAC,KAAK;yBACzB;qBACF;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,YAAY,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;YAC7D,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,sBAAsB,YAAY,CAAC,OAAO,iBAAiB,YAAY,CAAC,KAAK,EAAE,CAC3F,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC5C,OAAO;YACL,KAAK,EAAE,aAAa,CAAC,KAAK;YAC1B,SAAS,EAAE,aAAa,CAAC,UAAU;YACnC,OAAO,EAAE;gBACP,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC,aAAa;gBACjD,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,cAAc;gBACnD,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC,UAAU;aAC5C;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0BAA0B;QAC1B,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,WAAW,CAAC,gCAAgC,YAAY,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAQ,EACR,WAAmB;IAEnB,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;YAC9C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,WAAW,EAAE;aACvC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,YAAY,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;YAC7D,MAAM,IAAI,KAAK,CACb,uBAAuB,YAAY,CAAC,OAAO,YAAY,YAAY,CAAC,KAAK,EAAE,CAC5E,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAuB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE9D,OAAO,WAAW,CAAC;IACrB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0BAA0B;QAC1B,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,WAAW,CAAC,kCAAkC,YAAY,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC","sourcesContent":["import type {\n AccessToken,\n ErrorMessage,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\nimport type { Env, Platform } from '../../shared/env';\nimport { getEnvUrls, getOidcClientId } from '../../shared/env';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport {\n NonceRetrievalError,\n PairError,\n SignInError,\n ValidationError,\n} from '../errors';\n\nexport const NONCE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env) =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/profile/lineage`;\n\nconst getAuthenticationUrl = (authType: AuthType, env: Env): string => {\n switch (authType) {\n case AuthType.SRP:\n return SRP_LOGIN_URL(env);\n case AuthType.SiWE:\n return SIWE_LOGIN_URL(env);\n /* istanbul ignore next */\n default:\n throw new ValidationError(\n `Invalid AuthType: ${authType as number} - unable to create Auth URL`,\n );\n }\n};\n\ntype NonceResponse = {\n nonce: string;\n identifier: string;\n expiresIn: number;\n};\n\ntype PairRequest = {\n signature: string;\n raw_message: string;\n encrypted_storage_key: string;\n identifier_type: 'SIWE' | 'SRP';\n};\n\n/**\n * Pair multiple identifiers under a single profile\n *\n * @param nonce - session nonce\n * @param logins - pairing request payload\n * @param accessToken - JWT access token used to access protected resources\n * @param env - server environment\n * @returns void.\n */\nexport async function pairIdentifiers(\n nonce: string,\n logins: PairRequest[],\n accessToken: string,\n env: Env,\n): Promise<void> {\n const pairUrl = new URL(PAIR_IDENTIFIERS(env));\n\n try {\n const response = await fetch(pairUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n nonce,\n logins,\n }),\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new PairError(`unable to pair identifiers: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Get Nonce for JWT Bearer Flow\n *\n * @param id - identifier ID\n * @param env - server environment\n * @returns the nonce.\n */\nexport async function getNonce(id: string, env: Env): Promise<NonceResponse> {\n const nonceUrl = new URL(NONCE_URL(env));\n nonceUrl.searchParams.set('identifier', id);\n\n try {\n const nonceResponse = await fetch(nonceUrl.toString());\n if (!nonceResponse.ok) {\n const responseBody = (await nonceResponse.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const nonceJson = await nonceResponse.json();\n return {\n nonce: nonceJson.nonce,\n identifier: nonceJson.identifier,\n expiresIn: nonceJson.expires_in,\n };\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new NonceRetrievalError(`failed to generate nonce: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Authorize And perform OIDC Flow to get the Access Token\n *\n * @param jwtToken - The original token received from Authentication. This is traded for the Access Token. (the authentication token is single-use)\n * @param env - server environment\n * @param platform - SDK platform\n * @returns Access Token from Authorization server\n */\nexport async function authorizeOIDC(\n jwtToken: string,\n env: Env,\n platform: Platform,\n): Promise<AccessToken> {\n const grantType = 'urn:ietf:params:oauth:grant-type:jwt-bearer';\n const headers = new Headers({\n 'Content-Type': 'application/x-www-form-urlencoded',\n });\n\n const urlEncodedBody = new URLSearchParams();\n urlEncodedBody.append('grant_type', grantType);\n urlEncodedBody.append('client_id', getOidcClientId(env, platform));\n urlEncodedBody.append('assertion', jwtToken);\n\n try {\n const response = await fetch(OIDC_TOKEN_URL(env), {\n method: 'POST',\n headers,\n body: urlEncodedBody.toString(),\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as {\n error_description: string;\n error: string;\n };\n throw new Error(\n `HTTP error: ${responseBody.error_description}, error code: ${responseBody.error}`,\n );\n }\n\n const accessTokenResponse = await response.json();\n return {\n accessToken: accessTokenResponse.access_token,\n expiresIn: accessTokenResponse.expires_in,\n obtainedAt: Date.now(),\n };\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to get access token: ${errorMessage}`);\n }\n}\n\ntype Authentication = {\n token: string;\n expiresIn: number;\n profile: UserProfile;\n};\n/**\n * Service to Authenticate/Login a user via SIWE or SRP derived key.\n *\n * @param rawMessage - raw message for validation when authenticating\n * @param signature - signed raw message\n * @param authType - authentication type/flow used\n * @param env - server environment\n * @param metametrics - optional metametrics\n * @returns Authentication Token\n */\nexport async function authenticate(\n rawMessage: string,\n signature: string,\n authType: AuthType,\n env: Env,\n metametrics?: MetaMetricsAuth,\n): Promise<Authentication> {\n const authenticationUrl = getAuthenticationUrl(authType, env);\n\n try {\n const response = await fetch(authenticationUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n signature,\n raw_message: rawMessage,\n ...(metametrics\n ? {\n metametrics: {\n metametrics_id: await metametrics.getMetaMetricsId(),\n agent: metametrics.agent,\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `${authType} login HTTP error: ${responseBody.message}, error code: ${responseBody.error}`,\n );\n }\n\n const loginResponse = await response.json();\n return {\n token: loginResponse.token,\n expiresIn: loginResponse.expires_in,\n profile: {\n identifierId: loginResponse.profile.identifier_id,\n metaMetricsId: loginResponse.profile.metametrics_id,\n profileId: loginResponse.profile.profile_id,\n },\n };\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to perform SRP login: ${errorMessage}`);\n }\n}\n\n/**\n * Service to get the Profile Lineage\n *\n * @param env - server environment\n * @param accessToken - JWT access token used to access protected resources\n * @returns Profile Lineage information.\n */\nexport async function getUserProfileLineage(\n env: Env,\n accessToken: string,\n): Promise<UserProfileLineage> {\n const profileLineageUrl = new URL(PROFILE_LINEAGE_URL(env));\n\n try {\n const response = await fetch(profileLineageUrl, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const profileJson: UserProfileLineage = await response.json();\n\n return profileJson;\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`failed to get profile lineage: ${errorMessage}`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"services.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccessToken,\n ErrorMessage,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\nimport type { Env, Platform } from '../../shared/env';\nimport { getEnvUrls, getOidcClientId } from '../../shared/env';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { HTTP_STATUS_CODES } from '../constants';\nimport {\n NonceRetrievalError,\n PairError,\n SignInError,\n ValidationError,\n RateLimitedError,\n} from '../errors';\n\n/**\n * Parse Retry-After header into milliseconds if possible.\n * Supports seconds or HTTP-date formats.\n *\n * @param retryAfterHeader - The Retry-After header value (seconds or HTTP-date)\n * @returns The retry delay in milliseconds, or null if parsing fails\n */\nfunction parseRetryAfter(retryAfterHeader: string | null): number | null {\n if (!retryAfterHeader) {\n return null;\n }\n const seconds = Number(retryAfterHeader);\n if (!Number.isNaN(seconds)) {\n return seconds * 1000;\n }\n const date = Date.parse(retryAfterHeader);\n if (!Number.isNaN(date)) {\n const diff = date - Date.now();\n return diff > 0 ? diff : null;\n }\n return null;\n}\n\n/**\n * Handle HTTP error responses with rate limiting support.\n *\n * @param response - The HTTP response object\n * @param errorPrefix - Optional prefix for the error message\n * @throws RateLimitedError for 429 responses\n * @throws Error for other error responses\n */\nasync function handleErrorResponse(\n response: Response,\n errorPrefix?: string,\n): Promise<never> {\n const { status } = response;\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfterMs = parseRetryAfter(retryAfterHeader);\n\n const responseBody = (await response.json()) as\n | ErrorMessage\n | { error_description: string; error: string };\n\n const message =\n 'message' in responseBody\n ? responseBody.message\n : responseBody.error_description;\n const { error } = responseBody;\n\n if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {\n throw new RateLimitedError(\n `HTTP ${HTTP_STATUS_CODES.TOO_MANY_REQUESTS}: ${message} (error: ${error})`,\n retryAfterMs ?? undefined,\n );\n }\n\n const prefix = errorPrefix ? `${errorPrefix} ` : '';\n throw new Error(`${prefix}HTTP ${status} error: ${message}, error: ${error}`);\n}\n\nexport const NONCE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env) =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env) =>\n `${getEnvUrls(env).authApiUrl}/api/v2/profile/lineage`;\n\nconst getAuthenticationUrl = (authType: AuthType, env: Env): string => {\n switch (authType) {\n case AuthType.SRP:\n return SRP_LOGIN_URL(env);\n case AuthType.SiWE:\n return SIWE_LOGIN_URL(env);\n /* istanbul ignore next */\n default:\n throw new ValidationError(\n `Invalid AuthType: ${authType as number} - unable to create Auth URL`,\n );\n }\n};\n\ntype NonceResponse = {\n nonce: string;\n identifier: string;\n expiresIn: number;\n};\n\ntype PairRequest = {\n signature: string;\n raw_message: string;\n encrypted_storage_key: string;\n identifier_type: 'SIWE' | 'SRP';\n};\n\n/**\n * Pair multiple identifiers under a single profile\n *\n * @param nonce - session nonce\n * @param logins - pairing request payload\n * @param accessToken - JWT access token used to access protected resources\n * @param env - server environment\n * @returns void.\n */\nexport async function pairIdentifiers(\n nonce: string,\n logins: PairRequest[],\n accessToken: string,\n env: Env,\n): Promise<void> {\n const pairUrl = new URL(PAIR_IDENTIFIERS(env));\n\n try {\n const response = await fetch(pairUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n nonce,\n logins,\n }),\n });\n\n if (!response.ok) {\n await handleErrorResponse(response);\n }\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new PairError(`unable to pair identifiers: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Get Nonce for JWT Bearer Flow\n *\n * @param id - identifier ID\n * @param env - server environment\n * @returns the nonce.\n */\nexport async function getNonce(id: string, env: Env): Promise<NonceResponse> {\n const nonceUrl = new URL(NONCE_URL(env));\n nonceUrl.searchParams.set('identifier', id);\n\n try {\n const nonceResponse = await fetch(nonceUrl.toString());\n if (!nonceResponse.ok) {\n await handleErrorResponse(nonceResponse);\n }\n\n const nonceJson = await nonceResponse.json();\n return {\n nonce: nonceJson.nonce,\n identifier: nonceJson.identifier,\n expiresIn: nonceJson.expires_in,\n };\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new NonceRetrievalError(`failed to generate nonce: ${errorMessage}`);\n }\n}\n\n/**\n * Service to Authorize And perform OIDC Flow to get the Access Token\n *\n * @param jwtToken - The original token received from Authentication. This is traded for the Access Token. (the authentication token is single-use)\n * @param env - server environment\n * @param platform - SDK platform\n * @returns Access Token from Authorization server\n */\nexport async function authorizeOIDC(\n jwtToken: string,\n env: Env,\n platform: Platform,\n): Promise<AccessToken> {\n const grantType = 'urn:ietf:params:oauth:grant-type:jwt-bearer';\n const headers = new Headers({\n 'Content-Type': 'application/x-www-form-urlencoded',\n });\n\n const urlEncodedBody = new URLSearchParams();\n urlEncodedBody.append('grant_type', grantType);\n urlEncodedBody.append('client_id', getOidcClientId(env, platform));\n urlEncodedBody.append('assertion', jwtToken);\n\n try {\n const response = await fetch(OIDC_TOKEN_URL(env), {\n method: 'POST',\n headers,\n body: urlEncodedBody.toString(),\n });\n\n if (!response.ok) {\n await handleErrorResponse(response);\n }\n\n const accessTokenResponse = await response.json();\n return {\n accessToken: accessTokenResponse.access_token,\n expiresIn: accessTokenResponse.expires_in,\n obtainedAt: Date.now(),\n };\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to get access token: ${errorMessage}`);\n }\n}\n\ntype Authentication = {\n token: string;\n expiresIn: number;\n profile: UserProfile;\n};\n/**\n * Service to Authenticate/Login a user via SIWE or SRP derived key.\n *\n * @param rawMessage - raw message for validation when authenticating\n * @param signature - signed raw message\n * @param authType - authentication type/flow used\n * @param env - server environment\n * @param metametrics - optional metametrics\n * @returns Authentication Token\n */\nexport async function authenticate(\n rawMessage: string,\n signature: string,\n authType: AuthType,\n env: Env,\n metametrics?: MetaMetricsAuth,\n): Promise<Authentication> {\n const authenticationUrl = getAuthenticationUrl(authType, env);\n\n try {\n const response = await fetch(authenticationUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n signature,\n raw_message: rawMessage,\n ...(metametrics\n ? {\n metametrics: {\n metametrics_id: await metametrics.getMetaMetricsId(),\n agent: metametrics.agent,\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n await handleErrorResponse(response, `${authType} login`);\n }\n\n const loginResponse = await response.json();\n return {\n token: loginResponse.token,\n expiresIn: loginResponse.expires_in,\n profile: {\n identifierId: loginResponse.profile.identifier_id,\n metaMetricsId: loginResponse.profile.metametrics_id,\n profileId: loginResponse.profile.profile_id,\n },\n };\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`unable to perform SRP login: ${errorMessage}`);\n }\n}\n\n/**\n * Service to get the Profile Lineage\n *\n * @param env - server environment\n * @param accessToken - JWT access token used to access protected resources\n * @returns Profile Lineage information.\n */\nexport async function getUserProfileLineage(\n env: Env,\n accessToken: string,\n): Promise<UserProfileLineage> {\n const profileLineageUrl = new URL(PROFILE_LINEAGE_URL(env));\n\n try {\n const response = await fetch(profileLineageUrl, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n await handleErrorResponse(response, 'profile lineage');\n }\n\n const profileJson: UserProfileLineage = await response.json();\n\n return profileJson;\n } catch (e) {\n // Re-throw RateLimitedError to preserve 429 status and retry metadata\n if (RateLimitedError.isRateLimitError(e)) {\n throw e;\n }\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new SignInError(`failed to get profile lineage: ${errorMessage}`);\n }\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.delay = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Delays execution for the specified number of milliseconds.
|
|
6
|
+
*
|
|
7
|
+
* @param ms - Number of milliseconds to delay
|
|
8
|
+
* @returns Promise that resolves after the delay
|
|
9
|
+
*/
|
|
10
|
+
async function delay(ms) {
|
|
11
|
+
if (ms <= 0) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
|
+
}
|
|
16
|
+
exports.delay = delay;
|
|
17
|
+
//# sourceMappingURL=time.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.cjs","sourceRoot":"","sources":["../../../../src/sdk/authentication-jwt-bearer/utils/time.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACI,KAAK,UAAU,KAAK,CAAC,EAAU;IACpC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AALD,sBAKC","sourcesContent":["/**\n * Delays execution for the specified number of milliseconds.\n *\n * @param ms - Number of milliseconds to delay\n * @returns Promise that resolves after the delay\n */\nexport async function delay(ms: number): Promise<void> {\n if (ms <= 0) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delays execution for the specified number of milliseconds.
|
|
3
|
+
*
|
|
4
|
+
* @param ms - Number of milliseconds to delay
|
|
5
|
+
* @returns Promise that resolves after the delay
|
|
6
|
+
*/
|
|
7
|
+
export declare function delay(ms: number): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=time.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.d.cts","sourceRoot":"","sources":["../../../../src/sdk/authentication-jwt-bearer/utils/time.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delays execution for the specified number of milliseconds.
|
|
3
|
+
*
|
|
4
|
+
* @param ms - Number of milliseconds to delay
|
|
5
|
+
* @returns Promise that resolves after the delay
|
|
6
|
+
*/
|
|
7
|
+
export declare function delay(ms: number): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=time.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.d.mts","sourceRoot":"","sources":["../../../../src/sdk/authentication-jwt-bearer/utils/time.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delays execution for the specified number of milliseconds.
|
|
3
|
+
*
|
|
4
|
+
* @param ms - Number of milliseconds to delay
|
|
5
|
+
* @returns Promise that resolves after the delay
|
|
6
|
+
*/
|
|
7
|
+
export async function delay(ms) {
|
|
8
|
+
if (ms <= 0) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=time.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.mjs","sourceRoot":"","sources":["../../../../src/sdk/authentication-jwt-bearer/utils/time.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,EAAU;IACpC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["/**\n * Delays execution for the specified number of milliseconds.\n *\n * @param ms - Number of milliseconds to delay\n * @returns Promise that resolves after the delay\n */\nexport async function delay(ms: number): Promise<void> {\n if (ms <= 0) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.cjs","sourceRoot":"","sources":["../../src/sdk/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,iBAAiB,GAAG;IAC/B,iBAAiB,EAAE,GAAG;CACvB,CAAC","sourcesContent":["export const HTTP_STATUS_CODES = {\n TOO_MANY_REQUESTS: 429,\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.cts","sourceRoot":"","sources":["../../src/sdk/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB;;CAE7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../src/sdk/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB;;CAE7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../src/sdk/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,iBAAiB,EAAE,GAAG;CACvB,CAAC","sourcesContent":["export const HTTP_STATUS_CODES = {\n TOO_MANY_REQUESTS: 429,\n};\n"]}
|
package/dist/sdk/errors.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NotFoundError = exports.UnsupportedAuthTypeError = exports.ValidationError = exports.UserStorageError = exports.PairError = exports.SignInError = exports.NonceRetrievalError = void 0;
|
|
3
|
+
exports.RateLimitedError = exports.NotFoundError = exports.UnsupportedAuthTypeError = exports.ValidationError = exports.UserStorageError = exports.PairError = exports.SignInError = exports.NonceRetrievalError = void 0;
|
|
4
|
+
const constants_1 = require("./constants.cjs");
|
|
4
5
|
class NonceRetrievalError extends Error {
|
|
5
6
|
constructor(message) {
|
|
6
7
|
super(message);
|
|
@@ -50,4 +51,26 @@ class NotFoundError extends Error {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
exports.NotFoundError = NotFoundError;
|
|
54
|
+
class RateLimitedError extends Error {
|
|
55
|
+
constructor(message, retryAfterMs) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.status = constants_1.HTTP_STATUS_CODES.TOO_MANY_REQUESTS;
|
|
58
|
+
this.name = 'RateLimitedError';
|
|
59
|
+
this.retryAfterMs = retryAfterMs;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if an unknown error is a rate limit error (429 status).
|
|
63
|
+
*
|
|
64
|
+
* @param e - The error to check
|
|
65
|
+
* @returns True if the error is a rate limit error
|
|
66
|
+
*/
|
|
67
|
+
static isRateLimitError(e) {
|
|
68
|
+
return (e instanceof RateLimitedError ||
|
|
69
|
+
(typeof e === 'object' &&
|
|
70
|
+
e !== null &&
|
|
71
|
+
'status' in e &&
|
|
72
|
+
e.status === constants_1.HTTP_STATUS_CODES.TOO_MANY_REQUESTS));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.RateLimitedError = RateLimitedError;
|
|
53
76
|
//# sourceMappingURL=errors.cjs.map
|
package/dist/sdk/errors.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.cjs","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AALD,kDAKC;AAED,MAAa,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AALD,kCAKC;AAED,MAAa,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AALD,8BAKC;AAED,MAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AALD,4CAKC;AAED,MAAa,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AALD,0CAKC;AAED,MAAa,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AALD,4DAKC;AAED,MAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AALD,sCAKC","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"errors.cjs","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":";;;AAAA,+CAAgD;AAEhD,MAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AALD,kDAKC;AAED,MAAa,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AALD,kCAKC;AAED,MAAa,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AALD,8BAKC;AAED,MAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AALD,4CAKC;AAED,MAAa,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AALD,0CAKC;AAED,MAAa,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AALD,4DAKC;AAED,MAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AALD,sCAKC;AAED,MAAa,gBAAiB,SAAQ,KAAK;IAKzC,YAAY,OAAe,EAAE,YAAqB;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QALR,WAAM,GAAG,6BAAiB,CAAC,iBAAiB,CAAC;QAMpD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,CAAU;QAChC,OAAO,CACL,CAAC,YAAY,gBAAgB;YAC7B,CAAC,OAAO,CAAC,KAAK,QAAQ;gBACpB,CAAC,KAAK,IAAI;gBACV,QAAQ,IAAI,CAAC;gBACb,CAAC,CAAC,MAAM,KAAK,6BAAiB,CAAC,iBAAiB,CAAC,CACpD,CAAC;IACJ,CAAC;CACF;AA1BD,4CA0BC","sourcesContent":["import { HTTP_STATUS_CODES } from './constants';\n\nexport class NonceRetrievalError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NonceRetrievalError';\n }\n}\n\nexport class SignInError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SignInError';\n }\n}\n\nexport class PairError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PairError';\n }\n}\n\nexport class UserStorageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UserStorageError';\n }\n}\n\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\nexport class UnsupportedAuthTypeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UnsupportedAuthTypeError';\n }\n}\n\nexport class NotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotFoundError';\n }\n}\n\nexport class RateLimitedError extends Error {\n readonly status = HTTP_STATUS_CODES.TOO_MANY_REQUESTS;\n\n readonly retryAfterMs?: number;\n\n constructor(message: string, retryAfterMs?: number) {\n super(message);\n this.name = 'RateLimitedError';\n this.retryAfterMs = retryAfterMs;\n }\n\n /**\n * Check if an unknown error is a rate limit error (429 status).\n *\n * @param e - The error to check\n * @returns True if the error is a rate limit error\n */\n static isRateLimitError(e: unknown): e is RateLimitedError {\n return (\n e instanceof RateLimitedError ||\n (typeof e === 'object' &&\n e !== null &&\n 'status' in e &&\n e.status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS)\n );\n }\n}\n"]}
|
package/dist/sdk/errors.d.cts
CHANGED
|
@@ -19,4 +19,16 @@ export declare class UnsupportedAuthTypeError extends Error {
|
|
|
19
19
|
export declare class NotFoundError extends Error {
|
|
20
20
|
constructor(message: string);
|
|
21
21
|
}
|
|
22
|
+
export declare class RateLimitedError extends Error {
|
|
23
|
+
readonly status: number;
|
|
24
|
+
readonly retryAfterMs?: number;
|
|
25
|
+
constructor(message: string, retryAfterMs?: number);
|
|
26
|
+
/**
|
|
27
|
+
* Check if an unknown error is a rate limit error (429 status).
|
|
28
|
+
*
|
|
29
|
+
* @param e - The error to check
|
|
30
|
+
* @returns True if the error is a rate limit error
|
|
31
|
+
*/
|
|
32
|
+
static isRateLimitError(e: unknown): e is RateLimitedError;
|
|
33
|
+
}
|
|
22
34
|
//# sourceMappingURL=errors.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.cts","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.d.cts","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":"AAEA,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,SAAuC;IAEtD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;gBAEnB,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;IAMlD;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,gBAAgB;CAS3D"}
|
package/dist/sdk/errors.d.mts
CHANGED
|
@@ -19,4 +19,16 @@ export declare class UnsupportedAuthTypeError extends Error {
|
|
|
19
19
|
export declare class NotFoundError extends Error {
|
|
20
20
|
constructor(message: string);
|
|
21
21
|
}
|
|
22
|
+
export declare class RateLimitedError extends Error {
|
|
23
|
+
readonly status: number;
|
|
24
|
+
readonly retryAfterMs?: number;
|
|
25
|
+
constructor(message: string, retryAfterMs?: number);
|
|
26
|
+
/**
|
|
27
|
+
* Check if an unknown error is a rate limit error (429 status).
|
|
28
|
+
*
|
|
29
|
+
* @param e - The error to check
|
|
30
|
+
* @returns True if the error is a rate limit error
|
|
31
|
+
*/
|
|
32
|
+
static isRateLimitError(e: unknown): e is RateLimitedError;
|
|
33
|
+
}
|
|
22
34
|
//# sourceMappingURL=errors.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.mts","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.d.mts","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":"AAEA,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,SAAuC;IAEtD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;gBAEnB,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;IAMlD;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,gBAAgB;CAS3D"}
|
package/dist/sdk/errors.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HTTP_STATUS_CODES } from "./constants.mjs";
|
|
1
2
|
export class NonceRetrievalError extends Error {
|
|
2
3
|
constructor(message) {
|
|
3
4
|
super(message);
|
|
@@ -40,4 +41,25 @@ export class NotFoundError extends Error {
|
|
|
40
41
|
this.name = 'NotFoundError';
|
|
41
42
|
}
|
|
42
43
|
}
|
|
44
|
+
export class RateLimitedError extends Error {
|
|
45
|
+
constructor(message, retryAfterMs) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.status = HTTP_STATUS_CODES.TOO_MANY_REQUESTS;
|
|
48
|
+
this.name = 'RateLimitedError';
|
|
49
|
+
this.retryAfterMs = retryAfterMs;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if an unknown error is a rate limit error (429 status).
|
|
53
|
+
*
|
|
54
|
+
* @param e - The error to check
|
|
55
|
+
* @returns True if the error is a rate limit error
|
|
56
|
+
*/
|
|
57
|
+
static isRateLimitError(e) {
|
|
58
|
+
return (e instanceof RateLimitedError ||
|
|
59
|
+
(typeof e === 'object' &&
|
|
60
|
+
e !== null &&
|
|
61
|
+
'status' in e &&
|
|
62
|
+
e.status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
43
65
|
//# sourceMappingURL=errors.mjs.map
|
package/dist/sdk/errors.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.mjs","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"errors.mjs","sourceRoot":"","sources":["../../src/sdk/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,wBAAoB;AAEhD,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAKzC,YAAY,OAAe,EAAE,YAAqB;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QALR,WAAM,GAAG,iBAAiB,CAAC,iBAAiB,CAAC;QAMpD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,CAAU;QAChC,OAAO,CACL,CAAC,YAAY,gBAAgB;YAC7B,CAAC,OAAO,CAAC,KAAK,QAAQ;gBACpB,CAAC,KAAK,IAAI;gBACV,QAAQ,IAAI,CAAC;gBACb,CAAC,CAAC,MAAM,KAAK,iBAAiB,CAAC,iBAAiB,CAAC,CACpD,CAAC;IACJ,CAAC;CACF","sourcesContent":["import { HTTP_STATUS_CODES } from './constants';\n\nexport class NonceRetrievalError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NonceRetrievalError';\n }\n}\n\nexport class SignInError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SignInError';\n }\n}\n\nexport class PairError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PairError';\n }\n}\n\nexport class UserStorageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UserStorageError';\n }\n}\n\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\nexport class UnsupportedAuthTypeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UnsupportedAuthTypeError';\n }\n}\n\nexport class NotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotFoundError';\n }\n}\n\nexport class RateLimitedError extends Error {\n readonly status = HTTP_STATUS_CODES.TOO_MANY_REQUESTS;\n\n readonly retryAfterMs?: number;\n\n constructor(message: string, retryAfterMs?: number) {\n super(message);\n this.name = 'RateLimitedError';\n this.retryAfterMs = retryAfterMs;\n }\n\n /**\n * Check if an unknown error is a rate limit error (429 status).\n *\n * @param e - The error to check\n * @returns True if the error is a rate limit error\n */\n static isRateLimitError(e: unknown): e is RateLimitedError {\n return (\n e instanceof RateLimitedError ||\n (typeof e === 'object' &&\n e !== null &&\n 'status' in e &&\n e.status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS)\n );\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/profile-sync-controller",
|
|
3
|
-
"version": "26.0.0-preview-
|
|
3
|
+
"version": "26.0.0-preview-f4ab1511",
|
|
4
4
|
"description": "The profile sync helps developers synchronize data across multiple clients and devices in a privacy-preserving way. All data saved in the user storage database is encrypted client-side to preserve privacy. The user storage provides a modular design, giving developers the flexibility to construct and manage their storage spaces in a way that best suits their needs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|