@metamask/profile-sync-controller 28.0.1 → 28.1.0
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 +39 -1
- package/dist/controllers/authentication/AuthenticationController-method-action-types.cjs.map +1 -1
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.cts +45 -6
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.cts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.mts +45 -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 +170 -8
- package/dist/controllers/authentication/AuthenticationController.cjs.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.d.cts +64 -10
- package/dist/controllers/authentication/AuthenticationController.d.cts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.d.mts +64 -10
- package/dist/controllers/authentication/AuthenticationController.d.mts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.mjs +170 -8
- package/dist/controllers/authentication/AuthenticationController.mjs.map +1 -1
- package/dist/controllers/authentication/auth-snap-requests.cjs.map +1 -1
- package/dist/controllers/authentication/auth-snap-requests.d.cts +2 -2
- package/dist/controllers/authentication/auth-snap-requests.d.cts.map +1 -1
- package/dist/controllers/authentication/auth-snap-requests.d.mts +2 -2
- package/dist/controllers/authentication/auth-snap-requests.d.mts.map +1 -1
- package/dist/controllers/authentication/auth-snap-requests.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/controllers/user-storage/UserStorageController.cjs +3 -3
- package/dist/controllers/user-storage/UserStorageController.cjs.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.d.cts +4 -4
- package/dist/controllers/user-storage/UserStorageController.d.cts.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.d.mts +4 -4
- package/dist/controllers/user-storage/UserStorageController.d.mts.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.mjs +3 -3
- package/dist/controllers/user-storage/UserStorageController.mjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.cjs +2 -2
- package/dist/controllers/user-storage/contact-syncing/controller-integration.cjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.d.cts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.d.mts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.mjs +2 -2
- package/dist/controllers/user-storage/contact-syncing/controller-integration.mjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.cjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.d.cts +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.d.cts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.d.mts +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.d.mts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.mjs.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.cjs +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.cjs.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.d.cts.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.d.mts.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.mjs +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-siwe.cjs +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-siwe.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-siwe.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-siwe.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-siwe.mjs +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-siwe.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs +30 -3
- package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.cts +3 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.mts +3 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.mjs +30 -3
- package/dist/sdk/authentication-jwt-bearer/flow-srp.mjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.cjs +60 -2
- package/dist/sdk/authentication-jwt-bearer/services.cjs.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.cts +18 -2
- package/dist/sdk/authentication-jwt-bearer/services.d.cts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.d.mts +18 -2
- package/dist/sdk/authentication-jwt-bearer/services.d.mts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/services.mjs +57 -1
- 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 +27 -4
- package/dist/sdk/user-storage.cjs.map +1 -1
- package/dist/sdk/user-storage.d.cts +8 -1
- package/dist/sdk/user-storage.d.cts.map +1 -1
- package/dist/sdk/user-storage.d.mts +8 -1
- package/dist/sdk/user-storage.d.mts.map +1 -1
- package/dist/sdk/user-storage.mjs +27 -4
- 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/dist/shared/encryption/encryption.cjs.map +1 -1
- package/dist/shared/encryption/encryption.d.cts.map +1 -1
- package/dist/shared/encryption/encryption.d.mts.map +1 -1
- package/dist/shared/encryption/encryption.mjs.map +1 -1
- package/dist/shared/types/services.cjs.map +1 -1
- package/dist/shared/types/services.d.cts +7 -0
- package/dist/shared/types/services.d.cts.map +1 -1
- package/dist/shared/types/services.d.mts +7 -0
- package/dist/shared/types/services.d.mts.map +1 -1
- package/dist/shared/types/services.mjs.map +1 -1
- package/package.json +28 -29
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { MOCK_ENCRYPTED_STORAGE_DATA, MOCK_STORAGE_DATA, MOCK_STORAGE_KEY } from "./mockStorage.mjs";
|
|
2
1
|
import { Env, getEnvUrls } from "../../../sdk/index.mjs";
|
|
3
2
|
import { createEntryPath, USER_STORAGE_FEATURE_NAMES } from "../../../shared/storage-schema.mjs";
|
|
3
|
+
import { MOCK_ENCRYPTED_STORAGE_DATA, MOCK_STORAGE_DATA, MOCK_STORAGE_KEY } from "./mockStorage.mjs";
|
|
4
4
|
export const getMockUserStorageEndpoint = (path) => {
|
|
5
5
|
if (path.split('.').length === 1) {
|
|
6
6
|
return `${getEnvUrls(Env.PRD).userStorageApiUrl}/api/v1/userstorage/${path}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockResponses.mjs","sourceRoot":"","sources":["../../../../src/controllers/user-storage/mocks/mockResponses.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"mockResponses.mjs","sourceRoot":"","sources":["../../../../src/controllers/user-storage/mocks/mockResponses.ts"],"names":[],"mappings":"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","sourcesContent":["import { Env, getEnvUrls } from '../../../sdk';\nimport type {\n UserStorageGenericPathWithFeatureAndKey,\n UserStorageGenericPathWithFeatureOnly,\n} from '../../../shared/storage-schema';\nimport {\n createEntryPath,\n USER_STORAGE_FEATURE_NAMES,\n} from '../../../shared/storage-schema';\nimport type {\n GetUserStorageAllFeatureEntriesResponse,\n GetUserStorageResponse,\n} from '../types';\nimport {\n MOCK_ENCRYPTED_STORAGE_DATA,\n MOCK_STORAGE_DATA,\n MOCK_STORAGE_KEY,\n} from './mockStorage';\n\ntype MockResponse = {\n url: string;\n requestMethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n response: unknown;\n};\n\nexport const getMockUserStorageEndpoint = (\n path:\n | UserStorageGenericPathWithFeatureAndKey\n | UserStorageGenericPathWithFeatureOnly,\n) => {\n if (path.split('.').length === 1) {\n return `${getEnvUrls(Env.PRD).userStorageApiUrl}/api/v1/userstorage/${path}`;\n }\n\n return `${getEnvUrls(Env.PRD).userStorageApiUrl}/api/v1/userstorage/${createEntryPath(\n path as UserStorageGenericPathWithFeatureAndKey,\n MOCK_STORAGE_KEY,\n )}`;\n};\n\n/**\n * Creates a mock GET user-storage response\n *\n * @param data - data to encrypt\n * @returns a realistic GET Response Body\n */\nexport async function createMockGetStorageResponse(\n data?: string,\n): Promise<GetUserStorageResponse> {\n return {\n HashedKey: 'HASHED_KEY',\n Data: await MOCK_ENCRYPTED_STORAGE_DATA(data),\n };\n}\n\n/**\n * Creates a mock GET ALL user-storage response\n *\n * @param dataArr - array of data to encrypt\n * @returns a realistic GET ALL Response Body\n */\nexport async function createMockAllFeatureEntriesResponse(\n dataArr: string[] = [MOCK_STORAGE_DATA],\n): Promise<GetUserStorageAllFeatureEntriesResponse> {\n const decryptedData = [];\n\n for (const data of dataArr) {\n decryptedData.push({\n HashedKey: 'HASHED_KEY',\n Data: await MOCK_ENCRYPTED_STORAGE_DATA(data),\n });\n }\n\n return decryptedData;\n}\n\n/**\n * Creates a mock user-storage api GET request\n *\n * @param path - path of the GET Url\n * @returns mock GET API request. Can be used by e2e or unit mock servers\n */\nexport async function getMockUserStorageGetResponse(\n path: UserStorageGenericPathWithFeatureAndKey = `${USER_STORAGE_FEATURE_NAMES.notifications}.notification_settings`,\n) {\n return {\n url: getMockUserStorageEndpoint(path),\n requestMethod: 'GET',\n response: await createMockGetStorageResponse(),\n } satisfies MockResponse;\n}\n\n/**\n * Creates a mock user-storage api GET ALL request\n *\n * @param path - path of the GET url\n * @param dataArr - data to encrypt\n * @returns mock GET ALL API request. Can be used by e2e or unit mock servers\n */\nexport async function getMockUserStorageAllFeatureEntriesResponse(\n path: UserStorageGenericPathWithFeatureOnly = USER_STORAGE_FEATURE_NAMES.notifications,\n dataArr?: string[],\n) {\n return {\n url: getMockUserStorageEndpoint(path),\n requestMethod: 'GET',\n response: await createMockAllFeatureEntriesResponse(dataArr),\n } satisfies MockResponse;\n}\n\nexport const getMockUserStoragePutResponse = (\n path: UserStorageGenericPathWithFeatureAndKey = `${USER_STORAGE_FEATURE_NAMES.notifications}.notification_settings`,\n) => {\n return {\n url: getMockUserStorageEndpoint(path),\n requestMethod: 'PUT',\n response: null,\n } satisfies MockResponse;\n};\n\nexport const getMockUserStorageBatchPutResponse = (\n path: UserStorageGenericPathWithFeatureOnly = USER_STORAGE_FEATURE_NAMES.notifications,\n) => {\n return {\n url: getMockUserStorageEndpoint(path),\n requestMethod: 'PUT',\n response: null,\n } satisfies MockResponse;\n};\n\nexport const getMockUserStorageBatchDeleteResponse = (\n path: UserStorageGenericPathWithFeatureOnly = USER_STORAGE_FEATURE_NAMES.notifications,\n) => {\n return {\n url: getMockUserStorageEndpoint(path),\n requestMethod: 'PUT',\n response: null,\n } satisfies MockResponse;\n};\n\nexport const deleteMockUserStorageResponse = (\n path: UserStorageGenericPathWithFeatureAndKey = `${USER_STORAGE_FEATURE_NAMES.notifications}.notification_settings`,\n) => {\n return {\n url: getMockUserStorageEndpoint(path),\n requestMethod: 'DELETE',\n response: null,\n } satisfies MockResponse;\n};\n\nexport const deleteMockUserStorageAllFeatureEntriesResponse = (\n path: UserStorageGenericPathWithFeatureOnly = USER_STORAGE_FEATURE_NAMES.notifications,\n) => {\n return {\n url: getMockUserStorageEndpoint(path),\n requestMethod: 'DELETE',\n response: null,\n } satisfies MockResponse;\n};\n"]}
|
|
@@ -14,9 +14,9 @@ var _SIWEJwtBearerAuth_instances, _SIWEJwtBearerAuth_config, _SIWEJwtBearerAuth_
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.SIWEJwtBearerAuth = void 0;
|
|
16
16
|
const siwe_1 = require("siwe");
|
|
17
|
-
const services_1 = require("./services.cjs");
|
|
18
17
|
const errors_1 = require("../errors.cjs");
|
|
19
18
|
const validate_login_response_1 = require("../utils/validate-login-response.cjs");
|
|
19
|
+
const services_1 = require("./services.cjs");
|
|
20
20
|
class SIWEJwtBearerAuth {
|
|
21
21
|
constructor(config, options) {
|
|
22
22
|
_SIWEJwtBearerAuth_instances.add(this);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-siwe.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+BAAmC;AAEnC,
|
|
1
|
+
{"version":3,"file":"flow-siwe.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+BAAmC;AAEnC,0CAA4C;AAC5C,kFAAyE;AACzE,6CAMoB;AAsBpB,MAAa,iBAAiB;IAO5B,YACE,MAA4C,EAC5C,OAAmC;;QAR5B,4CAAoB;QAEpB,6CAAqC;QAE9C,4CAA+C;QAM7C,uBAAA,IAAI,6BAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,8BAAY,OAAO,MAAA,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,OAAO,GAAG,MAAM,uBAAA,IAAI,uEAAgB,MAApB,IAAI,CAAkB,CAAC;QAC7C,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC;QACnC,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,8DAAO,MAAX,IAAI,CAAS,CAAC;QAC1C,OAAO,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,OAAO,GAAG,MAAM,uBAAA,IAAI,uEAAgB,MAApB,IAAI,CAAkB,CAAC;QAC7C,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC,OAAO,CAAC;QACzB,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,8DAAO,MAAX,IAAI,CAAS,CAAC;QAC1C,OAAO,aAAa,CAAC,OAAO,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,uBAAA,IAAI,qEAAc,MAAlB,IAAI,EAAe,uBAAA,IAAI,iCAAQ,CAAC,CAAC;QACjC,OAAO,uBAAA,IAAI,iCAAQ,CAAC,OAAO,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAChD,OAAO,MAAM,IAAA,gCAAqB,EAAC,uBAAA,IAAI,iCAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe;QAC/B,uBAAA,IAAI,qEAAc,MAAlB,IAAI,EAAe,uBAAA,IAAI,iCAAQ,CAAC,CAAC;QACjC,OAAO,MAAM,uBAAA,IAAI,iCAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,MAAiC;QACvC,uBAAA,IAAI,6BAAW,MAAM,MAAA,CAAC;IACxB,CAAC;CA2EF;AA/HD,8CA+HC;;AAzEC,0EAA0E;AAC1E,KAAK;IACH,MAAM,IAAI,GAAG,MAAM,uBAAA,IAAI,kCAAS,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAC5D,IAAI,CAAC,IAAA,+CAAqB,EAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;IACvD,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,GAAG,GAAG,CAAC;IAE3D,IAAI,UAAU,GAAG,gBAAgB,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,6BAED,KAAK;IACH,uBAAA,IAAI,qEAAc,MAAlB,IAAI,EAAe,uBAAA,IAAI,iCAAQ,CAAC,CAAC;IAEjC,QAAQ;IACR,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,EAAE,uBAAA,IAAI,iCAAQ,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,uBAAA,IAAI,kFAA2B,MAA/B,IAAI,EAA4B,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAErD,eAAe;IACf,MAAM,YAAY,GAAG,MAAM,IAAA,uBAAY,EACrC,UAAU,EACV,SAAS,EACT,uBAAA,IAAI,iCAAQ,CAAC,IAAI,EACjB,uBAAA,IAAI,iCAAQ,CAAC,GAAG,CACjB,CAAC;IAEF,YAAY;IACZ,MAAM,aAAa,GAAG,MAAM,IAAA,wBAAa,EACvC,YAAY,CAAC,KAAK,EAClB,uBAAA,IAAI,iCAAQ,CAAC,GAAG,EAChB,uBAAA,IAAI,iCAAQ,CAAC,QAAQ,CACtB,CAAC;IAEF,OAAO;IACP,MAAM,MAAM,GAAkB;QAC5B,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,KAAK,EAAE,aAAa;KACrB,CAAC;IAEF,MAAM,uBAAA,IAAI,kCAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAErD,OAAO,MAAM,CAAC;AAChB,CAAC,uGAE0B,KAAa;IACtC,uBAAA,IAAI,qEAAc,MAAlB,IAAI,EAAe,uBAAA,IAAI,iCAAQ,CAAC,CAAC;IAEjC,OAAO,IAAI,kBAAW,CAAC;QACrB,MAAM,EAAE,uBAAA,IAAI,iCAAQ,EAAE,MAAM;QAC5B,OAAO,EAAE,uBAAA,IAAI,iCAAQ,EAAE,OAAO;QAC9B,GAAG,EAAE,IAAA,yBAAc,EAAC,uBAAA,IAAI,iCAAQ,CAAC,GAAG,CAAC;QACrC,OAAO,EAAE,GAAG;QACZ,OAAO,EAAE,uBAAA,IAAI,iCAAQ,EAAE,OAAO;QAC9B,KAAK;QACL,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACnC,CAAC,CAAC,cAAc,EAAE,CAAC;AACtB,CAAC,6EAGC,MAAkC;IAElC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,wBAAe,CAAC,6CAA6C,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC","sourcesContent":["import { SiweMessage } from 'siwe';\n\nimport { ValidationError } from '../errors';\nimport { validateLoginResponse } from '../utils/validate-login-response';\nimport {\n SIWE_LOGIN_URL,\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\n\ntype JwtBearerAuth_SIWE_Options = {\n storage: AuthStorageOptions;\n};\n\ntype JwtBearerAuth_SIWE_Signer = {\n address: string;\n chainId: number;\n signMessage: (message: string) => Promise<string>;\n domain: string;\n};\n\nexport class SIWEJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: JwtBearerAuth_SIWE_Options;\n\n #signer: JwtBearerAuth_SIWE_Signer | undefined;\n\n constructor(\n config: AuthConfig & { type: AuthType.SiWE },\n options: JwtBearerAuth_SIWE_Options,\n ) {\n this.#config = config;\n this.#options = options;\n }\n\n async getAccessToken(): Promise<string> {\n const session = await this.#getAuthSession();\n if (session) {\n return session.token.accessToken;\n }\n\n const loginResponse = await this.#login();\n return loginResponse.token.accessToken;\n }\n\n async getUserProfile(): Promise<UserProfile> {\n const session = await this.#getAuthSession();\n if (session) {\n return session.profile;\n }\n\n const loginResponse = await this.#login();\n return loginResponse.profile;\n }\n\n async getIdentifier(): Promise<string> {\n this.#assertSigner(this.#signer);\n return this.#signer.address;\n }\n\n async getUserProfileLineage(): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken();\n return await getUserProfileLineage(this.#config.env, accessToken);\n }\n\n async signMessage(message: string): Promise<string> {\n this.#assertSigner(this.#signer);\n return await this.#signer.signMessage(message);\n }\n\n prepare(signer: JwtBearerAuth_SIWE_Signer) {\n this.#signer = signer;\n }\n\n // convert expiresIn from seconds to milliseconds and use 90% of expiresIn\n async #getAuthSession(): Promise<LoginResponse | null> {\n const auth = await this.#options.storage.getLoginResponse();\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(): Promise<LoginResponse> {\n this.#assertSigner(this.#signer);\n\n // Nonce\n const address = await this.getIdentifier();\n const nonceRes = await getNonce(address, this.#config.env);\n const rawMessage = this.#createSiWELoginRawMessage(nonceRes.nonce);\n const signature = await this.signMessage(rawMessage);\n\n // Authenticate\n const authResponse = await authenticate(\n rawMessage,\n signature,\n this.#config.type,\n this.#config.env,\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);\n\n return result;\n }\n\n #createSiWELoginRawMessage(nonce: string): string {\n this.#assertSigner(this.#signer);\n\n return new SiweMessage({\n domain: this.#signer?.domain,\n address: this.#signer?.address,\n uri: SIWE_LOGIN_URL(this.#config.env),\n version: '1',\n chainId: this.#signer?.chainId,\n nonce,\n issuedAt: new Date().toISOString(),\n }).prepareMessage();\n }\n\n #assertSigner(\n signer?: JwtBearerAuth_SIWE_Signer,\n ): asserts signer is JwtBearerAuth_SIWE_Signer {\n if (!signer) {\n throw new ValidationError(`you must call 'prepare()' before logging in`);\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-siwe.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"flow-siwe.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AAEjB,KAAK,0BAA0B,GAAG;IAChC,OAAO,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qBAAa,iBAAkB,YAAW,SAAS;;gBAQ/C,MAAM,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAA;KAAE,EAC5C,OAAO,EAAE,0BAA0B;IAM/B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAUjC,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAUtC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAKhC,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKpD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKnD,OAAO,CAAC,MAAM,EAAE,yBAAyB;CA6E1C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-siwe.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"flow-siwe.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AAEjB,KAAK,0BAA0B,GAAG;IAChC,OAAO,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qBAAa,iBAAkB,YAAW,SAAS;;gBAQ/C,MAAM,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAA;KAAE,EAC5C,OAAO,EAAE,0BAA0B;IAM/B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAUjC,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAUtC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAKhC,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKpD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKnD,OAAO,CAAC,MAAM,EAAE,yBAAyB;CA6E1C"}
|
|
@@ -11,9 +11,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
11
11
|
};
|
|
12
12
|
var _SIWEJwtBearerAuth_instances, _SIWEJwtBearerAuth_config, _SIWEJwtBearerAuth_options, _SIWEJwtBearerAuth_signer, _SIWEJwtBearerAuth_getAuthSession, _SIWEJwtBearerAuth_login, _SIWEJwtBearerAuth_createSiWELoginRawMessage, _SIWEJwtBearerAuth_assertSigner;
|
|
13
13
|
import { SiweMessage } from "siwe";
|
|
14
|
-
import { SIWE_LOGIN_URL, authenticate, authorizeOIDC, getNonce, getUserProfileLineage } from "./services.mjs";
|
|
15
14
|
import { ValidationError } from "../errors.mjs";
|
|
16
15
|
import { validateLoginResponse } from "../utils/validate-login-response.mjs";
|
|
16
|
+
import { SIWE_LOGIN_URL, authenticate, authorizeOIDC, getNonce, getUserProfileLineage } from "./services.mjs";
|
|
17
17
|
export class SIWEJwtBearerAuth {
|
|
18
18
|
constructor(config, options) {
|
|
19
19
|
_SIWEJwtBearerAuth_instances.add(this);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-siwe.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,aAAa;AAEnC,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,qBAAqB,EACtB,uBAAmB;
|
|
1
|
+
{"version":3,"file":"flow-siwe.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-siwe.ts"],"names":[],"mappings":"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","sourcesContent":["import { SiweMessage } from 'siwe';\n\nimport { ValidationError } from '../errors';\nimport { validateLoginResponse } from '../utils/validate-login-response';\nimport {\n SIWE_LOGIN_URL,\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\n\ntype JwtBearerAuth_SIWE_Options = {\n storage: AuthStorageOptions;\n};\n\ntype JwtBearerAuth_SIWE_Signer = {\n address: string;\n chainId: number;\n signMessage: (message: string) => Promise<string>;\n domain: string;\n};\n\nexport class SIWEJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: JwtBearerAuth_SIWE_Options;\n\n #signer: JwtBearerAuth_SIWE_Signer | undefined;\n\n constructor(\n config: AuthConfig & { type: AuthType.SiWE },\n options: JwtBearerAuth_SIWE_Options,\n ) {\n this.#config = config;\n this.#options = options;\n }\n\n async getAccessToken(): Promise<string> {\n const session = await this.#getAuthSession();\n if (session) {\n return session.token.accessToken;\n }\n\n const loginResponse = await this.#login();\n return loginResponse.token.accessToken;\n }\n\n async getUserProfile(): Promise<UserProfile> {\n const session = await this.#getAuthSession();\n if (session) {\n return session.profile;\n }\n\n const loginResponse = await this.#login();\n return loginResponse.profile;\n }\n\n async getIdentifier(): Promise<string> {\n this.#assertSigner(this.#signer);\n return this.#signer.address;\n }\n\n async getUserProfileLineage(): Promise<UserProfileLineage> {\n const accessToken = await this.getAccessToken();\n return await getUserProfileLineage(this.#config.env, accessToken);\n }\n\n async signMessage(message: string): Promise<string> {\n this.#assertSigner(this.#signer);\n return await this.#signer.signMessage(message);\n }\n\n prepare(signer: JwtBearerAuth_SIWE_Signer) {\n this.#signer = signer;\n }\n\n // convert expiresIn from seconds to milliseconds and use 90% of expiresIn\n async #getAuthSession(): Promise<LoginResponse | null> {\n const auth = await this.#options.storage.getLoginResponse();\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(): Promise<LoginResponse> {\n this.#assertSigner(this.#signer);\n\n // Nonce\n const address = await this.getIdentifier();\n const nonceRes = await getNonce(address, this.#config.env);\n const rawMessage = this.#createSiWELoginRawMessage(nonceRes.nonce);\n const signature = await this.signMessage(rawMessage);\n\n // Authenticate\n const authResponse = await authenticate(\n rawMessage,\n signature,\n this.#config.type,\n this.#config.env,\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);\n\n return result;\n }\n\n #createSiWELoginRawMessage(nonce: string): string {\n this.#assertSigner(this.#signer);\n\n return new SiweMessage({\n domain: this.#signer?.domain,\n address: this.#signer?.address,\n uri: SIWE_LOGIN_URL(this.#config.env),\n version: '1',\n chainId: this.#signer?.chainId,\n nonce,\n issuedAt: new Date().toISOString(),\n }).prepareMessage();\n }\n\n #assertSigner(\n signer?: JwtBearerAuth_SIWE_Signer,\n ): asserts signer is JwtBearerAuth_SIWE_Signer {\n if (!signer) {\n throw new ValidationError(`you must call 'prepare()' before logging in`);\n }\n }\n}\n"]}
|
|
@@ -36,12 +36,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
36
36
|
var _SRPJwtBearerAuth_instances, _SRPJwtBearerAuth_config, _SRPJwtBearerAuth_options, _SRPJwtBearerAuth_metametrics, _SRPJwtBearerAuth_ongoingLogins, _SRPJwtBearerAuth_cooldownDefaultMs, _SRPJwtBearerAuth_maxLoginRetries, _SRPJwtBearerAuth_customProvider, _SRPJwtBearerAuth_getAuthSession, _SRPJwtBearerAuth_login, _SRPJwtBearerAuth_performLogin, _SRPJwtBearerAuth_deferredLogin, _SRPJwtBearerAuth_loginWithRetry, _SRPJwtBearerAuth_createSrpLoginRawMessage;
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.SRPJwtBearerAuth = void 0;
|
|
39
|
-
const services_1 = require("./services.cjs");
|
|
40
|
-
const timeUtils = __importStar(require("./utils/time.cjs"));
|
|
41
39
|
const errors_1 = require("../errors.cjs");
|
|
42
40
|
const eip_6963_metamask_provider_1 = require("../utils/eip-6963-metamask-provider.cjs");
|
|
43
41
|
const messaging_signing_snap_requests_1 = require("../utils/messaging-signing-snap-requests.cjs");
|
|
44
42
|
const validate_login_response_1 = require("../utils/validate-login-response.cjs");
|
|
43
|
+
const services_1 = require("./services.cjs");
|
|
44
|
+
const identifier_1 = require("./utils/identifier.cjs");
|
|
45
|
+
const timeUtils = __importStar(require("./utils/time.cjs"));
|
|
45
46
|
const getDefaultEIP6963Provider = async () => {
|
|
46
47
|
const provider = await (0, eip_6963_metamask_provider_1.getMetaMaskProviderEIP6963)();
|
|
47
48
|
if (!provider) {
|
|
@@ -113,6 +114,9 @@ class SRPJwtBearerAuth {
|
|
|
113
114
|
const accessToken = await this.getAccessToken(entropySourceId);
|
|
114
115
|
return await (0, services_1.getUserProfileLineage)(__classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env, accessToken);
|
|
115
116
|
}
|
|
117
|
+
async pairSrpProfiles(accessTokens, authAccessToken) {
|
|
118
|
+
return await (0, services_1.pairProfiles)(accessTokens, authAccessToken, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env);
|
|
119
|
+
}
|
|
116
120
|
async signMessage(message, entropySourceId) {
|
|
117
121
|
return await __classPrivateFieldGet(this, _SRPJwtBearerAuth_options, "f").signing.signMessage(message, entropySourceId);
|
|
118
122
|
}
|
|
@@ -138,6 +142,10 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
138
142
|
if (!(0, validate_login_response_1.validateLoginResponse)(auth)) {
|
|
139
143
|
return null;
|
|
140
144
|
}
|
|
145
|
+
// get canonical profile id from server if not present in the cached session
|
|
146
|
+
if (!auth.profile.canonicalProfileId) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
141
149
|
const currentTime = Date.now();
|
|
142
150
|
const sessionAge = currentTime - auth.token.obtainedAt;
|
|
143
151
|
const refreshThreshold = auth.token.expiresIn * 1000 * 0.9;
|
|
@@ -156,11 +164,30 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
156
164
|
const signature = await this.signMessage(rawMessage, entropySourceId);
|
|
157
165
|
// Authenticate
|
|
158
166
|
const authResponse = await (0, services_1.authenticate)(rawMessage, signature, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").type, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env, __classPrivateFieldGet(this, _SRPJwtBearerAuth_metametrics, "f"));
|
|
167
|
+
// Resolve original profileId from aliases.
|
|
168
|
+
// This is done mainly to preserve the original profileId for storage key derivation
|
|
169
|
+
// until we migrate to the canonical profileId storage system.
|
|
170
|
+
const canonicalProfileId = authResponse.profile.profileId;
|
|
171
|
+
const profile = { ...authResponse.profile };
|
|
172
|
+
if (authResponse.profileAliases?.length > 0) {
|
|
173
|
+
const targetIdentifierId = (0, identifier_1.computeIdentifierId)(publicKey, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env);
|
|
174
|
+
const matchingAliases = authResponse.profileAliases.filter((alias) => alias.identifierIds.some((id) => id.id === targetIdentifierId));
|
|
175
|
+
// Prefer the leaf alias (single identifier) — it's the original profile
|
|
176
|
+
// created for this SRP. Multi-identifier aliases are former canonicals
|
|
177
|
+
// that absorbed other profiles; they are correct only when this SRP's
|
|
178
|
+
// original profile was itself a canonical before being absorbed.
|
|
179
|
+
const targetAlias = matchingAliases.find((alias) => alias.identifierIds.length === 1) ??
|
|
180
|
+
matchingAliases[0];
|
|
181
|
+
if (targetAlias) {
|
|
182
|
+
profile.profileId = targetAlias.aliasProfileId;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
profile.canonicalProfileId = canonicalProfileId;
|
|
159
186
|
// Authorize
|
|
160
187
|
const tokenResponse = await (0, services_1.authorizeOIDC)(authResponse.token, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").platform);
|
|
161
188
|
// Save
|
|
162
189
|
const result = {
|
|
163
|
-
profile
|
|
190
|
+
profile,
|
|
164
191
|
token: tokenResponse,
|
|
165
192
|
};
|
|
166
193
|
await __classPrivateFieldGet(this, _SRPJwtBearerAuth_options, "f").storage.setLoginResponse(result, entropySourceId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Eip1193Provider } from 'ethers';\n\nimport {\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthSigningOptions,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport * as timeUtils from './utils/time';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { ValidationError, RateLimitedError } from '../errors';\nimport { getMetaMaskProviderEIP6963 } from '../utils/eip-6963-metamask-provider';\nimport {\n MESSAGE_SIGNING_SNAP,\n assertMessageStartsWithMetamask,\n connectSnap,\n isSnapConnected,\n} from '../utils/messaging-signing-snap-requests';\nimport { validateLoginResponse } from '../utils/validate-login-response';\n\ntype JwtBearerAuth_SRP_Options = {\n storage: AuthStorageOptions;\n signing?: AuthSigningOptions;\n rateLimitRetry?: {\n cooldownDefaultMs?: number; // default cooldown when 429 has no Retry-After\n maxLoginRetries?: number; // maximum number of login retries on rate limit\n };\n};\n\nconst getDefaultEIP6963Provider = async () => {\n const provider = await getMetaMaskProviderEIP6963();\n if (!provider) {\n throw new ValidationError('No MetaMask wallet connected');\n }\n return provider;\n};\n\nconst getDefaultEIP6963SigningOptions = (\n customProvider?: Eip1193Provider,\n): AuthSigningOptions => ({\n getIdentifier: async (entropySourceId?: string): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n return await MESSAGE_SIGNING_SNAP.getPublicKey(provider, entropySourceId);\n },\n signMessage: async (\n message: string,\n entropySourceId?: string,\n ): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n assertMessageStartsWithMetamask(message);\n return await MESSAGE_SIGNING_SNAP.signMessage(\n provider,\n message,\n entropySourceId,\n );\n },\n});\n\nexport class SRPJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: {\n storage: AuthStorageOptions;\n signing: AuthSigningOptions;\n };\n\n readonly #metametrics?: MetaMetricsAuth;\n\n // Map to store ongoing login promises by entropySourceId\n readonly #ongoingLogins = new Map<\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.cjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Eip1193Provider } from 'ethers';\n\nimport 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,6 +1,7 @@
|
|
|
1
1
|
import type { Eip1193Provider } from "ethers";
|
|
2
|
-
import type { AuthConfig, AuthSigningOptions, AuthStorageOptions, AuthType, IBaseAuth, UserProfile, UserProfileLineage } from "./types.cjs";
|
|
3
2
|
import type { MetaMetricsAuth } from "../../shared/types/services.cjs";
|
|
3
|
+
import type { PairProfilesResponse } from "./services.cjs";
|
|
4
|
+
import type { AuthConfig, AuthSigningOptions, AuthStorageOptions, AuthType, IBaseAuth, UserProfile, UserProfileLineage } from "./types.cjs";
|
|
4
5
|
type JwtBearerAuth_SRP_Options = {
|
|
5
6
|
storage: AuthStorageOptions;
|
|
6
7
|
signing?: AuthSigningOptions;
|
|
@@ -22,6 +23,7 @@ export declare class SRPJwtBearerAuth implements IBaseAuth {
|
|
|
22
23
|
getUserProfile(entropySourceId?: string): Promise<UserProfile>;
|
|
23
24
|
getIdentifier(entropySourceId?: string): Promise<string>;
|
|
24
25
|
getUserProfileLineage(entropySourceId?: string): Promise<UserProfileLineage>;
|
|
26
|
+
pairSrpProfiles(accessTokens: string[], authAccessToken: string): Promise<PairProfilesResponse>;
|
|
25
27
|
signMessage(message: string, entropySourceId?: string): Promise<string>;
|
|
26
28
|
isSnapConnected(): Promise<boolean>;
|
|
27
29
|
connectSnap(): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;
|
|
1
|
+
{"version":3,"file":"flow-srp.d.cts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAiBnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAmB;AACvD,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AAIjB,KAAK,yBAAyB,GAAG;IAC/B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,cAAc,CAAC,EAAE;QACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH,CAAC;AA+BF,qBAAa,gBAAiB,YAAW,SAAS;;gBAyB9C,MAAM,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAA;KAAE,EAC3C,OAAO,EAAE,yBAAyB,GAAG;QACnC,cAAc,CAAC,EAAE,eAAe,CAAC;QACjC,WAAW,CAAC,EAAE,eAAe,CAAC;KAC/B;IAkBH,iBAAiB,CAAC,QAAQ,EAAE,eAAe;IAMrC,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUzD,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAU9D,aAAa,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxD,qBAAqB,CACzB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,kBAAkB,CAAC;IAKxB,eAAe,CACnB,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,oBAAoB,CAAC;IAI1B,WAAW,CACf,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC;IAIZ,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAWnC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;CAkKrC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Eip1193Provider } from "ethers";
|
|
2
|
-
import type { AuthConfig, AuthSigningOptions, AuthStorageOptions, AuthType, IBaseAuth, UserProfile, UserProfileLineage } from "./types.mjs";
|
|
3
2
|
import type { MetaMetricsAuth } from "../../shared/types/services.mjs";
|
|
3
|
+
import type { PairProfilesResponse } from "./services.mjs";
|
|
4
|
+
import type { AuthConfig, AuthSigningOptions, AuthStorageOptions, AuthType, IBaseAuth, UserProfile, UserProfileLineage } from "./types.mjs";
|
|
4
5
|
type JwtBearerAuth_SRP_Options = {
|
|
5
6
|
storage: AuthStorageOptions;
|
|
6
7
|
signing?: AuthSigningOptions;
|
|
@@ -22,6 +23,7 @@ export declare class SRPJwtBearerAuth implements IBaseAuth {
|
|
|
22
23
|
getUserProfile(entropySourceId?: string): Promise<UserProfile>;
|
|
23
24
|
getIdentifier(entropySourceId?: string): Promise<string>;
|
|
24
25
|
getUserProfileLineage(entropySourceId?: string): Promise<UserProfileLineage>;
|
|
26
|
+
pairSrpProfiles(accessTokens: string[], authAccessToken: string): Promise<PairProfilesResponse>;
|
|
25
27
|
signMessage(message: string, entropySourceId?: string): Promise<string>;
|
|
26
28
|
isSnapConnected(): Promise<boolean>;
|
|
27
29
|
connectSnap(): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;
|
|
1
|
+
{"version":3,"file":"flow-srp.d.mts","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,wCAAoC;AAiBnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAmB;AACvD,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAET,WAAW,EACX,kBAAkB,EACnB,oBAAgB;AAIjB,KAAK,yBAAyB,GAAG;IAC/B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,cAAc,CAAC,EAAE;QACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH,CAAC;AA+BF,qBAAa,gBAAiB,YAAW,SAAS;;gBAyB9C,MAAM,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAA;KAAE,EAC3C,OAAO,EAAE,yBAAyB,GAAG;QACnC,cAAc,CAAC,EAAE,eAAe,CAAC;QACjC,WAAW,CAAC,EAAE,eAAe,CAAC;KAC/B;IAkBH,iBAAiB,CAAC,QAAQ,EAAE,eAAe;IAMrC,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUzD,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAU9D,aAAa,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxD,qBAAqB,CACzB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,kBAAkB,CAAC;IAKxB,eAAe,CACnB,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,oBAAoB,CAAC;IAI1B,WAAW,CACf,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC;IAIZ,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAWnC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;CAkKrC"}
|
|
@@ -10,12 +10,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
12
|
var _SRPJwtBearerAuth_instances, _SRPJwtBearerAuth_config, _SRPJwtBearerAuth_options, _SRPJwtBearerAuth_metametrics, _SRPJwtBearerAuth_ongoingLogins, _SRPJwtBearerAuth_cooldownDefaultMs, _SRPJwtBearerAuth_maxLoginRetries, _SRPJwtBearerAuth_customProvider, _SRPJwtBearerAuth_getAuthSession, _SRPJwtBearerAuth_login, _SRPJwtBearerAuth_performLogin, _SRPJwtBearerAuth_deferredLogin, _SRPJwtBearerAuth_loginWithRetry, _SRPJwtBearerAuth_createSrpLoginRawMessage;
|
|
13
|
-
import { authenticate, authorizeOIDC, getNonce, getUserProfileLineage } from "./services.mjs";
|
|
14
|
-
import * as timeUtils from "./utils/time.mjs";
|
|
15
13
|
import { ValidationError, RateLimitedError } from "../errors.mjs";
|
|
16
14
|
import { getMetaMaskProviderEIP6963 } from "../utils/eip-6963-metamask-provider.mjs";
|
|
17
15
|
import { MESSAGE_SIGNING_SNAP, assertMessageStartsWithMetamask, connectSnap, isSnapConnected } from "../utils/messaging-signing-snap-requests.mjs";
|
|
18
16
|
import { validateLoginResponse } from "../utils/validate-login-response.mjs";
|
|
17
|
+
import { authenticate, authorizeOIDC, getNonce, getUserProfileLineage, pairProfiles } from "./services.mjs";
|
|
18
|
+
import { computeIdentifierId } from "./utils/identifier.mjs";
|
|
19
|
+
import * as timeUtils from "./utils/time.mjs";
|
|
19
20
|
const getDefaultEIP6963Provider = async () => {
|
|
20
21
|
const provider = await getMetaMaskProviderEIP6963();
|
|
21
22
|
if (!provider) {
|
|
@@ -87,6 +88,9 @@ export class SRPJwtBearerAuth {
|
|
|
87
88
|
const accessToken = await this.getAccessToken(entropySourceId);
|
|
88
89
|
return await getUserProfileLineage(__classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env, accessToken);
|
|
89
90
|
}
|
|
91
|
+
async pairSrpProfiles(accessTokens, authAccessToken) {
|
|
92
|
+
return await pairProfiles(accessTokens, authAccessToken, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env);
|
|
93
|
+
}
|
|
90
94
|
async signMessage(message, entropySourceId) {
|
|
91
95
|
return await __classPrivateFieldGet(this, _SRPJwtBearerAuth_options, "f").signing.signMessage(message, entropySourceId);
|
|
92
96
|
}
|
|
@@ -111,6 +115,10 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
111
115
|
if (!validateLoginResponse(auth)) {
|
|
112
116
|
return null;
|
|
113
117
|
}
|
|
118
|
+
// get canonical profile id from server if not present in the cached session
|
|
119
|
+
if (!auth.profile.canonicalProfileId) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
114
122
|
const currentTime = Date.now();
|
|
115
123
|
const sessionAge = currentTime - auth.token.obtainedAt;
|
|
116
124
|
const refreshThreshold = auth.token.expiresIn * 1000 * 0.9;
|
|
@@ -129,11 +137,30 @@ async function _SRPJwtBearerAuth_getAuthSession(entropySourceId) {
|
|
|
129
137
|
const signature = await this.signMessage(rawMessage, entropySourceId);
|
|
130
138
|
// Authenticate
|
|
131
139
|
const authResponse = await authenticate(rawMessage, signature, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").type, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env, __classPrivateFieldGet(this, _SRPJwtBearerAuth_metametrics, "f"));
|
|
140
|
+
// Resolve original profileId from aliases.
|
|
141
|
+
// This is done mainly to preserve the original profileId for storage key derivation
|
|
142
|
+
// until we migrate to the canonical profileId storage system.
|
|
143
|
+
const canonicalProfileId = authResponse.profile.profileId;
|
|
144
|
+
const profile = { ...authResponse.profile };
|
|
145
|
+
if (authResponse.profileAliases?.length > 0) {
|
|
146
|
+
const targetIdentifierId = computeIdentifierId(publicKey, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env);
|
|
147
|
+
const matchingAliases = authResponse.profileAliases.filter((alias) => alias.identifierIds.some((id) => id.id === targetIdentifierId));
|
|
148
|
+
// Prefer the leaf alias (single identifier) — it's the original profile
|
|
149
|
+
// created for this SRP. Multi-identifier aliases are former canonicals
|
|
150
|
+
// that absorbed other profiles; they are correct only when this SRP's
|
|
151
|
+
// original profile was itself a canonical before being absorbed.
|
|
152
|
+
const targetAlias = matchingAliases.find((alias) => alias.identifierIds.length === 1) ??
|
|
153
|
+
matchingAliases[0];
|
|
154
|
+
if (targetAlias) {
|
|
155
|
+
profile.profileId = targetAlias.aliasProfileId;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
profile.canonicalProfileId = canonicalProfileId;
|
|
132
159
|
// Authorize
|
|
133
160
|
const tokenResponse = await authorizeOIDC(authResponse.token, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").env, __classPrivateFieldGet(this, _SRPJwtBearerAuth_config, "f").platform);
|
|
134
161
|
// Save
|
|
135
162
|
const result = {
|
|
136
|
-
profile
|
|
163
|
+
profile,
|
|
137
164
|
token: tokenResponse,
|
|
138
165
|
};
|
|
139
166
|
await __classPrivateFieldGet(this, _SRPJwtBearerAuth_options, "f").storage.setLoginResponse(result, entropySourceId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-srp.mjs","sourceRoot":"","sources":["../../../src/sdk/authentication-jwt-bearer/flow-srp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Eip1193Provider } from 'ethers';\n\nimport {\n authenticate,\n authorizeOIDC,\n getNonce,\n getUserProfileLineage,\n} from './services';\nimport type {\n AuthConfig,\n AuthSigningOptions,\n AuthStorageOptions,\n AuthType,\n IBaseAuth,\n LoginResponse,\n UserProfile,\n UserProfileLineage,\n} from './types';\nimport * as timeUtils from './utils/time';\nimport type { MetaMetricsAuth } from '../../shared/types/services';\nimport { ValidationError, RateLimitedError } from '../errors';\nimport { getMetaMaskProviderEIP6963 } from '../utils/eip-6963-metamask-provider';\nimport {\n MESSAGE_SIGNING_SNAP,\n assertMessageStartsWithMetamask,\n connectSnap,\n isSnapConnected,\n} from '../utils/messaging-signing-snap-requests';\nimport { validateLoginResponse } from '../utils/validate-login-response';\n\ntype JwtBearerAuth_SRP_Options = {\n storage: AuthStorageOptions;\n signing?: AuthSigningOptions;\n rateLimitRetry?: {\n cooldownDefaultMs?: number; // default cooldown when 429 has no Retry-After\n maxLoginRetries?: number; // maximum number of login retries on rate limit\n };\n};\n\nconst getDefaultEIP6963Provider = async () => {\n const provider = await getMetaMaskProviderEIP6963();\n if (!provider) {\n throw new ValidationError('No MetaMask wallet connected');\n }\n return provider;\n};\n\nconst getDefaultEIP6963SigningOptions = (\n customProvider?: Eip1193Provider,\n): AuthSigningOptions => ({\n getIdentifier: async (entropySourceId?: string): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n return await MESSAGE_SIGNING_SNAP.getPublicKey(provider, entropySourceId);\n },\n signMessage: async (\n message: string,\n entropySourceId?: string,\n ): Promise<string> => {\n const provider = customProvider ?? (await getDefaultEIP6963Provider());\n assertMessageStartsWithMetamask(message);\n return await MESSAGE_SIGNING_SNAP.signMessage(\n provider,\n message,\n entropySourceId,\n );\n },\n});\n\nexport class SRPJwtBearerAuth implements IBaseAuth {\n readonly #config: AuthConfig;\n\n readonly #options: {\n storage: AuthStorageOptions;\n signing: AuthSigningOptions;\n };\n\n readonly #metametrics?: MetaMetricsAuth;\n\n // Map to store ongoing login promises by entropySourceId\n readonly #ongoingLogins = new Map<\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":"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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 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"]}
|