@metamask-previews/profile-sync-controller 33.0.0-preview-0f8c056e2 → 34.0.0-preview-0305ce0
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 -1
- package/README.md +11 -4
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.ts +11 -0
- package/dist/controllers/authentication/AuthenticationController-method-action-types.d.ts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController-method-action-types.js.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.d.ts +11 -8
- package/dist/controllers/authentication/AuthenticationController.d.ts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.js +69 -18
- package/dist/controllers/authentication/AuthenticationController.js.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.ts +2 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.d.ts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.js +2 -1
- package/dist/sdk/authentication-jwt-bearer/flow-srp.js.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/mfa/schemas.d.ts +8 -2
- package/dist/sdk/authentication-jwt-bearer/mfa/schemas.d.ts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/mfa/schemas.js +5 -3
- package/dist/sdk/authentication-jwt-bearer/mfa/schemas.js.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/mfa/services.d.ts +3 -1
- package/dist/sdk/authentication-jwt-bearer/mfa/services.d.ts.map +1 -1
- package/dist/sdk/authentication-jwt-bearer/mfa/services.js +3 -0
- package/dist/sdk/authentication-jwt-bearer/mfa/services.js.map +1 -1
- package/dist/sdk/authentication.d.ts +1 -1
- package/dist/sdk/authentication.d.ts.map +1 -1
- package/dist/sdk/authentication.js +1 -1
- package/dist/sdk/authentication.js.map +1 -1
- package/dist/sdk/mocks/auth.d.ts +10 -3
- package/dist/sdk/mocks/auth.d.ts.map +1 -1
- package/dist/sdk/mocks/auth.js +1 -3
- package/dist/sdk/mocks/auth.js.map +1 -1
- package/dist/shared/encryption/cache.d.ts +4 -4
- package/dist/shared/encryption/cache.d.ts.map +1 -1
- package/dist/shared/encryption/cache.js.map +1 -1
- package/dist/shared/encryption/constants.d.ts +0 -1
- package/dist/shared/encryption/constants.d.ts.map +1 -1
- package/dist/shared/encryption/constants.js +0 -2
- package/dist/shared/encryption/constants.js.map +1 -1
- package/dist/shared/encryption/encryption.d.ts.map +1 -1
- package/dist/shared/encryption/encryption.js +22 -24
- package/dist/shared/encryption/encryption.js.map +1 -1
- package/dist/shared/types/encryption.d.ts +1 -1
- package/dist/shared/types/encryption.d.ts.map +1 -1
- package/dist/shared/types/encryption.js.map +1 -1
- package/package.json +6 -7
package/CHANGELOG.md
CHANGED
|
@@ -7,12 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [34.0.0]
|
|
11
|
+
|
|
10
12
|
### Changed
|
|
11
13
|
|
|
14
|
+
- Open the verification session on enrollment and let the server set its lifetime ([#10653](https://github.com/MetaMask/core/pull/10653))
|
|
15
|
+
- `completeCredentialEnrollment` opens a verification session with the assertion `POST /api/v2/mfa/enroll/complete` returns for the new credential, replacing any earlier one, so no separate verification is needed right after enrolling. If the token exchange fails, the enrollment still succeeds and the earlier session is kept
|
|
16
|
+
- `SRPJwtBearerAuth.completeMfaEnrollment` and `JwtBearerAuth.completeMfaEnrollment` return that assertion
|
|
17
|
+
- The session lasts for the token's `expires_in`, measured on the device clock, instead of at most 15 minutes
|
|
18
|
+
- Replace JS AES implementation with `@metamask/cryptography` ([#10621](https://github.com/MetaMask/core/pull/10621))
|
|
12
19
|
- Bump `immer` from `^9.0.21` to `^11.1.18` ([#10382](https://github.com/MetaMask/core/pull/10382))
|
|
13
20
|
|
|
21
|
+
### Removed
|
|
22
|
+
|
|
23
|
+
- **BREAKING:** Remove `VERIFICATION_SESSION_TTL_MS`, as the server now sets the verification session lifetime ([#10653](https://github.com/MetaMask/core/pull/10653))
|
|
24
|
+
|
|
14
25
|
### Fixed
|
|
15
26
|
|
|
27
|
+
- Coalesce overlapping `performSignIn` calls so only one sign-in runs at a time ([#10646](https://github.com/MetaMask/core/pull/10646))
|
|
16
28
|
- Rely on `@metamask/key-tree` crypto implementation for HMAC-SHA-512 instead of hardcoded `noble` implementation ([#10424](https://github.com/MetaMask/core/pull/10424))
|
|
17
29
|
- `@metamask/key-tree` uses WebCrypto API if available and fallback to `noble` otherwise.
|
|
18
30
|
- One note, we expect the platform to provide a fully-compliant WebCrypto (`crypto.subtle`) implementation for this to work (`@metamask/key-tree` detection is global and not "per crypto functions").
|
|
@@ -1030,7 +1042,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1030
1042
|
|
|
1031
1043
|
- Initial release
|
|
1032
1044
|
|
|
1033
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/profile-sync-controller@
|
|
1045
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/profile-sync-controller@34.0.0...HEAD
|
|
1046
|
+
[34.0.0]: https://github.com/MetaMask/core/compare/@metamask/profile-sync-controller@33.0.0...@metamask/profile-sync-controller@34.0.0
|
|
1034
1047
|
[33.0.0]: https://github.com/MetaMask/core/compare/@metamask/profile-sync-controller@32.3.1...@metamask/profile-sync-controller@33.0.0
|
|
1035
1048
|
[32.3.1]: https://github.com/MetaMask/core/compare/@metamask/profile-sync-controller@32.3.0...@metamask/profile-sync-controller@32.3.1
|
|
1036
1049
|
[32.3.0]: https://github.com/MetaMask/core/compare/@metamask/profile-sync-controller@32.2.0...@metamask/profile-sync-controller@32.3.0
|
package/README.md
CHANGED
|
@@ -58,14 +58,21 @@ email OTP enrollment and verification:
|
|
|
58
58
|
The controller never inspects the token's assurance level; the server
|
|
59
59
|
decides. A setup flow that proved a factor itself can pass
|
|
60
60
|
`maxSessionAgeMs` (for example, the time since the flow started) so chained
|
|
61
|
-
enrollments reuse that proof.
|
|
61
|
+
enrollments reuse that proof. `completeCredentialEnrollment()` opens a
|
|
62
|
+
verification session with the assertion the server returns for the new
|
|
63
|
+
credential (replacing any earlier one), so no separate verification is
|
|
64
|
+
needed right after enrolling.
|
|
62
65
|
- `beginCredentialVerification()` and `completeCredentialVerification()`
|
|
63
66
|
verify an enrolled credential and return a verification token.
|
|
64
67
|
- `getVerificationToken()` reuses a live verification session when it satisfies
|
|
65
68
|
the caller's freshness requirement; `clearVerificationSession()` clears it. The
|
|
66
|
-
session lasts as long as the
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
session lasts as long as the server says the token does (`expires_in`,
|
|
70
|
+
measured from when it was obtained) and ends on lock, sign-out, reset, or a
|
|
71
|
+
rejected base session. It is
|
|
72
|
+
a low-level read: features should go through the client MFA kit
|
|
73
|
+
(`verifyOrEnroll`), which reuses a matching session without showing any
|
|
74
|
+
screen. Read it directly only from code that cannot show UI, and treat `null`
|
|
75
|
+
as "let the UI layer ask".
|
|
69
76
|
|
|
70
77
|
Clients must retain the challenge `flowId`, perform the platform ceremony, and
|
|
71
78
|
send the resulting proof to the matching completion method. OTP codes,
|
|
@@ -38,6 +38,11 @@ export type AuthenticationControllerBeginCredentialEnrollmentAction = {
|
|
|
38
38
|
/**
|
|
39
39
|
* Completes credential enrollment and refreshes the credential cache.
|
|
40
40
|
*
|
|
41
|
+
* The server returns an assertion for the new credential, which opens a
|
|
42
|
+
* verification session like `completeCredentialVerification`, replacing
|
|
43
|
+
* any earlier one. If that exchange fails, the earlier session is kept:
|
|
44
|
+
* the credential is enrolled either way.
|
|
45
|
+
*
|
|
41
46
|
* A cache-refresh failure does not undo successful enrollment. Email
|
|
42
47
|
* enrollment invalidates the primary SRP session *after* refresh so the
|
|
43
48
|
* credentials call can reuse the still-valid access token; the next token
|
|
@@ -82,6 +87,12 @@ export type AuthenticationControllerCompleteCredentialVerificationAction = {
|
|
|
82
87
|
* Returns the active verification token when it meets the requested
|
|
83
88
|
* freshness.
|
|
84
89
|
*
|
|
90
|
+
* Low-level: features should go through the client MFA kit
|
|
91
|
+
* (`verifyOrEnroll`), which reuses a matching session without showing any
|
|
92
|
+
* screen and checks which method proved it. Read the token directly only
|
|
93
|
+
* from code that cannot show UI, and treat `null` as "let the UI layer
|
|
94
|
+
* ask".
|
|
95
|
+
*
|
|
85
96
|
* @param request - Optional maximum session age in milliseconds, measured
|
|
86
97
|
* from when the token was obtained. Zero always requires a new ceremony.
|
|
87
98
|
* @returns A live verification token, or null when no reusable session
|
package/dist/controllers/authentication/AuthenticationController-method-action-types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationController-method-action-types.d.ts","sourceRoot":"","sources":["../../../src/controllers/authentication/AuthenticationController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAE9E,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,wCAAwC,CAAC;IAC/C,OAAO,EAAE,wBAAwB,CAAC,eAAe,CAAC,CAAC;CACpD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,mDAAmD,GAAG;IAChE,IAAI,EAAE,gDAAgD,CAAC;IACvD,OAAO,EAAE,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;CAC5D,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,wDAAwD,GAAG;IACrE,IAAI,EAAE,qDAAqD,CAAC;IAC5D,OAAO,EAAE,wBAAwB,CAAC,4BAA4B,CAAC,CAAC;CACjE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,uDAAuD,GAAG;IACpE,IAAI,EAAE,oDAAoD,CAAC;IAC3D,OAAO,EAAE,wBAAwB,CAAC,2BAA2B,CAAC,CAAC;CAChE,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"AuthenticationController-method-action-types.d.ts","sourceRoot":"","sources":["../../../src/controllers/authentication/AuthenticationController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAE9E,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,wCAAwC,CAAC;IAC/C,OAAO,EAAE,wBAAwB,CAAC,eAAe,CAAC,CAAC;CACpD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,mDAAmD,GAAG;IAChE,IAAI,EAAE,gDAAgD,CAAC;IACvD,OAAO,EAAE,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;CAC5D,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,wDAAwD,GAAG;IACrE,IAAI,EAAE,qDAAqD,CAAC;IAC5D,OAAO,EAAE,wBAAwB,CAAC,4BAA4B,CAAC,CAAC;CACjE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,uDAAuD,GAAG;IACpE,IAAI,EAAE,oDAAoD,CAAC;IAC3D,OAAO,EAAE,wBAAwB,CAAC,2BAA2B,CAAC,CAAC;CAChE,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,0DAA0D,GAAG;IACvE,IAAI,EAAE,uDAAuD,CAAC;IAC9D,OAAO,EAAE,wBAAwB,CAAC,8BAA8B,CAAC,CAAC;CACnE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,sDAAsD,CAAC;IAC7D,OAAO,EAAE,wBAAwB,CAAC,6BAA6B,CAAC,CAAC;CAClE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,4DAA4D,GAAG;IACzE,IAAI,EAAE,yDAAyD,CAAC;IAChE,OAAO,EAAE,wBAAwB,CAAC,gCAAgC,CAAC,CAAC;CACrE,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,kDAAkD,GAAG;IAC/D,IAAI,EAAE,+CAA+C,CAAC;IACtD,OAAO,EAAE,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;CAC3D,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sDAAsD,GAAG;IACnE,IAAI,EAAE,mDAAmD,CAAC;IAC1D,OAAO,EAAE,wBAAwB,CAAC,0BAA0B,CAAC,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,4CAA4C,GAAG;IACzD,IAAI,EAAE,yCAAyC,CAAC;IAChD,OAAO,EAAE,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;CACrD,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,wBAAwB,CAAC,YAAY,CAAC,CAAC;CACjD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,4CAA4C,GAAG;IACzD,IAAI,EAAE,yCAAyC,CAAC;IAChD,OAAO,EAAE,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;CACrD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,+CAA+C,GAAG;IAC5D,IAAI,EAAE,4CAA4C,CAAC;IACnD,OAAO,EAAE,wBAAwB,CAAC,mBAAmB,CAAC,CAAC;CACxD,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,uDAAuD,GAAG;IACpE,IAAI,EAAE,oDAAoD,CAAC;IAC3D,OAAO,EAAE,wBAAwB,CAAC,2BAA2B,CAAC,CAAC;CAChE,CAAC;AAEF,MAAM,MAAM,mDAAmD,GAAG;IAChE,IAAI,EAAE,gDAAgD,CAAC;IACvD,OAAO,EAAE,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;CAC5D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,qDAAqD,GAAG;IAClE,IAAI,EAAE,kDAAkD,CAAC;IACzD,OAAO,EAAE,wBAAwB,CAAC,yBAAyB,CAAC,CAAC;CAC9D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,qDAAqD,GAAG;IAClE,IAAI,EAAE,kDAAkD,CAAC;IACzD,OAAO,EAAE,wBAAwB,CAAC,yBAAyB,CAAC,CAAC;CAC9D,CAAC;AAEF,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,wBAAwB,CAAC,YAAY,CAAC,CAAC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAC7C,2CAA2C,GAC3C,mDAAmD,GACnD,wDAAwD,GACxD,uDAAuD,GACvD,0DAA0D,GAC1D,yDAAyD,GACzD,4DAA4D,GAC5D,kDAAkD,GAClD,sDAAsD,GACtD,4CAA4C,GAC5C,wCAAwC,GACxC,4CAA4C,GAC5C,+CAA+C,GAC/C,uDAAuD,GACvD,mDAAmD,GACnD,qDAAqD,GACrD,qDAAqD,GACrD,wCAAwC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationController-method-action-types.js","sourceRoot":"","sources":["../../../src/controllers/authentication/AuthenticationController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AuthenticationController } from './AuthenticationController.js';\n\nexport type AuthenticationControllerPerformSignInAction = {\n type: `AuthenticationController:performSignIn`;\n handler: AuthenticationController['performSignIn'];\n};\n\n/**\n * Marks profile pairing as needed. Clients call this when the SRP set\n * changes (e.g. a new keyring was added) so the next auto-sign-in cycle\n * re-runs `performSignIn` and re-pairs.\n */\nexport type AuthenticationControllerRequestProfilePairingAction = {\n type: `AuthenticationController:requestProfilePairing`;\n handler: AuthenticationController['requestProfilePairing'];\n};\n\n/**\n * Refreshes credentials enrolled on the canonical profile.\n *\n * @returns The current supported credentials.\n */\nexport type AuthenticationControllerRefreshEnrolledCredentialsAction = {\n type: `AuthenticationController:refreshEnrolledCredentials`;\n handler: AuthenticationController['refreshEnrolledCredentials'];\n};\n\n/**\n * Begins enrollment of a passkey or email OTP credential.\n *\n * @param request - Credential, optional email address, and trace reason.\n * @returns A challenge for the client-owned ceremony.\n */\nexport type AuthenticationControllerBeginCredentialEnrollmentAction = {\n type: `AuthenticationController:beginCredentialEnrollment`;\n handler: AuthenticationController['beginCredentialEnrollment'];\n};\n\n/**\n * Completes credential enrollment and refreshes the credential cache.\n *\n * A cache-refresh failure does not undo successful enrollment. Email\n * enrollment invalidates the primary SRP session *after* refresh so the\n * credentials call can reuse the still-valid access token; the next token\n * fetch then includes the newly verified email claim. That invalidation\n * happens even if the session ends mid-request: the enrollment succeeded\n * on the server, so a token cached across a lock must not be reused\n * without the new claim.\n *\n * @param request - Flow identifier, platform or email proof, and trace reason.\n * @returns The refreshed credentials, or the existing cache if refresh fails.\n */\nexport type AuthenticationControllerCompleteCredentialEnrollmentAction = {\n type: `AuthenticationController:completeCredentialEnrollment`;\n handler: AuthenticationController['completeCredentialEnrollment'];\n};\n\n/**\n * Begins verification with an enrolled credential.\n *\n * @param request - Credential type and trace reason.\n * @returns A challenge for the client-owned ceremony.\n */\nexport type AuthenticationControllerBeginCredentialVerificationAction = {\n type: `AuthenticationController:beginCredentialVerification`;\n handler: AuthenticationController['beginCredentialVerification'];\n};\n\n/**\n * Completes verification and opens a short-lived verification session.\n *\n * The assertion returned by the MFA service is exchanged at Hydra for an\n * access token. Its assurance level is not checked: the services receiving\n * the token enforce their own requirements. The token itself never enters\n * controller state.\n *\n * @param request - Flow identifier, platform or email proof, and trace reason.\n * @returns The verification token.\n */\nexport type AuthenticationControllerCompleteCredentialVerificationAction = {\n type: `AuthenticationController:completeCredentialVerification`;\n handler: AuthenticationController['completeCredentialVerification'];\n};\n\n/**\n * Returns the active verification token when it meets the requested\n * freshness.\n *\n * @param request - Optional maximum session age in milliseconds, measured\n * from when the token was obtained. Zero always requires a new ceremony.\n * @returns A live verification token, or null when no reusable session\n * exists.\n */\nexport type AuthenticationControllerGetVerificationTokenAction = {\n type: `AuthenticationController:getVerificationToken`;\n handler: AuthenticationController['getVerificationToken'];\n};\n\n/**\n * Clears every in-memory verification session and its expiration timer.\n */\nexport type AuthenticationControllerClearVerificationSessionAction = {\n type: `AuthenticationController:clearVerificationSession`;\n handler: AuthenticationController['clearVerificationSession'];\n};\n\nexport type AuthenticationControllerPerformSignOutAction = {\n type: `AuthenticationController:performSignOut`;\n handler: AuthenticationController['performSignOut'];\n};\n\n/**\n * Resets the controller to `defaultState`. Clients call this on wallet reset\n * so the next wallet starts unsigned with both pairing gates re-armed.\n */\nexport type AuthenticationControllerClearStateAction = {\n type: `AuthenticationController:clearState`;\n handler: AuthenticationController['clearState'];\n};\n\n/**\n * Returns a bearer token for the specified SRP, logging in if needed.\n *\n * When called without `entropySourceId`, returns the primary (first) SRP's\n * access token, which is effectively the canonical\n * profile's token that can be used by alias-aware consumers for cross-SRP\n * operations.\n *\n * @param entropySourceId - The entropy source ID. Omit for the primary SRP.\n * @returns The OIDC access token.\n */\nexport type AuthenticationControllerGetBearerTokenAction = {\n type: `AuthenticationController:getBearerToken`;\n handler: AuthenticationController['getBearerToken'];\n};\n\n/**\n * Returns the cached session profile, logging in if no session exists.\n *\n * The returned `canonicalProfileId` reflects the value from the most recent\n * login or pairing. In the rare event where a canonical changed because of\n * a pairing that happened on another device, the cached value may be stale\n * until the next login. For guaranteed freshness, call\n * `refreshCanonicalProfileId()` before reading `canonicalProfileId`.\n *\n * @param entropySourceId - The entropy source ID used to derive the key,\n * when multiple sources are available (Multi-SRP).\n * @returns profile for the session.\n */\nexport type AuthenticationControllerGetSessionProfileAction = {\n type: `AuthenticationController:getSessionProfile`;\n handler: AuthenticationController['getSessionProfile'];\n};\n\n/**\n * Forces a fresh retrieval of the canonical profile ID from the server\n * and propagates it to all cached SRP sessions.\n *\n * This method invalidates the primary SRP's cached session and forces a\n * re-login. Use it before operations that require a guaranteed-fresh\n * canonical (e.g. storage key derivation for Accounts ADR 0005). For\n * best-effort reads, use\n * `getSessionProfile().canonicalProfileId` instead.\n *\n * Only the primary SRP is re-logged-in regardless of how many SRPs exist —\n * the server returns the current canonical for the entire pairing group\n * from any single SRP login.\n *\n * @returns The refreshed canonical profile ID.\n */\nexport type AuthenticationControllerRefreshCanonicalProfileIdAction = {\n type: `AuthenticationController:refreshCanonicalProfileId`;\n handler: AuthenticationController['refreshCanonicalProfileId'];\n};\n\nexport type AuthenticationControllerGetUserProfileLineageAction = {\n type: `AuthenticationController:getUserProfileLineage`;\n handler: AuthenticationController['getUserProfileLineage'];\n};\n\n/**\n * Returns a Customer Service specific access token for the specified SRP,\n * logging in if needed.\n *\n * Exchanges the OIDC access token for a short-lived token scoped to the\n * customer-service audience. Customer Service tooling consumes this token to\n * identify and authenticate the user.\n *\n * @param entropySourceId - The entropy source ID. Omit for the primary SRP.\n * @returns The customer-service access token.\n */\nexport type AuthenticationControllerGetCustomerServiceTokenAction = {\n type: `AuthenticationController:getCustomerServiceToken`;\n handler: AuthenticationController['getCustomerServiceToken'];\n};\n\n/**\n * Mints a partner identity token for the specified SRP, logging in if needed.\n *\n * Calls `POST /api/v2/oidc/token` with the Hydra login bearer and returns\n * the minted `access_token`. Email on live tokens is under JWT `ext`.\n * HTTP 422 throws `EmailRequiredError` when this profile has no\n * verified email.\n *\n * @param claims - Claim names to embed. Only `email` is supported.\n * @param audience - Partner audience (`kyc` or `iron`).\n * @param entropySourceId - The entropy source ID. Omit for the primary SRP.\n * @returns The partner identity access token.\n */\nexport type AuthenticationControllerGetPartnerIdentityTokenAction = {\n type: `AuthenticationController:getPartnerIdentityToken`;\n handler: AuthenticationController['getPartnerIdentityToken'];\n};\n\nexport type AuthenticationControllerIsSignedInAction = {\n type: `AuthenticationController:isSignedIn`;\n handler: AuthenticationController['isSignedIn'];\n};\n\n/**\n * Union of all AuthenticationController action types.\n */\nexport type AuthenticationControllerMethodActions =\n | AuthenticationControllerPerformSignInAction\n | AuthenticationControllerRequestProfilePairingAction\n | AuthenticationControllerRefreshEnrolledCredentialsAction\n | AuthenticationControllerBeginCredentialEnrollmentAction\n | AuthenticationControllerCompleteCredentialEnrollmentAction\n | AuthenticationControllerBeginCredentialVerificationAction\n | AuthenticationControllerCompleteCredentialVerificationAction\n | AuthenticationControllerGetVerificationTokenAction\n | AuthenticationControllerClearVerificationSessionAction\n | AuthenticationControllerPerformSignOutAction\n | AuthenticationControllerClearStateAction\n | AuthenticationControllerGetBearerTokenAction\n | AuthenticationControllerGetSessionProfileAction\n | AuthenticationControllerRefreshCanonicalProfileIdAction\n | AuthenticationControllerGetUserProfileLineageAction\n | AuthenticationControllerGetCustomerServiceTokenAction\n | AuthenticationControllerGetPartnerIdentityTokenAction\n | AuthenticationControllerIsSignedInAction;\n"]}
|
|
1
|
+
{"version":3,"file":"AuthenticationController-method-action-types.js","sourceRoot":"","sources":["../../../src/controllers/authentication/AuthenticationController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AuthenticationController } from './AuthenticationController.js';\n\nexport type AuthenticationControllerPerformSignInAction = {\n type: `AuthenticationController:performSignIn`;\n handler: AuthenticationController['performSignIn'];\n};\n\n/**\n * Marks profile pairing as needed. Clients call this when the SRP set\n * changes (e.g. a new keyring was added) so the next auto-sign-in cycle\n * re-runs `performSignIn` and re-pairs.\n */\nexport type AuthenticationControllerRequestProfilePairingAction = {\n type: `AuthenticationController:requestProfilePairing`;\n handler: AuthenticationController['requestProfilePairing'];\n};\n\n/**\n * Refreshes credentials enrolled on the canonical profile.\n *\n * @returns The current supported credentials.\n */\nexport type AuthenticationControllerRefreshEnrolledCredentialsAction = {\n type: `AuthenticationController:refreshEnrolledCredentials`;\n handler: AuthenticationController['refreshEnrolledCredentials'];\n};\n\n/**\n * Begins enrollment of a passkey or email OTP credential.\n *\n * @param request - Credential, optional email address, and trace reason.\n * @returns A challenge for the client-owned ceremony.\n */\nexport type AuthenticationControllerBeginCredentialEnrollmentAction = {\n type: `AuthenticationController:beginCredentialEnrollment`;\n handler: AuthenticationController['beginCredentialEnrollment'];\n};\n\n/**\n * Completes credential enrollment and refreshes the credential cache.\n *\n * The server returns an assertion for the new credential, which opens a\n * verification session like `completeCredentialVerification`, replacing\n * any earlier one. If that exchange fails, the earlier session is kept:\n * the credential is enrolled either way.\n *\n * A cache-refresh failure does not undo successful enrollment. Email\n * enrollment invalidates the primary SRP session *after* refresh so the\n * credentials call can reuse the still-valid access token; the next token\n * fetch then includes the newly verified email claim. That invalidation\n * happens even if the session ends mid-request: the enrollment succeeded\n * on the server, so a token cached across a lock must not be reused\n * without the new claim.\n *\n * @param request - Flow identifier, platform or email proof, and trace reason.\n * @returns The refreshed credentials, or the existing cache if refresh fails.\n */\nexport type AuthenticationControllerCompleteCredentialEnrollmentAction = {\n type: `AuthenticationController:completeCredentialEnrollment`;\n handler: AuthenticationController['completeCredentialEnrollment'];\n};\n\n/**\n * Begins verification with an enrolled credential.\n *\n * @param request - Credential type and trace reason.\n * @returns A challenge for the client-owned ceremony.\n */\nexport type AuthenticationControllerBeginCredentialVerificationAction = {\n type: `AuthenticationController:beginCredentialVerification`;\n handler: AuthenticationController['beginCredentialVerification'];\n};\n\n/**\n * Completes verification and opens a short-lived verification session.\n *\n * The assertion returned by the MFA service is exchanged at Hydra for an\n * access token. Its assurance level is not checked: the services receiving\n * the token enforce their own requirements. The token itself never enters\n * controller state.\n *\n * @param request - Flow identifier, platform or email proof, and trace reason.\n * @returns The verification token.\n */\nexport type AuthenticationControllerCompleteCredentialVerificationAction = {\n type: `AuthenticationController:completeCredentialVerification`;\n handler: AuthenticationController['completeCredentialVerification'];\n};\n\n/**\n * Returns the active verification token when it meets the requested\n * freshness.\n *\n * Low-level: features should go through the client MFA kit\n * (`verifyOrEnroll`), which reuses a matching session without showing any\n * screen and checks which method proved it. Read the token directly only\n * from code that cannot show UI, and treat `null` as \"let the UI layer\n * ask\".\n *\n * @param request - Optional maximum session age in milliseconds, measured\n * from when the token was obtained. Zero always requires a new ceremony.\n * @returns A live verification token, or null when no reusable session\n * exists.\n */\nexport type AuthenticationControllerGetVerificationTokenAction = {\n type: `AuthenticationController:getVerificationToken`;\n handler: AuthenticationController['getVerificationToken'];\n};\n\n/**\n * Clears every in-memory verification session and its expiration timer.\n */\nexport type AuthenticationControllerClearVerificationSessionAction = {\n type: `AuthenticationController:clearVerificationSession`;\n handler: AuthenticationController['clearVerificationSession'];\n};\n\nexport type AuthenticationControllerPerformSignOutAction = {\n type: `AuthenticationController:performSignOut`;\n handler: AuthenticationController['performSignOut'];\n};\n\n/**\n * Resets the controller to `defaultState`. Clients call this on wallet reset\n * so the next wallet starts unsigned with both pairing gates re-armed.\n */\nexport type AuthenticationControllerClearStateAction = {\n type: `AuthenticationController:clearState`;\n handler: AuthenticationController['clearState'];\n};\n\n/**\n * Returns a bearer token for the specified SRP, logging in if needed.\n *\n * When called without `entropySourceId`, returns the primary (first) SRP's\n * access token, which is effectively the canonical\n * profile's token that can be used by alias-aware consumers for cross-SRP\n * operations.\n *\n * @param entropySourceId - The entropy source ID. Omit for the primary SRP.\n * @returns The OIDC access token.\n */\nexport type AuthenticationControllerGetBearerTokenAction = {\n type: `AuthenticationController:getBearerToken`;\n handler: AuthenticationController['getBearerToken'];\n};\n\n/**\n * Returns the cached session profile, logging in if no session exists.\n *\n * The returned `canonicalProfileId` reflects the value from the most recent\n * login or pairing. In the rare event where a canonical changed because of\n * a pairing that happened on another device, the cached value may be stale\n * until the next login. For guaranteed freshness, call\n * `refreshCanonicalProfileId()` before reading `canonicalProfileId`.\n *\n * @param entropySourceId - The entropy source ID used to derive the key,\n * when multiple sources are available (Multi-SRP).\n * @returns profile for the session.\n */\nexport type AuthenticationControllerGetSessionProfileAction = {\n type: `AuthenticationController:getSessionProfile`;\n handler: AuthenticationController['getSessionProfile'];\n};\n\n/**\n * Forces a fresh retrieval of the canonical profile ID from the server\n * and propagates it to all cached SRP sessions.\n *\n * This method invalidates the primary SRP's cached session and forces a\n * re-login. Use it before operations that require a guaranteed-fresh\n * canonical (e.g. storage key derivation for Accounts ADR 0005). For\n * best-effort reads, use\n * `getSessionProfile().canonicalProfileId` instead.\n *\n * Only the primary SRP is re-logged-in regardless of how many SRPs exist —\n * the server returns the current canonical for the entire pairing group\n * from any single SRP login.\n *\n * @returns The refreshed canonical profile ID.\n */\nexport type AuthenticationControllerRefreshCanonicalProfileIdAction = {\n type: `AuthenticationController:refreshCanonicalProfileId`;\n handler: AuthenticationController['refreshCanonicalProfileId'];\n};\n\nexport type AuthenticationControllerGetUserProfileLineageAction = {\n type: `AuthenticationController:getUserProfileLineage`;\n handler: AuthenticationController['getUserProfileLineage'];\n};\n\n/**\n * Returns a Customer Service specific access token for the specified SRP,\n * logging in if needed.\n *\n * Exchanges the OIDC access token for a short-lived token scoped to the\n * customer-service audience. Customer Service tooling consumes this token to\n * identify and authenticate the user.\n *\n * @param entropySourceId - The entropy source ID. Omit for the primary SRP.\n * @returns The customer-service access token.\n */\nexport type AuthenticationControllerGetCustomerServiceTokenAction = {\n type: `AuthenticationController:getCustomerServiceToken`;\n handler: AuthenticationController['getCustomerServiceToken'];\n};\n\n/**\n * Mints a partner identity token for the specified SRP, logging in if needed.\n *\n * Calls `POST /api/v2/oidc/token` with the Hydra login bearer and returns\n * the minted `access_token`. Email on live tokens is under JWT `ext`.\n * HTTP 422 throws `EmailRequiredError` when this profile has no\n * verified email.\n *\n * @param claims - Claim names to embed. Only `email` is supported.\n * @param audience - Partner audience (`kyc` or `iron`).\n * @param entropySourceId - The entropy source ID. Omit for the primary SRP.\n * @returns The partner identity access token.\n */\nexport type AuthenticationControllerGetPartnerIdentityTokenAction = {\n type: `AuthenticationController:getPartnerIdentityToken`;\n handler: AuthenticationController['getPartnerIdentityToken'];\n};\n\nexport type AuthenticationControllerIsSignedInAction = {\n type: `AuthenticationController:isSignedIn`;\n handler: AuthenticationController['isSignedIn'];\n};\n\n/**\n * Union of all AuthenticationController action types.\n */\nexport type AuthenticationControllerMethodActions =\n | AuthenticationControllerPerformSignInAction\n | AuthenticationControllerRequestProfilePairingAction\n | AuthenticationControllerRefreshEnrolledCredentialsAction\n | AuthenticationControllerBeginCredentialEnrollmentAction\n | AuthenticationControllerCompleteCredentialEnrollmentAction\n | AuthenticationControllerBeginCredentialVerificationAction\n | AuthenticationControllerCompleteCredentialVerificationAction\n | AuthenticationControllerGetVerificationTokenAction\n | AuthenticationControllerClearVerificationSessionAction\n | AuthenticationControllerPerformSignOutAction\n | AuthenticationControllerClearStateAction\n | AuthenticationControllerGetBearerTokenAction\n | AuthenticationControllerGetSessionProfileAction\n | AuthenticationControllerRefreshCanonicalProfileIdAction\n | AuthenticationControllerGetUserProfileLineageAction\n | AuthenticationControllerGetCustomerServiceTokenAction\n | AuthenticationControllerGetPartnerIdentityTokenAction\n | AuthenticationControllerIsSignedInAction;\n"]}
|
|
@@ -45,14 +45,6 @@ export type AuthenticationControllerState = {
|
|
|
45
45
|
needsSocialPairing?: boolean;
|
|
46
46
|
};
|
|
47
47
|
export declare const defaultState: AuthenticationControllerState;
|
|
48
|
-
/**
|
|
49
|
-
* Upper bound on a verification session's lifetime. The session also ends at
|
|
50
|
-
* the verification token's own `exp` (15 minutes today), whichever comes
|
|
51
|
-
* first, so this only matters if the server ever issues longer-lived tokens.
|
|
52
|
-
* Callers needing a fresher proof pass `maxSessionAgeMs` to
|
|
53
|
-
* `getVerificationToken`.
|
|
54
|
-
*/
|
|
55
|
-
export declare const VERIFICATION_SESSION_TTL_MS: number;
|
|
56
48
|
/**
|
|
57
49
|
* Default maximum age of a verification session that may authorize enrolling a
|
|
58
50
|
* credential. A session opened for an unrelated operation must not be able to
|
|
@@ -125,6 +117,11 @@ export declare class AuthenticationController extends BaseController<typeof cont
|
|
|
125
117
|
/**
|
|
126
118
|
* Completes credential enrollment and refreshes the credential cache.
|
|
127
119
|
*
|
|
120
|
+
* The server returns an assertion for the new credential, which opens a
|
|
121
|
+
* verification session like `completeCredentialVerification`, replacing
|
|
122
|
+
* any earlier one. If that exchange fails, the earlier session is kept:
|
|
123
|
+
* the credential is enrolled either way.
|
|
124
|
+
*
|
|
128
125
|
* A cache-refresh failure does not undo successful enrollment. Email
|
|
129
126
|
* enrollment invalidates the primary SRP session *after* refresh so the
|
|
130
127
|
* credentials call can reuse the still-valid access token; the next token
|
|
@@ -160,6 +157,12 @@ export declare class AuthenticationController extends BaseController<typeof cont
|
|
|
160
157
|
* Returns the active verification token when it meets the requested
|
|
161
158
|
* freshness.
|
|
162
159
|
*
|
|
160
|
+
* Low-level: features should go through the client MFA kit
|
|
161
|
+
* (`verifyOrEnroll`), which reuses a matching session without showing any
|
|
162
|
+
* screen and checks which method proved it. Read the token directly only
|
|
163
|
+
* from code that cannot show UI, and treat `null` as "let the UI layer
|
|
164
|
+
* ask".
|
|
165
|
+
*
|
|
163
166
|
* @param request - Optional maximum session age in milliseconds, measured
|
|
164
167
|
* from when the token was obtained. Zero always requires a new ceremony.
|
|
165
168
|
* @returns A live verification token, or null when no reusable session
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationController.d.ts","sourceRoot":"","sources":["../../../src/controllers/authentication/AuthenticationController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,4BAA4B,CAAC;AAE9E,OAAO,KAAK,EACV,+BAA+B,EAC/B,0BAA0B,EAC1B,4BAA4B,EAC5B,0CAA0C,EAC3C,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EACV,gDAAgD,EAChD,0CAA0C,EAC3C,MAAM,0CAA0C,CAAC;AAYlD,OAAO,KAAK,EAEV,aAAa,EACb,YAAY,EAIZ,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,
|
|
1
|
+
{"version":3,"file":"AuthenticationController.d.ts","sourceRoot":"","sources":["../../../src/controllers/authentication/AuthenticationController.ts"],"names":[],"mappings":"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"}
|
|
@@ -71,14 +71,6 @@ const metadata = {
|
|
|
71
71
|
usedInUi: true,
|
|
72
72
|
},
|
|
73
73
|
};
|
|
74
|
-
/**
|
|
75
|
-
* Upper bound on a verification session's lifetime. The session also ends at
|
|
76
|
-
* the verification token's own `exp` (15 minutes today), whichever comes
|
|
77
|
-
* first, so this only matters if the server ever issues longer-lived tokens.
|
|
78
|
-
* Callers needing a fresher proof pass `maxSessionAgeMs` to
|
|
79
|
-
* `getVerificationToken`.
|
|
80
|
-
*/
|
|
81
|
-
export const VERIFICATION_SESSION_TTL_MS = 15 * 60_000;
|
|
82
74
|
/**
|
|
83
75
|
* Default maximum age of a verification session that may authorize enrolling a
|
|
84
76
|
* credential. A session opened for an unrelated operation must not be able to
|
|
@@ -147,6 +139,10 @@ export class AuthenticationController extends BaseController {
|
|
|
147
139
|
* `performSignIn` can't clear `needsProfilePairing` afterwards.
|
|
148
140
|
*/
|
|
149
141
|
#profilePairingRequestEpoch = 0;
|
|
142
|
+
/**
|
|
143
|
+
* Sign-in currently running. Overlapping callers share it.
|
|
144
|
+
*/
|
|
145
|
+
#ongoingSignIn;
|
|
150
146
|
#keyringController = {
|
|
151
147
|
setupLockedStateSubscriptions: () => {
|
|
152
148
|
const { isUnlocked } = this.messenger.call('KeyringController:getState');
|
|
@@ -349,6 +345,18 @@ export class AuthenticationController extends BaseController {
|
|
|
349
345
|
}
|
|
350
346
|
async performSignIn() {
|
|
351
347
|
this.#assertIsUnlocked('performSignIn');
|
|
348
|
+
if (this.#ongoingSignIn) {
|
|
349
|
+
return await this.#ongoingSignIn;
|
|
350
|
+
}
|
|
351
|
+
const signIn = this.#runPerformSignIn().finally(() => {
|
|
352
|
+
if (this.#ongoingSignIn === signIn) {
|
|
353
|
+
this.#ongoingSignIn = undefined;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
this.#ongoingSignIn = signIn;
|
|
357
|
+
return await signIn;
|
|
358
|
+
}
|
|
359
|
+
async #runPerformSignIn() {
|
|
352
360
|
const epochAtStart = this.#profilePairingRequestEpoch;
|
|
353
361
|
const entropySourceIds = this.#getHdKeyringEntropySourceIds();
|
|
354
362
|
const accessTokens = [];
|
|
@@ -695,6 +703,11 @@ export class AuthenticationController extends BaseController {
|
|
|
695
703
|
/**
|
|
696
704
|
* Completes credential enrollment and refreshes the credential cache.
|
|
697
705
|
*
|
|
706
|
+
* The server returns an assertion for the new credential, which opens a
|
|
707
|
+
* verification session like `completeCredentialVerification`, replacing
|
|
708
|
+
* any earlier one. If that exchange fails, the earlier session is kept:
|
|
709
|
+
* the credential is enrolled either way.
|
|
710
|
+
*
|
|
698
711
|
* A cache-refresh failure does not undo successful enrollment. Email
|
|
699
712
|
* enrollment invalidates the primary SRP session *after* refresh so the
|
|
700
713
|
* credentials call can reuse the still-valid access token; the next token
|
|
@@ -711,8 +724,22 @@ export class AuthenticationController extends BaseController {
|
|
|
711
724
|
const sessionEpoch = this.#authSessionEpoch;
|
|
712
725
|
assertValidMfaRequest(request, CompleteEnrollmentRequestStruct);
|
|
713
726
|
const { type } = request.proof;
|
|
727
|
+
const { operation } = request.reason;
|
|
714
728
|
const primaryEntropySourceId = this.#getPrimaryEntropySourceId();
|
|
715
|
-
await this.#runMfaRequest('MFA Enroll Complete',
|
|
729
|
+
const assertion = await this.#runMfaRequest('MFA Enroll Complete', operation, type, async () => await this.#auth.completeMfaEnrollment(request.flowId, request.proof, primaryEntropySourceId));
|
|
730
|
+
try {
|
|
731
|
+
await this.#openVerificationSessionFromAssertion(assertion, {
|
|
732
|
+
operation,
|
|
733
|
+
type,
|
|
734
|
+
sessionEpoch,
|
|
735
|
+
methodName: 'completeCredentialEnrollment',
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
catch {
|
|
739
|
+
// Callers see no session and verify the credential instead.
|
|
740
|
+
}
|
|
741
|
+
// Also catches a session that ended during the enrollment request; the
|
|
742
|
+
// exchange above then ran for nothing, and its session was never opened.
|
|
716
743
|
try {
|
|
717
744
|
this.#assertAuthSessionEpoch(sessionEpoch, 'completeCredentialEnrollment');
|
|
718
745
|
}
|
|
@@ -722,9 +749,6 @@ export class AuthenticationController extends BaseController {
|
|
|
722
749
|
}
|
|
723
750
|
throw error;
|
|
724
751
|
}
|
|
725
|
-
// The verification session is deliberately kept: adding a factor does not
|
|
726
|
-
// weaken an earlier proof, and `beginCredentialEnrollment` already limits
|
|
727
|
-
// which sessions may add the next one.
|
|
728
752
|
try {
|
|
729
753
|
return await this.refreshEnrolledCredentials();
|
|
730
754
|
}
|
|
@@ -772,8 +796,28 @@ export class AuthenticationController extends BaseController {
|
|
|
772
796
|
const primaryEntropySourceId = this.#getPrimaryEntropySourceId();
|
|
773
797
|
const assertion = await this.#runMfaRequest('MFA Verification Complete', operation, type, async () => await this.#auth.completeMfaVerification(request.flowId, request.proof, primaryEntropySourceId));
|
|
774
798
|
this.#assertAuthSessionEpoch(sessionEpoch, 'completeCredentialVerification');
|
|
799
|
+
return await this.#openVerificationSessionFromAssertion(assertion, {
|
|
800
|
+
operation,
|
|
801
|
+
type,
|
|
802
|
+
sessionEpoch,
|
|
803
|
+
methodName: 'completeCredentialVerification',
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Exchanges an MFA assertion at Hydra and opens the verification session
|
|
808
|
+
* with the resulting token.
|
|
809
|
+
*
|
|
810
|
+
* @param assertion - Assertion returned by a verify or enroll completion.
|
|
811
|
+
* @param context - Trace tags and the session the call started in.
|
|
812
|
+
* @param context.operation - Feature operation, for tracing.
|
|
813
|
+
* @param context.type - Credential type the assertion proves, for tracing.
|
|
814
|
+
* @param context.sessionEpoch - Authenticated session the call started in.
|
|
815
|
+
* @param context.methodName - Public method name, for error messages.
|
|
816
|
+
* @returns The verification token.
|
|
817
|
+
*/
|
|
818
|
+
async #openVerificationSessionFromAssertion(assertion, { operation, type, sessionEpoch, methodName, }) {
|
|
775
819
|
const accessToken = await this.#runMfaRequest('MFA Token Exchange', operation, type, async () => await this.#auth.exchangeMfaAssertion(assertion.token));
|
|
776
|
-
this.#assertAuthSessionEpoch(sessionEpoch,
|
|
820
|
+
this.#assertAuthSessionEpoch(sessionEpoch, methodName);
|
|
777
821
|
let decodedClaims;
|
|
778
822
|
try {
|
|
779
823
|
decodedClaims = decodeJwtPayload(accessToken.accessToken);
|
|
@@ -782,8 +826,8 @@ export class AuthenticationController extends BaseController {
|
|
|
782
826
|
throw new VerificationTokenInvalidError(toErrorMessage(error));
|
|
783
827
|
}
|
|
784
828
|
const claims = parseVerificationTokenClaims(decodedClaims);
|
|
785
|
-
if (
|
|
786
|
-
throw new VerificationTokenInvalidError('Verification token
|
|
829
|
+
if (!Number.isFinite(accessToken.expiresIn) || accessToken.expiresIn <= 0) {
|
|
830
|
+
throw new VerificationTokenInvalidError('Verification token has no remaining lifetime');
|
|
787
831
|
}
|
|
788
832
|
const token = { ...accessToken, claims };
|
|
789
833
|
this.#openVerificationSession(token);
|
|
@@ -793,6 +837,12 @@ export class AuthenticationController extends BaseController {
|
|
|
793
837
|
* Returns the active verification token when it meets the requested
|
|
794
838
|
* freshness.
|
|
795
839
|
*
|
|
840
|
+
* Low-level: features should go through the client MFA kit
|
|
841
|
+
* (`verifyOrEnroll`), which reuses a matching session without showing any
|
|
842
|
+
* screen and checks which method proved it. Read the token directly only
|
|
843
|
+
* from code that cannot show UI, and treat `null` as "let the UI layer
|
|
844
|
+
* ask".
|
|
845
|
+
*
|
|
796
846
|
* @param request - Optional maximum session age in milliseconds, measured
|
|
797
847
|
* from when the token was obtained. Zero always requires a new ceremony.
|
|
798
848
|
* @returns A live verification token, or null when no reusable session
|
|
@@ -820,15 +870,16 @@ export class AuthenticationController extends BaseController {
|
|
|
820
870
|
return session.token;
|
|
821
871
|
}
|
|
822
872
|
/**
|
|
823
|
-
* Opens the verification session
|
|
824
|
-
*
|
|
873
|
+
* Opens the verification session for the lifetime the server gave the token.
|
|
874
|
+
* It is measured from `expires_in` on the local clock rather than read from
|
|
875
|
+
* `exp`, so a skewed device clock cannot shorten or extend it.
|
|
825
876
|
*
|
|
826
877
|
* @param token - The freshly exchanged verification token.
|
|
827
878
|
*/
|
|
828
879
|
#openVerificationSession(token) {
|
|
829
880
|
const audience = DEFAULT_AUDIENCE;
|
|
830
881
|
this.#dropVerificationSession(audience);
|
|
831
|
-
const expiresAt =
|
|
882
|
+
const expiresAt = token.obtainedAt + token.expiresIn * 1000;
|
|
832
883
|
const timer = setTimeout(() => this.#dropVerificationSession(audience), Math.max(0, expiresAt - Date.now()));
|
|
833
884
|
// Never keep a Node process alive for the expiry timer (tests, tooling).
|
|
834
885
|
timer.unref?.();
|