@metamask-previews/profile-sync-controller 28.0.2-preview-8daaa5a40 → 28.0.2-preview-ae9b6b322
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 +14 -2
- package/dist/controllers/authentication/AuthenticationController-method-action-types.cjs.map +1 -1
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.cts +52 -6
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.cts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.mts +52 -6
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.mts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController-method-action-types.mjs.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.cjs +143 -6
- package/dist/controllers/authentication/AuthenticationController.cjs.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.d.cts +66 -7
- package/dist/controllers/authentication/AuthenticationController.d.cts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.d.mts +66 -7
- package/dist/controllers/authentication/AuthenticationController.d.mts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.mjs +143 -6
- package/dist/controllers/authentication/AuthenticationController.mjs.map +1 -1
- package/dist/controllers/authentication/index.cjs.map +1 -1
- package/dist/controllers/authentication/index.d.cts +1 -1
- package/dist/controllers/authentication/index.d.cts.map +1 -1
- package/dist/controllers/authentication/index.d.mts +1 -1
- package/dist/controllers/authentication/index.d.mts.map +1 -1
- package/dist/controllers/authentication/index.mjs.map +1 -1
- package/dist/controllers/authentication/mocks/mockResponses.cjs +10 -1
- package/dist/controllers/authentication/mocks/mockResponses.cjs.map +1 -1
- package/dist/controllers/authentication/mocks/mockResponses.d.cts +17 -32
- package/dist/controllers/authentication/mocks/mockResponses.d.cts.map +1 -1
- package/dist/controllers/authentication/mocks/mockResponses.d.mts +17 -32
- package/dist/controllers/authentication/mocks/mockResponses.d.mts.map +1 -1
- package/dist/controllers/authentication/mocks/mockResponses.mjs +9 -1
- package/dist/controllers/authentication/mocks/mockResponses.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs +28 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.cts +2 -0
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.mts +2 -0
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.mjs +29 -2
- package/dist/sdk/authentication-jwt-bearer/flow-srp.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.cjs +58 -1
- package/dist/sdk/authentication-jwt-bearer/services.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.cts +17 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.mts +17 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.mjs +55 -0
- package/dist/sdk/authentication-jwt-bearer/services.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/types.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/types.d.cts +20 -1
- package/dist/sdk/authentication-jwt-bearer/types.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/types.d.mts +20 -1
- package/dist/sdk/authentication-jwt-bearer/types.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/types.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.cjs +27 -0
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.cjs.map +1 -0
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.d.cts +13 -0
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.d.cts.map +1 -0
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.d.mts +13 -0
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.d.mts.map +1 -0
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.mjs +23 -0
- package/dist/sdk/authentication-jwt-bearer/utils/identifier.mjs.map +1 -0
- package/dist/sdk/authentication.cjs +4 -0
- package/dist/sdk/authentication.cjs.map +1 -1
- package/dist/sdk/authentication.d.cts +2 -0
- package/dist/sdk/authentication.d.cts.map +1 -1
- package/dist/sdk/authentication.d.mts +2 -0
- package/dist/sdk/authentication.d.mts.map +1 -1
- package/dist/sdk/authentication.mjs +4 -0
- package/dist/sdk/authentication.mjs.map +1 -1
- package/dist/sdk/mocks/auth.cjs +11 -1
- package/dist/sdk/mocks/auth.cjs.map +1 -1
- package/dist/sdk/mocks/auth.d.cts +10 -0
- package/dist/sdk/mocks/auth.d.cts.map +1 -1
- package/dist/sdk/mocks/auth.d.mts +10 -0
- package/dist/sdk/mocks/auth.d.mts.map +1 -1
- package/dist/sdk/mocks/auth.mjs +11 -1
- package/dist/sdk/mocks/auth.mjs.map +1 -1
- package/dist/sdk/user-storage.cjs +26 -3
- package/dist/sdk/user-storage.cjs.map +1 -1
- package/dist/sdk/user-storage.d.cts +7 -0
- package/dist/sdk/user-storage.d.cts.map +1 -1
- package/dist/sdk/user-storage.d.mts +7 -0
- package/dist/sdk/user-storage.d.mts.map +1 -1
- package/dist/sdk/user-storage.mjs +26 -3
- package/dist/sdk/user-storage.mjs.map +1 -1
- package/dist/sdk/utils/validate-pair-response.cjs +29 -0
- package/dist/sdk/utils/validate-pair-response.cjs.map +1 -0
- package/dist/sdk/utils/validate-pair-response.d.cts +26 -0
- package/dist/sdk/utils/validate-pair-response.d.cts.map +1 -0
- package/dist/sdk/utils/validate-pair-response.d.mts +26 -0
- package/dist/sdk/utils/validate-pair-response.d.mts.map +1 -0
- package/dist/sdk/utils/validate-pair-response.mjs +25 -0
- package/dist/sdk/utils/validate-pair-response.mjs.map +1 -0
- package/package.json +4 -4
|
@@ -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 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';\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';\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<\n string | undefined,\n Promise<LoginResponse>\n >();\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(\n entropySourceId?: string,\n ): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken(entropySourceId);\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 // Check if there's already an ongoing login for this entropySourceId\n const existingLogin = this.#ongoingLogins.get(entropySourceId);\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(entropySourceId, loginPromise);\n\n try {\n // Wait for the login to complete\n return await loginPromise;\n } finally {\n // Always clean up the ongoing login promise when done\n this.#ongoingLogins.delete(entropySourceId);\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"]}
|
|
1
|
+
{"version":3,"file":"flow-srp.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":";;;;;;;;;;;;AAGA,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;AACzE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,qBAAqB,EACrB,YAAY,EACb,uBAAmB;AAYpB,OAAO,EAAE,mBAAmB,EAAE,+BAA2B;AACzD,OAAO,KAAK,SAAS,yBAAqB;AAW1C,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;IAwB3B,YACE,MAA2C,EAC3C,OAGC;;QA5BM,2CAAoB;QAEpB,4CAGP;QAEO,gDAA+B;QAExC,yDAAyD;QAChD,0CAAiB,IAAI,GAAG,EAG9B,EAAC;QAEJ,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,CACzB,eAAwB;QAExB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC/D,OAAO,MAAM,qBAAqB,CAAC,uBAAA,IAAI,gCAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,YAAsB,EACtB,eAAuB;QAEvB,OAAO,MAAM,YAAY,CAAC,YAAY,EAAE,eAAe,EAAE,uBAAA,IAAI,gCAAQ,CAAC,GAAG,CAAC,CAAC;IAC7E,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;CA4JF;;AA1JC,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,4EAA4E;IAC5E,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC;QACrC,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,2CAA2C;IAC3C,oFAAoF;IACpF,8DAA8D;IAC9D,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC;IAC1D,MAAM,OAAO,GAAG,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC;IAE5C,IAAI,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,MAAM,kBAAkB,GAAG,mBAAmB,CAC5C,SAAS,EACT,uBAAA,IAAI,gCAAQ,CAAC,GAAG,CACjB,CAAC;QAEF,MAAM,eAAe,GAAG,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CACnE,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,kBAAkB,CAAC,CAC/D,CAAC;QAEF,wEAAwE;QACxE,uEAAuE;QACvE,sEAAsE;QACtE,iEAAiE;QACjE,MAAM,WAAW,GACf,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC;YACjE,eAAe,CAAC,CAAC,CAAC,CAAC;QAErB,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,CAAC,SAAS,GAAG,WAAW,CAAC,cAAc,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;IAEhD,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;QACP,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,qEAAqE;IACrE,MAAM,aAAa,GAAG,uBAAA,IAAI,uCAAe,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC/D,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,eAAe,EAAE,YAAY,CAAC,CAAC;IAEvD,IAAI,CAAC;QACH,iCAAiC;QACjC,OAAO,MAAM,YAAY,CAAC;IAC5B,CAAC;YAAS,CAAC;QACT,sDAAsD;QACtD,uBAAA,IAAI,uCAAe,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC9C,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 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';\nimport {\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n pairProfiles,\n} from './services';\nimport type { PairProfilesResponse } from './services';\nimport type {\n AuthConfig,\n AuthSigningOptions,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { computeIdentifierId } from './utils/identifier';\nimport * as timeUtils from './utils/time';\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<\n string | undefined,\n Promise<LoginResponse>\n >();\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(\n entropySourceId?: string,\n ): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken(entropySourceId);\n return await getUserProfileLineage(this.#config.env, accessToken);\n }\n\n async pairSrpProfiles(\n accessTokens: string[],\n authAccessToken: string,\n ): Promise<PairProfilesResponse> {\n return await pairProfiles(accessTokens, authAccessToken, this.#config.env);\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 // get canonical profile id from server if not present in the cached session\n if (!auth.profile.canonicalProfileId) {\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 // Resolve original profileId from aliases.\n // This is done mainly to preserve the original profileId for storage key derivation\n // until we migrate to the canonical profileId storage system.\n const canonicalProfileId = authResponse.profile.profileId;\n const profile = { ...authResponse.profile };\n\n if (authResponse.profileAliases?.length > 0) {\n const targetIdentifierId = computeIdentifierId(\n publicKey,\n this.#config.env,\n );\n\n const matchingAliases = authResponse.profileAliases.filter((alias) =>\n alias.identifierIds.some((id) => id.id === targetIdentifierId),\n );\n\n // Prefer the leaf alias (single identifier) — it's the original profile\n // created for this SRP. Multi-identifier aliases are former canonicals\n // that absorbed other profiles; they are correct only when this SRP's\n // original profile was itself a canonical before being absorbed.\n const targetAlias =\n matchingAliases.find((alias) => alias.identifierIds.length === 1) ??\n matchingAliases[0];\n\n if (targetAlias) {\n profile.profileId = targetAlias.aliasProfileId;\n }\n }\n\n profile.canonicalProfileId = canonicalProfileId;\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,\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 // Check if there's already an ongoing login for this entropySourceId\n const existingLogin = this.#ongoingLogins.get(entropySourceId);\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(entropySourceId, loginPromise);\n\n try {\n // Wait for the login to complete\n return await loginPromise;\n } finally {\n // Always clean up the ongoing login promise when done\n this.#ongoingLogins.delete(entropySourceId);\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"]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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;
|
|
3
|
+
exports.getUserProfileLineage = exports.authenticate = exports.authorizeOIDC = exports.getNonce = exports.pairProfiles = exports.pairIdentifiers = exports.PROFILE_LINEAGE_URL = exports.PAIR_PROFILES_URL = exports.SIWE_LOGIN_URL = exports.SRP_LOGIN_URL = exports.OIDC_TOKEN_URL = exports.PAIR_IDENTIFIERS = exports.NONCE_URL = void 0;
|
|
4
4
|
const env_1 = require("../../shared/env.cjs");
|
|
5
5
|
const constants_1 = require("../constants.cjs");
|
|
6
6
|
const errors_1 = require("../errors.cjs");
|
|
7
|
+
const validate_pair_response_1 = require("../utils/validate-pair-response.cjs");
|
|
7
8
|
const types_1 = require("./types.cjs");
|
|
8
9
|
/**
|
|
9
10
|
* Parse Retry-After header into milliseconds if possible.
|
|
@@ -112,6 +113,8 @@ const SRP_LOGIN_URL = (env) => `${(0, env_1.getEnvUrls)(env).authApiUrl}/api/v2/
|
|
|
112
113
|
exports.SRP_LOGIN_URL = SRP_LOGIN_URL;
|
|
113
114
|
const SIWE_LOGIN_URL = (env) => `${(0, env_1.getEnvUrls)(env).authApiUrl}/api/v2/siwe/login`;
|
|
114
115
|
exports.SIWE_LOGIN_URL = SIWE_LOGIN_URL;
|
|
116
|
+
const PAIR_PROFILES_URL = (env) => `${(0, env_1.getEnvUrls)(env).authApiUrl}/api/v2/profile/pair`;
|
|
117
|
+
exports.PAIR_PROFILES_URL = PAIR_PROFILES_URL;
|
|
115
118
|
const PROFILE_LINEAGE_URL = (env) => `${(0, env_1.getEnvUrls)(env).authApiUrl}/api/v2/profile/lineage`;
|
|
116
119
|
exports.PROFILE_LINEAGE_URL = PROFILE_LINEAGE_URL;
|
|
117
120
|
const getAuthenticationUrl = (authType, env) => {
|
|
@@ -125,6 +128,13 @@ const getAuthenticationUrl = (authType, env) => {
|
|
|
125
128
|
throw new errors_1.ValidationError(`Invalid AuthType: ${authType} - unable to create Auth URL`);
|
|
126
129
|
}
|
|
127
130
|
};
|
|
131
|
+
const parseProfileAliases = (raw) => {
|
|
132
|
+
return raw.map((alias) => ({
|
|
133
|
+
aliasProfileId: alias.alias_profile_id,
|
|
134
|
+
canonicalProfileId: alias.canonical_profile_id,
|
|
135
|
+
identifierIds: alias.identifier_ids ?? [],
|
|
136
|
+
}));
|
|
137
|
+
};
|
|
128
138
|
/**
|
|
129
139
|
* Pair multiple identifiers under a single profile
|
|
130
140
|
*
|
|
@@ -158,6 +168,48 @@ async function pairIdentifiers(nonce, logins, accessToken, env) {
|
|
|
158
168
|
}
|
|
159
169
|
}
|
|
160
170
|
exports.pairIdentifiers = pairIdentifiers;
|
|
171
|
+
/**
|
|
172
|
+
* Pair multiple profiles using their OIDC access tokens.
|
|
173
|
+
* Idempotent — calling with already-paired tokens is a no-op.
|
|
174
|
+
*
|
|
175
|
+
* @param accessTokens - Two or more OIDC access tokens to pair
|
|
176
|
+
* @param authAccessToken - A valid access token for the Authorization header
|
|
177
|
+
* @param env - server environment
|
|
178
|
+
* @returns The pair response containing the canonical profile and aliases
|
|
179
|
+
*/
|
|
180
|
+
async function pairProfiles(accessTokens, authAccessToken, env) {
|
|
181
|
+
const pairUrl = new URL((0, exports.PAIR_PROFILES_URL)(env));
|
|
182
|
+
try {
|
|
183
|
+
const response = await fetch(pairUrl, {
|
|
184
|
+
method: 'POST',
|
|
185
|
+
headers: {
|
|
186
|
+
'Content-Type': 'application/json',
|
|
187
|
+
Authorization: `Bearer ${authAccessToken}`,
|
|
188
|
+
},
|
|
189
|
+
body: JSON.stringify({
|
|
190
|
+
jwts: accessTokens,
|
|
191
|
+
}),
|
|
192
|
+
});
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
return await throwServiceError(response, 'Failed to pair profiles', errors_1.PairError);
|
|
195
|
+
}
|
|
196
|
+
const pairResponse = await response.json();
|
|
197
|
+
(0, validate_pair_response_1.validatePairResponse)(pairResponse);
|
|
198
|
+
return {
|
|
199
|
+
profile: {
|
|
200
|
+
identifierId: pairResponse.profile.identifier_id,
|
|
201
|
+
metaMetricsId: pairResponse.profile.metametrics_id ?? '',
|
|
202
|
+
profileId: pairResponse.profile.profile_id,
|
|
203
|
+
canonicalProfileId: pairResponse.profile.profile_id,
|
|
204
|
+
},
|
|
205
|
+
profileAliases: parseProfileAliases(pairResponse.profile_aliases ?? []),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
return await throwServiceError(error, 'Failed to pair profiles', errors_1.PairError);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exports.pairProfiles = pairProfiles;
|
|
161
213
|
/**
|
|
162
214
|
* Service to Get Nonce for JWT Bearer Flow
|
|
163
215
|
*
|
|
@@ -240,6 +292,9 @@ async function authenticate(rawMessage, signature, authType, env, metametrics) {
|
|
|
240
292
|
method: 'POST',
|
|
241
293
|
headers: {
|
|
242
294
|
'Content-Type': 'application/json',
|
|
295
|
+
...(authType === types_1.AuthType.SRP
|
|
296
|
+
? { 'X-MetaMask-Profile-Pairing': 'enabled' }
|
|
297
|
+
: {}),
|
|
243
298
|
},
|
|
244
299
|
body: JSON.stringify({
|
|
245
300
|
signature,
|
|
@@ -266,7 +321,9 @@ async function authenticate(rawMessage, signature, authType, env, metametrics) {
|
|
|
266
321
|
identifierId: loginResponse.profile.identifier_id,
|
|
267
322
|
metaMetricsId: loginResponse.profile.metametrics_id,
|
|
268
323
|
profileId: loginResponse.profile.profile_id,
|
|
324
|
+
canonicalProfileId: loginResponse.profile.profile_id,
|
|
269
325
|
},
|
|
326
|
+
profileAliases: parseProfileAliases(loginResponse.profile_aliases ?? []),
|
|
270
327
|
};
|
|
271
328
|
}
|
|
272
329
|
catch (error) {
|
|
@@ -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 { 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';\nimport type {\n AccessToken,\n ErrorMessage,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\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 * Extracts error details from a Response object.\n *\n * @param response - The HTTP response object\n * @returns Formatted error message with HTTP status and response body\n */\nasync function getResponseErrorMessage(response: Response): Promise<string> {\n const { status } = response;\n const clonedResponse = response.clone();\n\n let message = 'Unknown error';\n let error = 'unknown';\n\n try {\n const responseBody = (await response.json()) as\n | ErrorMessage\n // eslint-disable-next-line @typescript-eslint/naming-convention\n | { error_description: string; error: string };\n\n message =\n 'message' in responseBody\n ? responseBody.message\n : responseBody.error_description;\n error = responseBody.error ?? 'unknown';\n } catch {\n try {\n const textContent = await clonedResponse.text();\n message = textContent\n ? textContent.slice(0, 150)\n : 'Non-JSON error response';\n error = 'non_json_response';\n } catch {\n message = 'Unable to parse error response';\n error = 'unparseable_response';\n }\n }\n\n return `HTTP ${status} - ${message} (error: ${error})`;\n}\n\n/**\n * Type guard to check if an object is a Response-like object.\n *\n * @param obj - The object to check\n * @returns True if the object is a Response-like object, false otherwise\n */\nconst isErrorResponse = (obj: unknown): obj is Response =>\n typeof obj === 'object' &&\n obj !== null &&\n 'status' in obj &&\n 'headers' in obj;\n\n/**\n * Throws a domain-specific error for service failures.\n * Handles both HTTP error responses and regular errors (network failures, etc.).\n * For HTTP 429, throws RateLimitedError with Retry-After header parsing.\n *\n * @param error - The error (Response object or caught error)\n * @param errorPrefix - Context prefix for the error message\n * @param ErrorClass - The domain-specific error class to throw\n * @throws RateLimitedError for 429, otherwise ErrorClass\n */\nasync function throwServiceError(\n error: unknown,\n errorPrefix: string,\n ErrorClass: new (message: string) => Error,\n): Promise<never> {\n // Re-throw RateLimitedError or matching ErrorClass as-is (don't double-wrap)\n if (error instanceof RateLimitedError || error instanceof ErrorClass) {\n throw error;\n }\n\n // Not a Response-like object - handle as regular error\n if (!isErrorResponse(error)) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new ErrorClass(`${errorPrefix}: ${errorMessage}`);\n }\n\n // Handle HTTP error response\n const response = error;\n const { status } = response;\n const responseMessage = await getResponseErrorMessage(response);\n\n if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfterMs = parseRetryAfter(retryAfterHeader);\n throw new RateLimitedError(\n `${errorPrefix}: ${responseMessage}`,\n retryAfterMs ?? undefined,\n );\n }\n\n throw new ErrorClass(`${errorPrefix}: ${responseMessage}`);\n}\n\nexport const NONCE_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env): string =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env): string =>\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 // eslint-disable-next-line @typescript-eslint/naming-convention\n raw_message: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n encrypted_storage_key: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\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 return await throwServiceError(\n response,\n 'Failed to pair identifiers',\n PairError,\n );\n }\n return undefined;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to pair identifiers',\n PairError,\n );\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 return await throwServiceError(\n nonceResponse,\n 'Failed to get nonce',\n NonceRetrievalError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get nonce',\n NonceRetrievalError,\n );\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 = {\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 return await throwServiceError(\n response,\n 'Failed to get access token',\n SignInError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get access token',\n SignInError,\n );\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 app_version: await metametrics.getAppVersion?.(),\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n return await throwServiceError(\n response,\n `Failed to login with ${authType}`,\n SignInError,\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 (error) {\n return await throwServiceError(\n error,\n `Failed to login with ${authType}`,\n SignInError,\n );\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 return await throwServiceError(\n response,\n 'Failed to get profile lineage',\n SignInError,\n );\n }\n\n const profileJson: UserProfileLineage = await response.json();\n return profileJson;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to get profile lineage',\n SignInError,\n );\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 { 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';\nimport { validatePairResponse } from '../utils/validate-pair-response';\nimport type {\n AccessToken,\n ErrorMessage,\n ProfileAlias,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\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 * Extracts error details from a Response object.\n *\n * @param response - The HTTP response object\n * @returns Formatted error message with HTTP status and response body\n */\nasync function getResponseErrorMessage(response: Response): Promise<string> {\n const { status } = response;\n const clonedResponse = response.clone();\n\n let message = 'Unknown error';\n let error = 'unknown';\n\n try {\n const responseBody = (await response.json()) as\n | ErrorMessage\n // eslint-disable-next-line @typescript-eslint/naming-convention\n | { error_description: string; error: string };\n\n message =\n 'message' in responseBody\n ? responseBody.message\n : responseBody.error_description;\n error = responseBody.error ?? 'unknown';\n } catch {\n try {\n const textContent = await clonedResponse.text();\n message = textContent\n ? textContent.slice(0, 150)\n : 'Non-JSON error response';\n error = 'non_json_response';\n } catch {\n message = 'Unable to parse error response';\n error = 'unparseable_response';\n }\n }\n\n return `HTTP ${status} - ${message} (error: ${error})`;\n}\n\n/**\n * Type guard to check if an object is a Response-like object.\n *\n * @param obj - The object to check\n * @returns True if the object is a Response-like object, false otherwise\n */\nconst isErrorResponse = (obj: unknown): obj is Response =>\n typeof obj === 'object' &&\n obj !== null &&\n 'status' in obj &&\n 'headers' in obj;\n\n/**\n * Throws a domain-specific error for service failures.\n * Handles both HTTP error responses and regular errors (network failures, etc.).\n * For HTTP 429, throws RateLimitedError with Retry-After header parsing.\n *\n * @param error - The error (Response object or caught error)\n * @param errorPrefix - Context prefix for the error message\n * @param ErrorClass - The domain-specific error class to throw\n * @throws RateLimitedError for 429, otherwise ErrorClass\n */\nasync function throwServiceError(\n error: unknown,\n errorPrefix: string,\n ErrorClass: new (message: string) => Error,\n): Promise<never> {\n // Re-throw RateLimitedError or matching ErrorClass as-is (don't double-wrap)\n if (error instanceof RateLimitedError || error instanceof ErrorClass) {\n throw error;\n }\n\n // Not a Response-like object - handle as regular error\n if (!isErrorResponse(error)) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new ErrorClass(`${errorPrefix}: ${errorMessage}`);\n }\n\n // Handle HTTP error response\n const response = error;\n const { status } = response;\n const responseMessage = await getResponseErrorMessage(response);\n\n if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfterMs = parseRetryAfter(retryAfterHeader);\n throw new RateLimitedError(\n `${errorPrefix}: ${responseMessage}`,\n retryAfterMs ?? undefined,\n );\n }\n\n throw new ErrorClass(`${errorPrefix}: ${responseMessage}`);\n}\n\nexport const NONCE_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env): string =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PAIR_PROFILES_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/profile/pair`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env): string =>\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 RawProfileAlias = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n alias_profile_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n canonical_profile_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n identifier_ids: { id: string; type: string }[];\n};\n\nconst parseProfileAliases = (raw: RawProfileAlias[]): ProfileAlias[] => {\n return raw.map((alias) => ({\n aliasProfileId: alias.alias_profile_id,\n canonicalProfileId: alias.canonical_profile_id,\n identifierIds: alias.identifier_ids ?? [],\n }));\n};\n\ntype PairRequest = {\n signature: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n raw_message: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n encrypted_storage_key: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\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 return await throwServiceError(\n response,\n 'Failed to pair identifiers',\n PairError,\n );\n }\n return undefined;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to pair identifiers',\n PairError,\n );\n }\n}\n\nexport type PairProfilesResponse = {\n profile: UserProfile;\n profileAliases: ProfileAlias[];\n};\n\n/**\n * Pair multiple profiles using their OIDC access tokens.\n * Idempotent — calling with already-paired tokens is a no-op.\n *\n * @param accessTokens - Two or more OIDC access tokens to pair\n * @param authAccessToken - A valid access token for the Authorization header\n * @param env - server environment\n * @returns The pair response containing the canonical profile and aliases\n */\nexport async function pairProfiles(\n accessTokens: string[],\n authAccessToken: string,\n env: Env,\n): Promise<PairProfilesResponse> {\n const pairUrl = new URL(PAIR_PROFILES_URL(env));\n\n try {\n const response = await fetch(pairUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${authAccessToken}`,\n },\n body: JSON.stringify({\n jwts: accessTokens,\n }),\n });\n\n if (!response.ok) {\n return await throwServiceError(\n response,\n 'Failed to pair profiles',\n PairError,\n );\n }\n\n const pairResponse: unknown = await response.json();\n validatePairResponse(pairResponse);\n\n return {\n profile: {\n identifierId: pairResponse.profile.identifier_id,\n metaMetricsId: pairResponse.profile.metametrics_id ?? '',\n profileId: pairResponse.profile.profile_id,\n canonicalProfileId: pairResponse.profile.profile_id,\n },\n profileAliases: parseProfileAliases(pairResponse.profile_aliases ?? []),\n };\n } catch (error) {\n return await throwServiceError(error, 'Failed to pair profiles', PairError);\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 return await throwServiceError(\n nonceResponse,\n 'Failed to get nonce',\n NonceRetrievalError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get nonce',\n NonceRetrievalError,\n );\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 = {\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 return await throwServiceError(\n response,\n 'Failed to get access token',\n SignInError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get access token',\n SignInError,\n );\n }\n}\n\ntype Authentication = {\n token: string;\n expiresIn: number;\n profile: UserProfile;\n profileAliases: ProfileAlias[];\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 ...(authType === AuthType.SRP\n ? { 'X-MetaMask-Profile-Pairing': 'enabled' }\n : {}),\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 app_version: await metametrics.getAppVersion?.(),\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n return await throwServiceError(\n response,\n `Failed to login with ${authType}`,\n SignInError,\n );\n }\n\n const loginResponse = await response.json();\n\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 canonicalProfileId: loginResponse.profile.profile_id,\n },\n profileAliases: parseProfileAliases(loginResponse.profile_aliases ?? []),\n };\n } catch (error) {\n return await throwServiceError(\n error,\n `Failed to login with ${authType}`,\n SignInError,\n );\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 return await throwServiceError(\n response,\n 'Failed to get profile lineage',\n SignInError,\n );\n }\n\n const profileJson: UserProfileLineage = await response.json();\n return profileJson;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to get profile lineage',\n SignInError,\n );\n }\n}\n"]}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { Env, Platform } from "../../shared/env.cjs";
|
|
2
2
|
import type { MetaMetricsAuth } from "../../shared/types/services.cjs";
|
|
3
|
-
import type { AccessToken, UserProfile, UserProfileLineage } from "./types.cjs";
|
|
3
|
+
import type { AccessToken, ProfileAlias, UserProfile, UserProfileLineage } from "./types.cjs";
|
|
4
4
|
import { AuthType } from "./types.cjs";
|
|
5
5
|
export declare const NONCE_URL: (env: Env) => string;
|
|
6
6
|
export declare const PAIR_IDENTIFIERS: (env: Env) => string;
|
|
7
7
|
export declare const OIDC_TOKEN_URL: (env: Env) => string;
|
|
8
8
|
export declare const SRP_LOGIN_URL: (env: Env) => string;
|
|
9
9
|
export declare const SIWE_LOGIN_URL: (env: Env) => string;
|
|
10
|
+
export declare const PAIR_PROFILES_URL: (env: Env) => string;
|
|
10
11
|
export declare const PROFILE_LINEAGE_URL: (env: Env) => string;
|
|
11
12
|
type NonceResponse = {
|
|
12
13
|
nonce: string;
|
|
@@ -29,6 +30,20 @@ type PairRequest = {
|
|
|
29
30
|
* @returns void.
|
|
30
31
|
*/
|
|
31
32
|
export declare function pairIdentifiers(nonce: string, logins: PairRequest[], accessToken: string, env: Env): Promise<void>;
|
|
33
|
+
export type PairProfilesResponse = {
|
|
34
|
+
profile: UserProfile;
|
|
35
|
+
profileAliases: ProfileAlias[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Pair multiple profiles using their OIDC access tokens.
|
|
39
|
+
* Idempotent — calling with already-paired tokens is a no-op.
|
|
40
|
+
*
|
|
41
|
+
* @param accessTokens - Two or more OIDC access tokens to pair
|
|
42
|
+
* @param authAccessToken - A valid access token for the Authorization header
|
|
43
|
+
* @param env - server environment
|
|
44
|
+
* @returns The pair response containing the canonical profile and aliases
|
|
45
|
+
*/
|
|
46
|
+
export declare function pairProfiles(accessTokens: string[], authAccessToken: string, env: Env): Promise<PairProfilesResponse>;
|
|
32
47
|
/**
|
|
33
48
|
* Service to Get Nonce for JWT Bearer Flow
|
|
34
49
|
*
|
|
@@ -50,6 +65,7 @@ type Authentication = {
|
|
|
50
65
|
token: string;
|
|
51
66
|
expiresIn: number;
|
|
52
67
|
profile: UserProfile;
|
|
68
|
+
profileAliases: ProfileAlias[];
|
|
53
69
|
};
|
|
54
70
|
/**
|
|
55
71
|
* Service to Authenticate/Login a user via SIWE or SRP derived key.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AAAA,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,EAAE,GAAG,EAAE,QAAQ,EAAE,6BAAyB;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAUnE,OAAO,KAAK,EACV,WAAW,EAEX,YAAY,EACZ,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AACjB,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AAwHnC,eAAO,MAAM,SAAS,QAAS,GAAG,KAAG,MACS,CAAC;AAE/C,eAAO,MAAM,gBAAgB,QAAS,GAAG,KAAG,MACa,CAAC;AAE1D,eAAO,MAAM,cAAc,QAAS,GAAG,KAAG,MACI,CAAC;AAE/C,eAAO,MAAM,aAAa,QAAS,GAAG,KAAG,MACS,CAAC;AAEnD,eAAO,MAAM,cAAc,QAAS,GAAG,KAAG,MACS,CAAC;AAEpD,eAAO,MAAM,iBAAiB,QAAS,GAAG,KAAG,MACQ,CAAC;AAEtD,eAAO,MAAM,mBAAmB,QAAS,GAAG,KAAG,MACS,CAAC;AAgBzD,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAmBF,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;IAElB,WAAW,EAAE,MAAM,CAAC;IAEpB,qBAAqB,EAAE,MAAM,CAAC;IAE9B,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,CA+Bf;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,EAAE,YAAY,EAAE,CAAC;CAChC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,MAAM,EACvB,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,oBAAoB,CAAC,CAsC/B;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CA2B3E;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,WAAW,CAAC,CAuCtB;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,EAAE,YAAY,EAAE,CAAC;CAChC,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,CAuDzB;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4B7B"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { Env, Platform } from "../../shared/env.mjs";
|
|
2
2
|
import type { MetaMetricsAuth } from "../../shared/types/services.mjs";
|
|
3
|
-
import type { AccessToken, UserProfile, UserProfileLineage } from "./types.mjs";
|
|
3
|
+
import type { AccessToken, ProfileAlias, UserProfile, UserProfileLineage } from "./types.mjs";
|
|
4
4
|
import { AuthType } from "./types.mjs";
|
|
5
5
|
export declare const NONCE_URL: (env: Env) => string;
|
|
6
6
|
export declare const PAIR_IDENTIFIERS: (env: Env) => string;
|
|
7
7
|
export declare const OIDC_TOKEN_URL: (env: Env) => string;
|
|
8
8
|
export declare const SRP_LOGIN_URL: (env: Env) => string;
|
|
9
9
|
export declare const SIWE_LOGIN_URL: (env: Env) => string;
|
|
10
|
+
export declare const PAIR_PROFILES_URL: (env: Env) => string;
|
|
10
11
|
export declare const PROFILE_LINEAGE_URL: (env: Env) => string;
|
|
11
12
|
type NonceResponse = {
|
|
12
13
|
nonce: string;
|
|
@@ -29,6 +30,20 @@ type PairRequest = {
|
|
|
29
30
|
* @returns void.
|
|
30
31
|
*/
|
|
31
32
|
export declare function pairIdentifiers(nonce: string, logins: PairRequest[], accessToken: string, env: Env): Promise<void>;
|
|
33
|
+
export type PairProfilesResponse = {
|
|
34
|
+
profile: UserProfile;
|
|
35
|
+
profileAliases: ProfileAlias[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Pair multiple profiles using their OIDC access tokens.
|
|
39
|
+
* Idempotent — calling with already-paired tokens is a no-op.
|
|
40
|
+
*
|
|
41
|
+
* @param accessTokens - Two or more OIDC access tokens to pair
|
|
42
|
+
* @param authAccessToken - A valid access token for the Authorization header
|
|
43
|
+
* @param env - server environment
|
|
44
|
+
* @returns The pair response containing the canonical profile and aliases
|
|
45
|
+
*/
|
|
46
|
+
export declare function pairProfiles(accessTokens: string[], authAccessToken: string, env: Env): Promise<PairProfilesResponse>;
|
|
32
47
|
/**
|
|
33
48
|
* Service to Get Nonce for JWT Bearer Flow
|
|
34
49
|
*
|
|
@@ -50,6 +65,7 @@ type Authentication = {
|
|
|
50
65
|
token: string;
|
|
51
66
|
expiresIn: number;
|
|
52
67
|
profile: UserProfile;
|
|
68
|
+
profileAliases: ProfileAlias[];
|
|
53
69
|
};
|
|
54
70
|
/**
|
|
55
71
|
* Service to Authenticate/Login a user via SIWE or SRP derived key.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AAAA,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,EAAE,GAAG,EAAE,QAAQ,EAAE,6BAAyB;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAUnE,OAAO,KAAK,EACV,WAAW,EAEX,YAAY,EACZ,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AACjB,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AAwHnC,eAAO,MAAM,SAAS,QAAS,GAAG,KAAG,MACS,CAAC;AAE/C,eAAO,MAAM,gBAAgB,QAAS,GAAG,KAAG,MACa,CAAC;AAE1D,eAAO,MAAM,cAAc,QAAS,GAAG,KAAG,MACI,CAAC;AAE/C,eAAO,MAAM,aAAa,QAAS,GAAG,KAAG,MACS,CAAC;AAEnD,eAAO,MAAM,cAAc,QAAS,GAAG,KAAG,MACS,CAAC;AAEpD,eAAO,MAAM,iBAAiB,QAAS,GAAG,KAAG,MACQ,CAAC;AAEtD,eAAO,MAAM,mBAAmB,QAAS,GAAG,KAAG,MACS,CAAC;AAgBzD,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAmBF,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;IAElB,WAAW,EAAE,MAAM,CAAC;IAEpB,qBAAqB,EAAE,MAAM,CAAC;IAE9B,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,CA+Bf;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,EAAE,YAAY,EAAE,CAAC;CAChC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,MAAM,EACvB,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,oBAAoB,CAAC,CAsC/B;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CA2B3E;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,WAAW,CAAC,CAuCtB;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,EAAE,YAAY,EAAE,CAAC;CAChC,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,CAuDzB;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4B7B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getEnvUrls, getOidcClientId } from "../../shared/env.mjs";
|
|
2
2
|
import { HTTP_STATUS_CODES } from "../constants.mjs";
|
|
3
3
|
import { NonceRetrievalError, PairError, SignInError, ValidationError, RateLimitedError } from "../errors.mjs";
|
|
4
|
+
import { validatePairResponse } from "../utils/validate-pair-response.mjs";
|
|
4
5
|
import { AuthType } from "./types.mjs";
|
|
5
6
|
/**
|
|
6
7
|
* Parse Retry-After header into milliseconds if possible.
|
|
@@ -104,6 +105,7 @@ export const PAIR_IDENTIFIERS = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/i
|
|
|
104
105
|
export const OIDC_TOKEN_URL = (env) => `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;
|
|
105
106
|
export const SRP_LOGIN_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;
|
|
106
107
|
export const SIWE_LOGIN_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;
|
|
108
|
+
export const PAIR_PROFILES_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/profile/pair`;
|
|
107
109
|
export const PROFILE_LINEAGE_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/profile/lineage`;
|
|
108
110
|
const getAuthenticationUrl = (authType, env) => {
|
|
109
111
|
switch (authType) {
|
|
@@ -116,6 +118,13 @@ const getAuthenticationUrl = (authType, env) => {
|
|
|
116
118
|
throw new ValidationError(`Invalid AuthType: ${authType} - unable to create Auth URL`);
|
|
117
119
|
}
|
|
118
120
|
};
|
|
121
|
+
const parseProfileAliases = (raw) => {
|
|
122
|
+
return raw.map((alias) => ({
|
|
123
|
+
aliasProfileId: alias.alias_profile_id,
|
|
124
|
+
canonicalProfileId: alias.canonical_profile_id,
|
|
125
|
+
identifierIds: alias.identifier_ids ?? [],
|
|
126
|
+
}));
|
|
127
|
+
};
|
|
119
128
|
/**
|
|
120
129
|
* Pair multiple identifiers under a single profile
|
|
121
130
|
*
|
|
@@ -148,6 +157,47 @@ export async function pairIdentifiers(nonce, logins, accessToken, env) {
|
|
|
148
157
|
return await throwServiceError(error, 'Failed to pair identifiers', PairError);
|
|
149
158
|
}
|
|
150
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Pair multiple profiles using their OIDC access tokens.
|
|
162
|
+
* Idempotent — calling with already-paired tokens is a no-op.
|
|
163
|
+
*
|
|
164
|
+
* @param accessTokens - Two or more OIDC access tokens to pair
|
|
165
|
+
* @param authAccessToken - A valid access token for the Authorization header
|
|
166
|
+
* @param env - server environment
|
|
167
|
+
* @returns The pair response containing the canonical profile and aliases
|
|
168
|
+
*/
|
|
169
|
+
export async function pairProfiles(accessTokens, authAccessToken, env) {
|
|
170
|
+
const pairUrl = new URL(PAIR_PROFILES_URL(env));
|
|
171
|
+
try {
|
|
172
|
+
const response = await fetch(pairUrl, {
|
|
173
|
+
method: 'POST',
|
|
174
|
+
headers: {
|
|
175
|
+
'Content-Type': 'application/json',
|
|
176
|
+
Authorization: `Bearer ${authAccessToken}`,
|
|
177
|
+
},
|
|
178
|
+
body: JSON.stringify({
|
|
179
|
+
jwts: accessTokens,
|
|
180
|
+
}),
|
|
181
|
+
});
|
|
182
|
+
if (!response.ok) {
|
|
183
|
+
return await throwServiceError(response, 'Failed to pair profiles', PairError);
|
|
184
|
+
}
|
|
185
|
+
const pairResponse = await response.json();
|
|
186
|
+
validatePairResponse(pairResponse);
|
|
187
|
+
return {
|
|
188
|
+
profile: {
|
|
189
|
+
identifierId: pairResponse.profile.identifier_id,
|
|
190
|
+
metaMetricsId: pairResponse.profile.metametrics_id ?? '',
|
|
191
|
+
profileId: pairResponse.profile.profile_id,
|
|
192
|
+
canonicalProfileId: pairResponse.profile.profile_id,
|
|
193
|
+
},
|
|
194
|
+
profileAliases: parseProfileAliases(pairResponse.profile_aliases ?? []),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
return await throwServiceError(error, 'Failed to pair profiles', PairError);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
151
201
|
/**
|
|
152
202
|
* Service to Get Nonce for JWT Bearer Flow
|
|
153
203
|
*
|
|
@@ -228,6 +278,9 @@ export async function authenticate(rawMessage, signature, authType, env, metamet
|
|
|
228
278
|
method: 'POST',
|
|
229
279
|
headers: {
|
|
230
280
|
'Content-Type': 'application/json',
|
|
281
|
+
...(authType === AuthType.SRP
|
|
282
|
+
? { 'X-MetaMask-Profile-Pairing': 'enabled' }
|
|
283
|
+
: {}),
|
|
231
284
|
},
|
|
232
285
|
body: JSON.stringify({
|
|
233
286
|
signature,
|
|
@@ -254,7 +307,9 @@ export async function authenticate(rawMessage, signature, authType, env, metamet
|
|
|
254
307
|
identifierId: loginResponse.profile.identifier_id,
|
|
255
308
|
metaMetricsId: loginResponse.profile.metametrics_id,
|
|
256
309
|
profileId: loginResponse.profile.profile_id,
|
|
310
|
+
canonicalProfileId: loginResponse.profile.profile_id,
|
|
257
311
|
},
|
|
312
|
+
profileAliases: parseProfileAliases(loginResponse.profile_aliases ?? []),
|
|
258
313
|
};
|
|
259
314
|
}
|
|
260
315
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/services.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,6BAAyB;AAE/D,OAAO,EAAE,iBAAiB,EAAE,yBAAqB;AACjD,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,WAAW,EACX,eAAe,EACf,gBAAgB,EACjB,sBAAkB;AAOnB,OAAO,EAAE,QAAQ,EAAE,oBAAgB;AAEnC;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,gBAA+B;IACtD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO,GAAG,IAAI,CAAC;IACxB,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,uBAAuB,CAAC,QAAkB;IACvD,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IAC5B,MAAM,cAAc,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;IAExC,IAAI,OAAO,GAAG,eAAe,CAAC;IAC9B,IAAI,KAAK,GAAG,SAAS,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGK,CAAC;QAEjD,OAAO;YACL,SAAS,IAAI,YAAY;gBACvB,CAAC,CAAC,YAAY,CAAC,OAAO;gBACtB,CAAC,CAAC,YAAY,CAAC,iBAAiB,CAAC;QACrC,KAAK,GAAG,YAAY,CAAC,KAAK,IAAI,SAAS,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC;YAChD,OAAO,GAAG,WAAW;gBACnB,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBAC3B,CAAC,CAAC,yBAAyB,CAAC;YAC9B,KAAK,GAAG,mBAAmB,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,gCAAgC,CAAC;YAC3C,KAAK,GAAG,sBAAsB,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,MAAM,MAAM,OAAO,YAAY,KAAK,GAAG,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,eAAe,GAAG,CAAC,GAAY,EAAmB,EAAE,CACxD,OAAO,GAAG,KAAK,QAAQ;IACvB,GAAG,KAAK,IAAI;IACZ,QAAQ,IAAI,GAAG;IACf,SAAS,IAAI,GAAG,CAAC;AAEnB;;;;;;;;;GASG;AACH,KAAK,UAAU,iBAAiB,CAC9B,KAAc,EACd,WAAmB,EACnB,UAA0C;IAE1C,6EAA6E;IAC7E,IAAI,KAAK,YAAY,gBAAgB,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QACrE,MAAM,KAAK,CAAC;IACd,CAAC;IAED,uDAAuD;IACvD,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,IAAI,UAAU,CAAC,GAAG,WAAW,KAAK,YAAY,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IAC5B,MAAM,eAAe,GAAG,MAAM,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAEhE,IAAI,MAAM,KAAK,iBAAiB,CAAC,iBAAiB,EAAE,CAAC;QACnD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAAC;QACvD,MAAM,IAAI,gBAAgB,CACxB,GAAG,WAAW,KAAK,eAAe,EAAE,EACpC,YAAY,IAAI,SAAS,CAC1B,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,UAAU,CAAC,GAAG,WAAW,KAAK,eAAe,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAQ,EAAU,EAAE,CAC5C,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAQ,EAAU,EAAE,CACnD,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,0BAA0B,CAAC;AAE1D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAQ,EAAU,EAAE,CACjD,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAQ,EAAU,EAAE,CAChD,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,mBAAmB,CAAC;AAEnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAQ,EAAU,EAAE,CACjD,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,oBAAoB,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAQ,EAAU,EAAE,CACtD,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;AAkBF;;;;;;;;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,OAAO,MAAM,iBAAiB,CAC5B,QAAQ,EACR,4BAA4B,EAC5B,SAAS,CACV,CAAC;QACJ,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,iBAAiB,CAC5B,KAAK,EACL,4BAA4B,EAC5B,SAAS,CACV,CAAC;IACJ,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,OAAO,MAAM,iBAAiB,CAC5B,aAAa,EACb,qBAAqB,EACrB,mBAAmB,CACpB,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,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,iBAAiB,CAC5B,KAAK,EACL,qBAAqB,EACrB,mBAAmB,CACpB,CAAC;IACJ,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;QACd,cAAc,EAAE,mCAAmC;KACpD,CAAC;IAEF,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,OAAO,MAAM,iBAAiB,CAC5B,QAAQ,EACR,4BAA4B,EAC5B,WAAW,CACZ,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,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,iBAAiB,CAC5B,KAAK,EACL,4BAA4B,EAC5B,WAAW,CACZ,CAAC;IACJ,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;4BACxB,WAAW,EAAE,MAAM,WAAW,CAAC,aAAa,EAAE,EAAE;yBACjD;qBACF;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,MAAM,iBAAiB,CAC5B,QAAQ,EACR,wBAAwB,QAAQ,EAAE,EAClC,WAAW,CACZ,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,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,iBAAiB,CAC5B,KAAK,EACL,wBAAwB,QAAQ,EAAE,EAClC,WAAW,CACZ,CAAC;IACJ,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,OAAO,MAAM,iBAAiB,CAC5B,QAAQ,EACR,+BAA+B,EAC/B,WAAW,CACZ,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAuB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC9D,OAAO,WAAW,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,iBAAiB,CAC5B,KAAK,EACL,+BAA+B,EAC/B,WAAW,CACZ,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import 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';\nimport type {\n AccessToken,\n ErrorMessage,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\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 * Extracts error details from a Response object.\n *\n * @param response - The HTTP response object\n * @returns Formatted error message with HTTP status and response body\n */\nasync function getResponseErrorMessage(response: Response): Promise<string> {\n const { status } = response;\n const clonedResponse = response.clone();\n\n let message = 'Unknown error';\n let error = 'unknown';\n\n try {\n const responseBody = (await response.json()) as\n | ErrorMessage\n // eslint-disable-next-line @typescript-eslint/naming-convention\n | { error_description: string; error: string };\n\n message =\n 'message' in responseBody\n ? responseBody.message\n : responseBody.error_description;\n error = responseBody.error ?? 'unknown';\n } catch {\n try {\n const textContent = await clonedResponse.text();\n message = textContent\n ? textContent.slice(0, 150)\n : 'Non-JSON error response';\n error = 'non_json_response';\n } catch {\n message = 'Unable to parse error response';\n error = 'unparseable_response';\n }\n }\n\n return `HTTP ${status} - ${message} (error: ${error})`;\n}\n\n/**\n * Type guard to check if an object is a Response-like object.\n *\n * @param obj - The object to check\n * @returns True if the object is a Response-like object, false otherwise\n */\nconst isErrorResponse = (obj: unknown): obj is Response =>\n typeof obj === 'object' &&\n obj !== null &&\n 'status' in obj &&\n 'headers' in obj;\n\n/**\n * Throws a domain-specific error for service failures.\n * Handles both HTTP error responses and regular errors (network failures, etc.).\n * For HTTP 429, throws RateLimitedError with Retry-After header parsing.\n *\n * @param error - The error (Response object or caught error)\n * @param errorPrefix - Context prefix for the error message\n * @param ErrorClass - The domain-specific error class to throw\n * @throws RateLimitedError for 429, otherwise ErrorClass\n */\nasync function throwServiceError(\n error: unknown,\n errorPrefix: string,\n ErrorClass: new (message: string) => Error,\n): Promise<never> {\n // Re-throw RateLimitedError or matching ErrorClass as-is (don't double-wrap)\n if (error instanceof RateLimitedError || error instanceof ErrorClass) {\n throw error;\n }\n\n // Not a Response-like object - handle as regular error\n if (!isErrorResponse(error)) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new ErrorClass(`${errorPrefix}: ${errorMessage}`);\n }\n\n // Handle HTTP error response\n const response = error;\n const { status } = response;\n const responseMessage = await getResponseErrorMessage(response);\n\n if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfterMs = parseRetryAfter(retryAfterHeader);\n throw new RateLimitedError(\n `${errorPrefix}: ${responseMessage}`,\n retryAfterMs ?? undefined,\n );\n }\n\n throw new ErrorClass(`${errorPrefix}: ${responseMessage}`);\n}\n\nexport const NONCE_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env): string =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env): string =>\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 // eslint-disable-next-line @typescript-eslint/naming-convention\n raw_message: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n encrypted_storage_key: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\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 return await throwServiceError(\n response,\n 'Failed to pair identifiers',\n PairError,\n );\n }\n return undefined;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to pair identifiers',\n PairError,\n );\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 return await throwServiceError(\n nonceResponse,\n 'Failed to get nonce',\n NonceRetrievalError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get nonce',\n NonceRetrievalError,\n );\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 = {\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 return await throwServiceError(\n response,\n 'Failed to get access token',\n SignInError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get access token',\n SignInError,\n );\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 app_version: await metametrics.getAppVersion?.(),\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n return await throwServiceError(\n response,\n `Failed to login with ${authType}`,\n SignInError,\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 (error) {\n return await throwServiceError(\n error,\n `Failed to login with ${authType}`,\n SignInError,\n );\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 return await throwServiceError(\n response,\n 'Failed to get profile lineage',\n SignInError,\n );\n }\n\n const profileJson: UserProfileLineage = await response.json();\n return profileJson;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to get profile lineage',\n SignInError,\n );\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 { 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';\nimport { validatePairResponse } from '../utils/validate-pair-response';\nimport type {\n AccessToken,\n ErrorMessage,\n ProfileAlias,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport { AuthType } from './types';\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 * Extracts error details from a Response object.\n *\n * @param response - The HTTP response object\n * @returns Formatted error message with HTTP status and response body\n */\nasync function getResponseErrorMessage(response: Response): Promise<string> {\n const { status } = response;\n const clonedResponse = response.clone();\n\n let message = 'Unknown error';\n let error = 'unknown';\n\n try {\n const responseBody = (await response.json()) as\n | ErrorMessage\n // eslint-disable-next-line @typescript-eslint/naming-convention\n | { error_description: string; error: string };\n\n message =\n 'message' in responseBody\n ? responseBody.message\n : responseBody.error_description;\n error = responseBody.error ?? 'unknown';\n } catch {\n try {\n const textContent = await clonedResponse.text();\n message = textContent\n ? textContent.slice(0, 150)\n : 'Non-JSON error response';\n error = 'non_json_response';\n } catch {\n message = 'Unable to parse error response';\n error = 'unparseable_response';\n }\n }\n\n return `HTTP ${status} - ${message} (error: ${error})`;\n}\n\n/**\n * Type guard to check if an object is a Response-like object.\n *\n * @param obj - The object to check\n * @returns True if the object is a Response-like object, false otherwise\n */\nconst isErrorResponse = (obj: unknown): obj is Response =>\n typeof obj === 'object' &&\n obj !== null &&\n 'status' in obj &&\n 'headers' in obj;\n\n/**\n * Throws a domain-specific error for service failures.\n * Handles both HTTP error responses and regular errors (network failures, etc.).\n * For HTTP 429, throws RateLimitedError with Retry-After header parsing.\n *\n * @param error - The error (Response object or caught error)\n * @param errorPrefix - Context prefix for the error message\n * @param ErrorClass - The domain-specific error class to throw\n * @throws RateLimitedError for 429, otherwise ErrorClass\n */\nasync function throwServiceError(\n error: unknown,\n errorPrefix: string,\n ErrorClass: new (message: string) => Error,\n): Promise<never> {\n // Re-throw RateLimitedError or matching ErrorClass as-is (don't double-wrap)\n if (error instanceof RateLimitedError || error instanceof ErrorClass) {\n throw error;\n }\n\n // Not a Response-like object - handle as regular error\n if (!isErrorResponse(error)) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new ErrorClass(`${errorPrefix}: ${errorMessage}`);\n }\n\n // Handle HTTP error response\n const response = error;\n const { status } = response;\n const responseMessage = await getResponseErrorMessage(response);\n\n if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfterMs = parseRetryAfter(retryAfterHeader);\n throw new RateLimitedError(\n `${errorPrefix}: ${responseMessage}`,\n retryAfterMs ?? undefined,\n );\n }\n\n throw new ErrorClass(`${errorPrefix}: ${responseMessage}`);\n}\n\nexport const NONCE_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/nonce`;\n\nexport const PAIR_IDENTIFIERS = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/identifiers/pair`;\n\nexport const OIDC_TOKEN_URL = (env: Env): string =>\n `${getEnvUrls(env).oidcApiUrl}/oauth2/token`;\n\nexport const SRP_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/srp/login`;\n\nexport const SIWE_LOGIN_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/siwe/login`;\n\nexport const PAIR_PROFILES_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/profile/pair`;\n\nexport const PROFILE_LINEAGE_URL = (env: Env): string =>\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 RawProfileAlias = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n alias_profile_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n canonical_profile_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n identifier_ids: { id: string; type: string }[];\n};\n\nconst parseProfileAliases = (raw: RawProfileAlias[]): ProfileAlias[] => {\n return raw.map((alias) => ({\n aliasProfileId: alias.alias_profile_id,\n canonicalProfileId: alias.canonical_profile_id,\n identifierIds: alias.identifier_ids ?? [],\n }));\n};\n\ntype PairRequest = {\n signature: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n raw_message: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n encrypted_storage_key: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\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 return await throwServiceError(\n response,\n 'Failed to pair identifiers',\n PairError,\n );\n }\n return undefined;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to pair identifiers',\n PairError,\n );\n }\n}\n\nexport type PairProfilesResponse = {\n profile: UserProfile;\n profileAliases: ProfileAlias[];\n};\n\n/**\n * Pair multiple profiles using their OIDC access tokens.\n * Idempotent — calling with already-paired tokens is a no-op.\n *\n * @param accessTokens - Two or more OIDC access tokens to pair\n * @param authAccessToken - A valid access token for the Authorization header\n * @param env - server environment\n * @returns The pair response containing the canonical profile and aliases\n */\nexport async function pairProfiles(\n accessTokens: string[],\n authAccessToken: string,\n env: Env,\n): Promise<PairProfilesResponse> {\n const pairUrl = new URL(PAIR_PROFILES_URL(env));\n\n try {\n const response = await fetch(pairUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${authAccessToken}`,\n },\n body: JSON.stringify({\n jwts: accessTokens,\n }),\n });\n\n if (!response.ok) {\n return await throwServiceError(\n response,\n 'Failed to pair profiles',\n PairError,\n );\n }\n\n const pairResponse: unknown = await response.json();\n validatePairResponse(pairResponse);\n\n return {\n profile: {\n identifierId: pairResponse.profile.identifier_id,\n metaMetricsId: pairResponse.profile.metametrics_id ?? '',\n profileId: pairResponse.profile.profile_id,\n canonicalProfileId: pairResponse.profile.profile_id,\n },\n profileAliases: parseProfileAliases(pairResponse.profile_aliases ?? []),\n };\n } catch (error) {\n return await throwServiceError(error, 'Failed to pair profiles', PairError);\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 return await throwServiceError(\n nonceResponse,\n 'Failed to get nonce',\n NonceRetrievalError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get nonce',\n NonceRetrievalError,\n );\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 = {\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 return await throwServiceError(\n response,\n 'Failed to get access token',\n SignInError,\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 (error) {\n return await throwServiceError(\n error,\n 'Failed to get access token',\n SignInError,\n );\n }\n}\n\ntype Authentication = {\n token: string;\n expiresIn: number;\n profile: UserProfile;\n profileAliases: ProfileAlias[];\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 ...(authType === AuthType.SRP\n ? { 'X-MetaMask-Profile-Pairing': 'enabled' }\n : {}),\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 app_version: await metametrics.getAppVersion?.(),\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n return await throwServiceError(\n response,\n `Failed to login with ${authType}`,\n SignInError,\n );\n }\n\n const loginResponse = await response.json();\n\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 canonicalProfileId: loginResponse.profile.profile_id,\n },\n profileAliases: parseProfileAliases(loginResponse.profile_aliases ?? []),\n };\n } catch (error) {\n return await throwServiceError(\n error,\n `Failed to login with ${authType}`,\n SignInError,\n );\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 return await throwServiceError(\n response,\n 'Failed to get profile lineage',\n SignInError,\n );\n }\n\n const profileJson: UserProfileLineage = await response.json();\n return profileJson;\n } catch (error) {\n return await throwServiceError(\n error,\n 'Failed to get profile lineage',\n SignInError,\n );\n }\n}\n"]}
|