@account-kit/signer 4.21.0 → 4.23.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/dist/esm/base.d.ts +183 -2
- package/dist/esm/base.js +352 -55
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +46 -5
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.d.ts +51 -4
- package/dist/esm/client/index.js +201 -9
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +102 -1
- package/dist/esm/client/types.js.map +1 -1
- package/dist/esm/errors.d.ts +6 -0
- package/dist/esm/errors.js +18 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/session/manager.d.ts +2 -0
- package/dist/esm/session/manager.js.map +1 -1
- package/dist/esm/signer.d.ts +4 -2
- package/dist/esm/signer.js.map +1 -1
- package/dist/esm/types.d.ts +15 -1
- package/dist/esm/types.js +6 -0
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/parseMfaError.d.ts +2 -0
- package/dist/esm/utils/parseMfaError.js +15 -0
- package/dist/esm/utils/parseMfaError.js.map +1 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/base.d.ts +183 -2
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +46 -5
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +51 -4
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/client/types.d.ts +102 -1
- package/dist/types/client/types.d.ts.map +1 -1
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/session/manager.d.ts +2 -0
- package/dist/types/session/manager.d.ts.map +1 -1
- package/dist/types/signer.d.ts +4 -2
- package/dist/types/signer.d.ts.map +1 -1
- package/dist/types/types.d.ts +15 -1
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/parseMfaError.d.ts +3 -0
- package/dist/types/utils/parseMfaError.d.ts.map +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +4 -4
- package/src/base.ts +421 -62
- package/src/client/base.ts +56 -2
- package/src/client/index.ts +225 -10
- package/src/client/types.ts +112 -1
- package/src/errors.ts +11 -1
- package/src/index.ts +5 -1
- package/src/session/manager.ts +6 -1
- package/src/signer.ts +6 -1
- package/src/types.ts +16 -0
- package/src/utils/parseMfaError.ts +15 -0
- package/src/version.ts +1 -1
package/src/client/index.ts
CHANGED
|
@@ -17,9 +17,25 @@ import type {
|
|
|
17
17
|
OauthConfig,
|
|
18
18
|
OtpParams,
|
|
19
19
|
User,
|
|
20
|
+
MfaFactor,
|
|
21
|
+
EnableMfaParams,
|
|
22
|
+
EnableMfaResult,
|
|
23
|
+
VerifyMfaParams,
|
|
24
|
+
RemoveMfaParams,
|
|
25
|
+
SubmitOtpCodeResponse,
|
|
26
|
+
ValidateMultiFactorsParams,
|
|
20
27
|
} from "./types.js";
|
|
28
|
+
import { MfaRequiredError, NotAuthenticatedError } from "../errors.js";
|
|
29
|
+
import { parseMfaError } from "../utils/parseMfaError.js";
|
|
21
30
|
|
|
22
31
|
const CHECK_CLOSE_INTERVAL = 500;
|
|
32
|
+
const MFA_PAYLOAD = {
|
|
33
|
+
GET: "get_mfa",
|
|
34
|
+
ADD: "add_mfa",
|
|
35
|
+
DELETE: "delete_mfas",
|
|
36
|
+
VERIFY: "verify_mfa",
|
|
37
|
+
LIST: "list_mfas",
|
|
38
|
+
};
|
|
23
39
|
|
|
24
40
|
export const AlchemySignerClientParamsSchema = z.object({
|
|
25
41
|
connection: ConnectionConfigSchema,
|
|
@@ -198,13 +214,25 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
198
214
|
const { email, emailMode, expirationSeconds } = params;
|
|
199
215
|
const publicKey = await this.initIframeStamper();
|
|
200
216
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
217
|
+
try {
|
|
218
|
+
return await this.request("/v1/auth", {
|
|
219
|
+
email,
|
|
220
|
+
emailMode,
|
|
221
|
+
targetPublicKey: publicKey,
|
|
222
|
+
expirationSeconds,
|
|
223
|
+
redirectParams: params.redirectParams?.toString(),
|
|
224
|
+
multiFactors: params.multiFactors,
|
|
225
|
+
});
|
|
226
|
+
} catch (error) {
|
|
227
|
+
const multiFactors = parseMfaError(error);
|
|
228
|
+
|
|
229
|
+
// If MFA is required, and emailMode is Magic Link, the user must submit mfa with the request or
|
|
230
|
+
// the the server will return an error with the required mfa factors.
|
|
231
|
+
if (multiFactors) {
|
|
232
|
+
throw new MfaRequiredError(multiFactors);
|
|
233
|
+
}
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
208
236
|
};
|
|
209
237
|
|
|
210
238
|
/**
|
|
@@ -235,14 +263,38 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
235
263
|
*/
|
|
236
264
|
public override async submitOtpCode(
|
|
237
265
|
args: Omit<OtpParams, "targetPublicKey">
|
|
238
|
-
): Promise<
|
|
266
|
+
): Promise<SubmitOtpCodeResponse> {
|
|
239
267
|
this.eventEmitter.emit("authenticating", { type: "otpVerify" });
|
|
240
268
|
const targetPublicKey = await this.initIframeStamper();
|
|
241
|
-
const
|
|
269
|
+
const response = await this.request("/v1/otp", {
|
|
242
270
|
...args,
|
|
243
271
|
targetPublicKey,
|
|
244
272
|
});
|
|
245
|
-
|
|
273
|
+
|
|
274
|
+
if ("credentialBundle" in response && response.credentialBundle) {
|
|
275
|
+
return {
|
|
276
|
+
mfaRequired: false,
|
|
277
|
+
bundle: response.credentialBundle,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// If the server says "MFA_REQUIRED", pass that data back to the caller:
|
|
282
|
+
if (
|
|
283
|
+
response.status === "MFA_REQUIRED" &&
|
|
284
|
+
response.encryptedPayload &&
|
|
285
|
+
response.multiFactors
|
|
286
|
+
) {
|
|
287
|
+
return {
|
|
288
|
+
mfaRequired: true,
|
|
289
|
+
encryptedPayload: response.encryptedPayload,
|
|
290
|
+
multiFactors: response.multiFactors,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Otherwise, it's truly an error:
|
|
295
|
+
throw new Error(
|
|
296
|
+
"Failed to submit OTP code. Server did not return required fields."
|
|
297
|
+
);
|
|
246
298
|
}
|
|
247
299
|
|
|
248
300
|
/**
|
|
@@ -670,6 +722,169 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
670
722
|
const nonce = this.getOauthNonce(publicKey);
|
|
671
723
|
return this.request("/v1/prepare-oauth", { nonce });
|
|
672
724
|
};
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Retrieves the list of MFA factors configured for the current user.
|
|
728
|
+
*
|
|
729
|
+
* @returns {Promise<{ multiFactors: MfaFactor[] }>} A promise that resolves to an array of configured MFA factors
|
|
730
|
+
* @throws {NotAuthenticatedError} If no user is authenticated
|
|
731
|
+
*/
|
|
732
|
+
public override getMfaFactors = async (): Promise<{
|
|
733
|
+
multiFactors: MfaFactor[];
|
|
734
|
+
}> => {
|
|
735
|
+
if (!this.user) {
|
|
736
|
+
throw new NotAuthenticatedError();
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
const stampedRequest = await this.turnkeyClient.stampSignRawPayload({
|
|
740
|
+
organizationId: this.user.orgId,
|
|
741
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
742
|
+
timestampMs: Date.now().toString(),
|
|
743
|
+
parameters: {
|
|
744
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
745
|
+
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
746
|
+
payload: MFA_PAYLOAD.LIST,
|
|
747
|
+
signWith: this.user.address,
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
return this.request("/v1/auth-list-multi-factors", {
|
|
752
|
+
stampedRequest,
|
|
753
|
+
});
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Initiates the setup of a new MFA factor for the current user. Mfa will need to be verified before it is active.
|
|
758
|
+
*
|
|
759
|
+
* @param {EnableMfaParams} params The parameters required to enable a new MFA factor
|
|
760
|
+
* @returns {Promise<EnableMfaResult>} A promise that resolves to the factor setup information
|
|
761
|
+
* @throws {NotAuthenticatedError} If no user is authenticated
|
|
762
|
+
* @throws {Error} If an unsupported factor type is provided
|
|
763
|
+
*/
|
|
764
|
+
public override addMfa = async (
|
|
765
|
+
params: EnableMfaParams
|
|
766
|
+
): Promise<EnableMfaResult> => {
|
|
767
|
+
if (!this.user) {
|
|
768
|
+
throw new NotAuthenticatedError();
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
const stampedRequest = await this.turnkeyClient.stampSignRawPayload({
|
|
772
|
+
organizationId: this.user.orgId,
|
|
773
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
774
|
+
timestampMs: Date.now().toString(),
|
|
775
|
+
parameters: {
|
|
776
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
777
|
+
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
778
|
+
payload: MFA_PAYLOAD.ADD,
|
|
779
|
+
signWith: this.user.address,
|
|
780
|
+
},
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
switch (params.multiFactorType) {
|
|
784
|
+
case "totp":
|
|
785
|
+
return this.request("/v1/auth-request-multi-factor", {
|
|
786
|
+
stampedRequest,
|
|
787
|
+
multiFactorType: params.multiFactorType,
|
|
788
|
+
});
|
|
789
|
+
default:
|
|
790
|
+
throw new Error(
|
|
791
|
+
`Unsupported MFA factor type: ${params.multiFactorType}`
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Verifies a newly created MFA factor to complete the setup process.
|
|
798
|
+
*
|
|
799
|
+
* @param {VerifyMfaParams} params The parameters required to verify the MFA factor
|
|
800
|
+
* @returns {Promise<{ multiFactors: MfaFactor[] }>} A promise that resolves to the updated list of MFA factors
|
|
801
|
+
* @throws {NotAuthenticatedError} If no user is authenticated
|
|
802
|
+
*/
|
|
803
|
+
public override verifyMfa = async (
|
|
804
|
+
params: VerifyMfaParams
|
|
805
|
+
): Promise<{ multiFactors: MfaFactor[] }> => {
|
|
806
|
+
if (!this.user) {
|
|
807
|
+
throw new NotAuthenticatedError();
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const stampedRequest = await this.turnkeyClient.stampSignRawPayload({
|
|
811
|
+
organizationId: this.user.orgId,
|
|
812
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
813
|
+
timestampMs: Date.now().toString(),
|
|
814
|
+
parameters: {
|
|
815
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
816
|
+
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
817
|
+
payload: MFA_PAYLOAD.VERIFY,
|
|
818
|
+
signWith: this.user.address,
|
|
819
|
+
},
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
return this.request("/v1/auth-verify-multi-factor", {
|
|
823
|
+
stampedRequest,
|
|
824
|
+
multiFactorId: params.multiFactorId,
|
|
825
|
+
multiFactorCode: params.multiFactorCode,
|
|
826
|
+
});
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* Removes existing MFA factors by ID.
|
|
831
|
+
*
|
|
832
|
+
* @param {RemoveMfaParams} params The parameters specifying which factors to disable
|
|
833
|
+
* @returns {Promise<{ multiFactors: MfaFactor[] }>} A promise that resolves to the updated list of MFA factors
|
|
834
|
+
* @throws {NotAuthenticatedError} If no user is authenticated
|
|
835
|
+
*/
|
|
836
|
+
public override removeMfa = async (
|
|
837
|
+
params: RemoveMfaParams
|
|
838
|
+
): Promise<{ multiFactors: MfaFactor[] }> => {
|
|
839
|
+
if (!this.user) {
|
|
840
|
+
throw new NotAuthenticatedError();
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
const stampedRequest = await this.turnkeyClient.stampSignRawPayload({
|
|
844
|
+
organizationId: this.user.orgId,
|
|
845
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
846
|
+
timestampMs: Date.now().toString(),
|
|
847
|
+
parameters: {
|
|
848
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
849
|
+
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
850
|
+
payload: MFA_PAYLOAD.DELETE,
|
|
851
|
+
signWith: this.user.address,
|
|
852
|
+
},
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
return this.request("/v1/auth-delete-multi-factors", {
|
|
856
|
+
stampedRequest,
|
|
857
|
+
multiFactorIds: params.multiFactorIds,
|
|
858
|
+
});
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Validates multiple MFA factors using the provided encrypted payload and MFA codes.
|
|
863
|
+
*
|
|
864
|
+
* @param {ValidateMultiFactorsParams} params The validation parameters
|
|
865
|
+
* @returns {Promise<{ bundle: string }>} A promise that resolves to an object containing the credential bundle
|
|
866
|
+
* @throws {Error} If no credential bundle is returned from the server
|
|
867
|
+
*/
|
|
868
|
+
public override async validateMultiFactors(
|
|
869
|
+
params: ValidateMultiFactorsParams
|
|
870
|
+
): Promise<{ bundle: string }> {
|
|
871
|
+
// Send the encryptedPayload plus TOTP codes, etc:
|
|
872
|
+
const response = await this.request("/v1/auth-validate-multi-factors", {
|
|
873
|
+
encryptedPayload: params.encryptedPayload,
|
|
874
|
+
multiFactors: params.multiFactors,
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
// The server is expected to return the *decrypted* payload in `response.payload.credentialBundle`
|
|
878
|
+
if (!response.payload || !response.payload.credentialBundle) {
|
|
879
|
+
throw new Error(
|
|
880
|
+
"Request to validateMultiFactors did not return a credential bundle"
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
return {
|
|
885
|
+
bundle: response.payload.credentialBundle,
|
|
886
|
+
};
|
|
887
|
+
}
|
|
673
888
|
}
|
|
674
889
|
|
|
675
890
|
/**
|
package/src/client/types.ts
CHANGED
|
@@ -54,6 +54,7 @@ export type EmailAuthParams = {
|
|
|
54
54
|
expirationSeconds?: number;
|
|
55
55
|
targetPublicKey: string;
|
|
56
56
|
redirectParams?: URLSearchParams;
|
|
57
|
+
multiFactors?: VerifyMfaParams[];
|
|
57
58
|
};
|
|
58
59
|
|
|
59
60
|
export type OauthParams = Extract<AuthParams, { type: "oauth" }> & {
|
|
@@ -66,8 +67,20 @@ export type OtpParams = {
|
|
|
66
67
|
otpCode: string;
|
|
67
68
|
targetPublicKey: string;
|
|
68
69
|
expirationSeconds?: number;
|
|
70
|
+
multiFactors?: VerifyMfaParams[];
|
|
69
71
|
};
|
|
70
72
|
|
|
73
|
+
export type OtpResponse =
|
|
74
|
+
| {
|
|
75
|
+
status: "SUCCESS";
|
|
76
|
+
credentialBundle: string;
|
|
77
|
+
}
|
|
78
|
+
| {
|
|
79
|
+
status: "MFA_REQUIRED";
|
|
80
|
+
encryptedPayload: string;
|
|
81
|
+
multiFactors: MfaFactor[];
|
|
82
|
+
};
|
|
83
|
+
|
|
71
84
|
export type SignupResponse = {
|
|
72
85
|
orgId: string;
|
|
73
86
|
userId?: string;
|
|
@@ -132,10 +145,12 @@ export type SignerEndpoints = [
|
|
|
132
145
|
Route: "/v1/auth";
|
|
133
146
|
Body: Omit<EmailAuthParams, "redirectParams"> & {
|
|
134
147
|
redirectParams?: string;
|
|
148
|
+
multiFactors?: VerifyMfaParams[];
|
|
135
149
|
};
|
|
136
150
|
Response: {
|
|
137
151
|
orgId: string;
|
|
138
152
|
otpId?: string;
|
|
153
|
+
multiFactors?: MfaFactor[];
|
|
139
154
|
};
|
|
140
155
|
},
|
|
141
156
|
{
|
|
@@ -166,12 +181,61 @@ export type SignerEndpoints = [
|
|
|
166
181
|
{
|
|
167
182
|
Route: "/v1/otp";
|
|
168
183
|
Body: OtpParams;
|
|
169
|
-
Response:
|
|
184
|
+
Response: OtpResponse;
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
Route: "/v1/auth-list-multi-factors";
|
|
188
|
+
Body: {
|
|
189
|
+
stampedRequest: TSignedRequest;
|
|
190
|
+
};
|
|
191
|
+
Response: {
|
|
192
|
+
multiFactors: MfaFactor[];
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
Route: "/v1/auth-delete-multi-factors";
|
|
197
|
+
Body: {
|
|
198
|
+
stampedRequest: TSignedRequest;
|
|
199
|
+
multiFactorIds: string[];
|
|
200
|
+
};
|
|
201
|
+
Response: {
|
|
202
|
+
multiFactors: MfaFactor[];
|
|
203
|
+
};
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
Route: "/v1/auth-request-multi-factor";
|
|
207
|
+
Body: {
|
|
208
|
+
stampedRequest: TSignedRequest;
|
|
209
|
+
multiFactorType: MultiFactorType;
|
|
210
|
+
};
|
|
211
|
+
Response: EnableMfaResult;
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
Route: "/v1/auth-verify-multi-factor";
|
|
215
|
+
Body: VerifyMfaParams & {
|
|
216
|
+
stampedRequest: TSignedRequest;
|
|
217
|
+
};
|
|
218
|
+
Response: {
|
|
219
|
+
multiFactors: MfaFactor[];
|
|
220
|
+
};
|
|
170
221
|
},
|
|
171
222
|
{
|
|
172
223
|
Route: "/v1/signer-config";
|
|
173
224
|
Body: {};
|
|
174
225
|
Response: SignerConfig;
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
Route: "/v1/auth-validate-multi-factors";
|
|
229
|
+
Body: {
|
|
230
|
+
encryptedPayload: string;
|
|
231
|
+
multiFactors: VerifyMfaParams[];
|
|
232
|
+
};
|
|
233
|
+
Response: {
|
|
234
|
+
payload: {
|
|
235
|
+
credentialBundle?: string;
|
|
236
|
+
};
|
|
237
|
+
multiFactors: MfaFactor[];
|
|
238
|
+
};
|
|
175
239
|
}
|
|
176
240
|
];
|
|
177
241
|
|
|
@@ -216,6 +280,53 @@ export type GetOauthProviderUrlArgs = {
|
|
|
216
280
|
usesRelativeUrl?: boolean;
|
|
217
281
|
};
|
|
218
282
|
|
|
283
|
+
export type MfaFactor = {
|
|
284
|
+
multiFactorId: string;
|
|
285
|
+
multiFactorType: string;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
type MultiFactorType = "totp";
|
|
289
|
+
|
|
290
|
+
export type EnableMfaParams = {
|
|
291
|
+
multiFactorType: MultiFactorType;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export type EnableMfaResult = {
|
|
295
|
+
multiFactorType: MultiFactorType;
|
|
296
|
+
multiFactorId: string;
|
|
297
|
+
multiFactorTotpUrl: string;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
export type VerifyMfaParams = {
|
|
301
|
+
multiFactorId: string;
|
|
302
|
+
multiFactorCode: string;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
export type RemoveMfaParams = {
|
|
306
|
+
multiFactorIds: string[];
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
export type ValidateMultiFactorsParams = {
|
|
310
|
+
encryptedPayload: string;
|
|
311
|
+
multiFactors: Array<{
|
|
312
|
+
multiFactorId: string;
|
|
313
|
+
multiFactorCode: string;
|
|
314
|
+
}>;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export type MfaChallenge = {
|
|
318
|
+
multiFactorId: string;
|
|
319
|
+
multiFactorChallenge:
|
|
320
|
+
| {
|
|
321
|
+
code: string;
|
|
322
|
+
}
|
|
323
|
+
| Record<string, any>;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
export type SubmitOtpCodeResponse =
|
|
327
|
+
| { bundle: string; mfaRequired: false }
|
|
328
|
+
| { mfaRequired: true; encryptedPayload: string; multiFactors: MfaFactor[] };
|
|
329
|
+
|
|
219
330
|
export type experimental_CreateApiKeyParams = {
|
|
220
331
|
name: string;
|
|
221
332
|
publicKey: string;
|
package/src/errors.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseError } from "@aa-sdk/core";
|
|
2
|
-
|
|
2
|
+
import type { MfaFactor } from "./client/types";
|
|
3
3
|
export class NotAuthenticatedError extends BaseError {
|
|
4
4
|
override name = "NotAuthenticatedError";
|
|
5
5
|
constructor() {
|
|
@@ -23,3 +23,13 @@ export class OAuthProvidersError extends BaseError {
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
export class MfaRequiredError extends BaseError {
|
|
28
|
+
override name = "MfaRequiredError";
|
|
29
|
+
public multiFactors: MfaFactor[];
|
|
30
|
+
|
|
31
|
+
constructor(multiFactors: MfaFactor[]) {
|
|
32
|
+
super("MFA is required for this user");
|
|
33
|
+
this.multiFactors = multiFactors;
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,11 @@ export {
|
|
|
6
6
|
OauthFailedError,
|
|
7
7
|
} from "./client/index.js";
|
|
8
8
|
export type * from "./client/types.js";
|
|
9
|
-
export {
|
|
9
|
+
export {
|
|
10
|
+
NotAuthenticatedError,
|
|
11
|
+
OAuthProvidersError,
|
|
12
|
+
MfaRequiredError,
|
|
13
|
+
} from "./errors.js";
|
|
10
14
|
export {
|
|
11
15
|
DEFAULT_SESSION_MS,
|
|
12
16
|
SessionManagerParamsSchema,
|
package/src/session/manager.ts
CHANGED
|
@@ -43,7 +43,12 @@ type Store = Mutate<
|
|
|
43
43
|
[["zustand/subscribeWithSelector", never], ["zustand/persist", SessionState]]
|
|
44
44
|
>;
|
|
45
45
|
|
|
46
|
-
type TemporarySession = {
|
|
46
|
+
type TemporarySession = {
|
|
47
|
+
orgId: string;
|
|
48
|
+
isNewUser?: boolean;
|
|
49
|
+
encryptedPayload?: string;
|
|
50
|
+
mfaFactorId?: string;
|
|
51
|
+
};
|
|
47
52
|
|
|
48
53
|
export class SessionManager {
|
|
49
54
|
private sessionKey: string;
|
package/src/signer.ts
CHANGED
|
@@ -4,7 +4,10 @@ import {
|
|
|
4
4
|
AlchemySignerClientParamsSchema,
|
|
5
5
|
AlchemySignerWebClient,
|
|
6
6
|
} from "./client/index.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
CredentialCreationOptionOverrides,
|
|
9
|
+
VerifyMfaParams,
|
|
10
|
+
} from "./client/types.js";
|
|
8
11
|
import { SessionManagerParamsSchema } from "./session/manager.js";
|
|
9
12
|
|
|
10
13
|
export type AuthParams =
|
|
@@ -14,6 +17,7 @@ export type AuthParams =
|
|
|
14
17
|
/** @deprecated This option will be overriden by dashboard settings. Please use the dashboard settings instead. This option will be removed in a future release. */
|
|
15
18
|
emailMode?: "magicLink" | "otp";
|
|
16
19
|
redirectParams?: URLSearchParams;
|
|
20
|
+
multiFactors?: VerifyMfaParams[];
|
|
17
21
|
}
|
|
18
22
|
| { type: "email"; bundle: string; orgId?: string; isNewUser?: boolean }
|
|
19
23
|
| {
|
|
@@ -48,6 +52,7 @@ export type AuthParams =
|
|
|
48
52
|
| {
|
|
49
53
|
type: "otp";
|
|
50
54
|
otpCode: string;
|
|
55
|
+
multiFactors?: VerifyMfaParams[];
|
|
51
56
|
};
|
|
52
57
|
|
|
53
58
|
export type OauthProviderConfig =
|
package/src/types.ts
CHANGED
|
@@ -6,6 +6,11 @@ export type AlchemySignerEvents = {
|
|
|
6
6
|
disconnected(): void;
|
|
7
7
|
statusChanged(status: AlchemySignerStatus): void;
|
|
8
8
|
errorChanged(error: ErrorInfo | undefined): void;
|
|
9
|
+
mfaStatusChanged(mfaStatus: {
|
|
10
|
+
mfaRequired: boolean;
|
|
11
|
+
mfaFactorId?: string;
|
|
12
|
+
encryptedPayload?: string;
|
|
13
|
+
}): void;
|
|
9
14
|
};
|
|
10
15
|
|
|
11
16
|
export type AlchemySignerEvent = keyof AlchemySignerEvents;
|
|
@@ -19,9 +24,20 @@ export enum AlchemySignerStatus {
|
|
|
19
24
|
AUTHENTICATING_OAUTH = "AUTHENTICATING_OAUTH",
|
|
20
25
|
AWAITING_EMAIL_AUTH = "AWAITING_EMAIL_AUTH",
|
|
21
26
|
AWAITING_OTP_AUTH = "AWAITING_OTP_AUTH",
|
|
27
|
+
AWAITING_MFA_AUTH = "AWAITING_MFA_AUTH",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export enum AlchemyMfaStatus {
|
|
31
|
+
NOT_REQUIRED = "not_required",
|
|
32
|
+
REQUIRED = "required",
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
export interface ErrorInfo {
|
|
25
36
|
name: string;
|
|
26
37
|
message: string;
|
|
27
38
|
}
|
|
39
|
+
|
|
40
|
+
export type ValidateMultiFactorsArgs = {
|
|
41
|
+
multiFactorId?: string;
|
|
42
|
+
multiFactorCode: string;
|
|
43
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MfaFactor } from "../client/types.js";
|
|
2
|
+
|
|
3
|
+
export function parseMfaError(error: unknown): MfaFactor[] | null {
|
|
4
|
+
if (error instanceof Error) {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = JSON.parse(error.message);
|
|
7
|
+
if (parsed?.data?.multiFactors) {
|
|
8
|
+
return parsed.data.multiFactors;
|
|
9
|
+
}
|
|
10
|
+
} catch {
|
|
11
|
+
// ignore JSON parse failures
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
package/src/version.ts
CHANGED