@structured-id/ui-core 4.12.0 → 4.13.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/package.json +3 -2
- package/src/profile/components/SidLoginForm.vue +3 -2
- package/src/profile/composables/useAuth.test.ts +37 -34
- package/src/profile/composables/useAuth.ts +9 -9
- package/src/profile/composables/useAuthApi.ids.test.ts +248 -0
- package/src/profile/composables/useAuthApi.opaque.test.ts +55 -93
- package/src/profile/composables/useAuthApi.ts +189 -92
- package/src/profile/composables/useLoginSuccess.ts +2 -1
|
@@ -13,13 +13,22 @@
|
|
|
13
13
|
* behind the injected ZkppClientApi: no dependency on the client package.
|
|
14
14
|
*/
|
|
15
15
|
import { getTransport, getAccountTransport } from "../../index";
|
|
16
|
+
import {
|
|
17
|
+
CredentialId,
|
|
18
|
+
MagicLinkId,
|
|
19
|
+
OpaqueLoginId,
|
|
20
|
+
OtpSessionId,
|
|
21
|
+
ResetSessionId,
|
|
22
|
+
SessionId,
|
|
23
|
+
StepUpChallengeId,
|
|
24
|
+
optional,
|
|
25
|
+
required,
|
|
26
|
+
} from "@structured-id/ids";
|
|
16
27
|
import { AuthServiceClient } from "@structured-id/proto/sid/v1/authn/auth.client";
|
|
17
28
|
import {
|
|
18
29
|
StepUpMethod,
|
|
19
30
|
type OpaqueLoginStartResponse,
|
|
20
31
|
type OpaqueLoginFinishResponse,
|
|
21
|
-
type OpaqueRegistrationStartResponse,
|
|
22
|
-
type OpaqueRegistrationFinishResponse,
|
|
23
32
|
type MfaVerifyResponse,
|
|
24
33
|
type TotpEnrollmentChallenge,
|
|
25
34
|
type FinishTotpEnrollmentResponse,
|
|
@@ -87,6 +96,13 @@ function account(): AuthServiceClient {
|
|
|
87
96
|
return new AuthServiceClient(getAccountTransport());
|
|
88
97
|
}
|
|
89
98
|
|
|
99
|
+
/**
|
|
100
|
+
* An answer with its identifier field `K` read into the typed identifier
|
|
101
|
+
* `V`. Reading validates it: a malformed or missing reference the answer
|
|
102
|
+
* owes fails here, not on a page.
|
|
103
|
+
*/
|
|
104
|
+
export type WithId<T, K extends keyof T, V> = Omit<T, K> & { [P in K]: V };
|
|
105
|
+
|
|
90
106
|
// ── MFA TOTP ──
|
|
91
107
|
|
|
92
108
|
export async function startTotpEnrollment(): Promise<TotpEnrollmentChallenge> {
|
|
@@ -97,32 +113,52 @@ export async function startTotpEnrollment(): Promise<TotpEnrollmentChallenge> {
|
|
|
97
113
|
return response;
|
|
98
114
|
}
|
|
99
115
|
|
|
116
|
+
export type TotpEnrollmentResult = WithId<
|
|
117
|
+
FinishTotpEnrollmentResponse,
|
|
118
|
+
"credentialId",
|
|
119
|
+
CredentialId
|
|
120
|
+
>;
|
|
121
|
+
|
|
100
122
|
export async function finishTotpEnrollment(
|
|
101
123
|
code: string,
|
|
102
|
-
): Promise<
|
|
124
|
+
): Promise<TotpEnrollmentResult> {
|
|
103
125
|
const { response } = await account().finishTotpEnrollment(
|
|
104
126
|
{ code },
|
|
105
127
|
{ meta: authMeta() },
|
|
106
128
|
);
|
|
107
|
-
return
|
|
129
|
+
return {
|
|
130
|
+
...response,
|
|
131
|
+
credentialId: required(CredentialId, response.credentialId),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** A second factor's answer: the session once the last required step passed. */
|
|
136
|
+
export type MfaVerifyResult = WithId<
|
|
137
|
+
MfaVerifyResponse,
|
|
138
|
+
"sessionId",
|
|
139
|
+
SessionId | undefined
|
|
140
|
+
>;
|
|
141
|
+
|
|
142
|
+
function mfaVerified(response: MfaVerifyResponse): MfaVerifyResult {
|
|
143
|
+
return { ...response, sessionId: optional(SessionId, response.sessionId) };
|
|
108
144
|
}
|
|
109
145
|
|
|
110
|
-
export async function verifyTotp(code: string): Promise<
|
|
146
|
+
export async function verifyTotp(code: string): Promise<MfaVerifyResult> {
|
|
111
147
|
const { response } = await client().verifyTotp(
|
|
112
148
|
{ code },
|
|
113
149
|
{ meta: authMeta() },
|
|
114
150
|
);
|
|
115
|
-
return response;
|
|
151
|
+
return mfaVerified(response);
|
|
116
152
|
}
|
|
117
153
|
|
|
118
154
|
// ── MFA SMS ──
|
|
119
155
|
|
|
120
|
-
export async function verifySmsMfa(code: string): Promise<
|
|
156
|
+
export async function verifySmsMfa(code: string): Promise<MfaVerifyResult> {
|
|
121
157
|
const { response } = await client().verifySmsMfa(
|
|
122
158
|
{ code },
|
|
123
159
|
{ meta: authMeta() },
|
|
124
160
|
);
|
|
125
|
-
return response;
|
|
161
|
+
return mfaVerified(response);
|
|
126
162
|
}
|
|
127
163
|
|
|
128
164
|
export async function resendSmsMfa(): Promise<ResendSmsMfaResponse> {
|
|
@@ -142,32 +178,40 @@ export async function generateRecoveryCodes(): Promise<GenerateRecoveryCodesResp
|
|
|
142
178
|
|
|
143
179
|
export async function verifyRecoveryCode(
|
|
144
180
|
code: string,
|
|
145
|
-
): Promise<
|
|
181
|
+
): Promise<MfaVerifyResult> {
|
|
146
182
|
const { response } = await client().verifyRecoveryCode(
|
|
147
183
|
{ code },
|
|
148
184
|
{ meta: authMeta() },
|
|
149
185
|
);
|
|
150
|
-
return response;
|
|
186
|
+
return mfaVerified(response);
|
|
151
187
|
}
|
|
152
188
|
|
|
153
189
|
// ── OTP ──
|
|
154
190
|
|
|
191
|
+
/** A verified code's answer: the provisional session, set only when verified. */
|
|
192
|
+
export type VerifyOtpResult = WithId<
|
|
193
|
+
VerifyOtpResponse,
|
|
194
|
+
"sessionId",
|
|
195
|
+
SessionId | undefined
|
|
196
|
+
>;
|
|
197
|
+
|
|
198
|
+
/** Verify `code` of the request `otpSessionId` (RequestOtpResponse). */
|
|
155
199
|
export async function verifyOtp(
|
|
156
200
|
code: string,
|
|
157
|
-
|
|
158
|
-
): Promise<
|
|
201
|
+
otpSessionId: OtpSessionId,
|
|
202
|
+
): Promise<VerifyOtpResult> {
|
|
159
203
|
const { response } = await client().verifyOtp(
|
|
160
|
-
{ code,
|
|
204
|
+
{ code, otpSessionId: otpSessionId.toWire() },
|
|
161
205
|
{ meta: authMeta() },
|
|
162
206
|
);
|
|
163
|
-
return response;
|
|
207
|
+
return { ...response, sessionId: optional(SessionId, response.sessionId) };
|
|
164
208
|
}
|
|
165
209
|
|
|
166
210
|
export async function resendOtp(
|
|
167
|
-
|
|
211
|
+
otpSessionId: OtpSessionId,
|
|
168
212
|
): Promise<ResendOtpResponse> {
|
|
169
213
|
const { response } = await client().resendOtp(
|
|
170
|
-
{
|
|
214
|
+
{ otpSessionId: otpSessionId.toWire() },
|
|
171
215
|
{ meta: authMeta() },
|
|
172
216
|
);
|
|
173
217
|
return response;
|
|
@@ -216,16 +260,25 @@ export async function webAuthnAuthenticationStart(
|
|
|
216
260
|
return response;
|
|
217
261
|
}
|
|
218
262
|
|
|
263
|
+
export type PasskeySignInResult = WithId<
|
|
264
|
+
WebAuthnAuthenticationFinishResponse,
|
|
265
|
+
"sessionId",
|
|
266
|
+
SessionId
|
|
267
|
+
>;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Finish a passkey sign-in with the assertion; the server finds the ceremony
|
|
271
|
+
* by the challenge the assertion signs.
|
|
272
|
+
*/
|
|
219
273
|
export async function webAuthnAuthenticationFinish(
|
|
220
274
|
credential: Uint8Array,
|
|
221
275
|
principal?: string,
|
|
222
|
-
|
|
223
|
-
): Promise<WebAuthnAuthenticationFinishResponse> {
|
|
276
|
+
): Promise<PasskeySignInResult> {
|
|
224
277
|
const { response } = await client().webAuthnAuthenticationFinish(
|
|
225
|
-
{ credential, principal: principal ?? ""
|
|
278
|
+
{ credential, principal: principal ?? "" },
|
|
226
279
|
{ meta: authMeta() },
|
|
227
280
|
);
|
|
228
|
-
return response;
|
|
281
|
+
return { ...response, sessionId: required(SessionId, response.sessionId) };
|
|
229
282
|
}
|
|
230
283
|
|
|
231
284
|
export async function webAuthnRegistrationStart(
|
|
@@ -238,15 +291,24 @@ export async function webAuthnRegistrationStart(
|
|
|
238
291
|
return response;
|
|
239
292
|
}
|
|
240
293
|
|
|
294
|
+
export type PasskeyRegistrationResult = WithId<
|
|
295
|
+
WebAuthnRegistrationFinishResponse,
|
|
296
|
+
"credentialId",
|
|
297
|
+
CredentialId
|
|
298
|
+
>;
|
|
299
|
+
|
|
241
300
|
export async function webAuthnRegistrationFinish(
|
|
242
301
|
credential: Uint8Array,
|
|
243
302
|
label?: string,
|
|
244
|
-
): Promise<
|
|
303
|
+
): Promise<PasskeyRegistrationResult> {
|
|
245
304
|
const { response } = await account().webAuthnRegistrationFinish(
|
|
246
305
|
{ credential, label },
|
|
247
306
|
{ meta: authMeta() },
|
|
248
307
|
);
|
|
249
|
-
return
|
|
308
|
+
return {
|
|
309
|
+
...response,
|
|
310
|
+
credentialId: required(CredentialId, response.credentialId),
|
|
311
|
+
};
|
|
250
312
|
}
|
|
251
313
|
|
|
252
314
|
// ── Device Authorization (RFC 8628) ──
|
|
@@ -306,27 +368,46 @@ export async function oauth2Authorize(params: {
|
|
|
306
368
|
|
|
307
369
|
// ── Magic Link ──
|
|
308
370
|
|
|
371
|
+
export type MagicLinkRequest = WithId<
|
|
372
|
+
RequestMagicLinkResponse,
|
|
373
|
+
"magicLinkId",
|
|
374
|
+
MagicLinkId
|
|
375
|
+
>;
|
|
376
|
+
|
|
309
377
|
export async function requestMagicLink(
|
|
310
378
|
principal: string,
|
|
311
379
|
clientId: string,
|
|
312
380
|
redirectUri: string,
|
|
313
|
-
): Promise<
|
|
381
|
+
): Promise<MagicLinkRequest> {
|
|
314
382
|
const { response } = await client().requestMagicLink(
|
|
315
383
|
{ principal, clientId, redirectUri },
|
|
316
384
|
{ meta: authMeta() },
|
|
317
385
|
);
|
|
318
|
-
return
|
|
386
|
+
return {
|
|
387
|
+
...response,
|
|
388
|
+
magicLinkId: required(MagicLinkId, response.magicLinkId),
|
|
389
|
+
};
|
|
319
390
|
}
|
|
320
391
|
|
|
392
|
+
export type MagicLinkSignInResult = WithId<
|
|
393
|
+
VerifyMagicLinkResponse,
|
|
394
|
+
"sessionId",
|
|
395
|
+
SessionId
|
|
396
|
+
>;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Verify the magic link `magicLinkId` with its `token`; the page reads both
|
|
400
|
+
* from the link (`MagicLinkId.parse` of its text form).
|
|
401
|
+
*/
|
|
321
402
|
export async function verifyMagicLink(
|
|
322
|
-
|
|
403
|
+
magicLinkId: MagicLinkId,
|
|
323
404
|
token: string,
|
|
324
|
-
): Promise<
|
|
405
|
+
): Promise<MagicLinkSignInResult> {
|
|
325
406
|
const { response } = await client().verifyMagicLink(
|
|
326
|
-
{
|
|
407
|
+
{ magicLinkId: magicLinkId.toWire(), token },
|
|
327
408
|
{ meta: authMeta() },
|
|
328
409
|
);
|
|
329
|
-
return response;
|
|
410
|
+
return { ...response, sessionId: required(SessionId, response.sessionId) };
|
|
330
411
|
}
|
|
331
412
|
|
|
332
413
|
// ── IdP Link ──
|
|
@@ -446,21 +527,34 @@ export async function submitDynamicPrompt(
|
|
|
446
527
|
|
|
447
528
|
// ── Step-Up Auth ──
|
|
448
529
|
|
|
530
|
+
/** A step-up challenge; `challengeId` is absent for a 1-phase method. */
|
|
531
|
+
export type StepUpChallengeResult = WithId<
|
|
532
|
+
StepUpChallenge,
|
|
533
|
+
"challengeId",
|
|
534
|
+
StepUpChallengeId | undefined
|
|
535
|
+
>;
|
|
536
|
+
|
|
537
|
+
/** Request a step-up challenge for the session the bearer token holds. */
|
|
449
538
|
export async function requestStepUp(
|
|
450
|
-
sessionId: string,
|
|
451
539
|
method: StepUpMethod,
|
|
452
|
-
): Promise<
|
|
540
|
+
): Promise<StepUpChallengeResult> {
|
|
453
541
|
const { response } = await client().requestStepUp(
|
|
454
|
-
{
|
|
542
|
+
{ method },
|
|
455
543
|
{ meta: authMeta() },
|
|
456
544
|
);
|
|
457
|
-
return
|
|
545
|
+
return {
|
|
546
|
+
...response,
|
|
547
|
+
challengeId: optional(StepUpChallengeId, response.challengeId),
|
|
548
|
+
};
|
|
458
549
|
}
|
|
459
550
|
|
|
551
|
+
/**
|
|
552
|
+
* Elevate the bearer token's session with `proof`; `challengeId` is the
|
|
553
|
+
* challenge's (absent for a 1-phase method).
|
|
554
|
+
*/
|
|
460
555
|
export async function completeStepUp(
|
|
461
|
-
sessionId: string,
|
|
462
556
|
method: StepUpMethod,
|
|
463
|
-
challengeId:
|
|
557
|
+
challengeId: StepUpChallengeId | undefined,
|
|
464
558
|
proof: {
|
|
465
559
|
totpCode?: string;
|
|
466
560
|
webauthnAssertion?: Uint8Array;
|
|
@@ -469,9 +563,8 @@ export async function completeStepUp(
|
|
|
469
563
|
): Promise<CompleteStepUpResponse> {
|
|
470
564
|
const { response } = await client().completeStepUp(
|
|
471
565
|
{
|
|
472
|
-
sessionId,
|
|
473
566
|
method,
|
|
474
|
-
challengeId,
|
|
567
|
+
challengeId: challengeId?.toWire(),
|
|
475
568
|
proof: proof.totpCode
|
|
476
569
|
? { oneofKind: "totpCode", totpCode: proof.totpCode }
|
|
477
570
|
: proof.webauthnAssertion
|
|
@@ -491,10 +584,10 @@ export async function completeStepUp(
|
|
|
491
584
|
// ── MFA Credential Management ──
|
|
492
585
|
|
|
493
586
|
export async function deleteMfaCredential(
|
|
494
|
-
credentialId:
|
|
587
|
+
credentialId: CredentialId,
|
|
495
588
|
): Promise<DeleteMfaCredentialResponse> {
|
|
496
589
|
const { response } = await account().deleteMfaCredential(
|
|
497
|
-
{ credentialId },
|
|
590
|
+
{ credentialId: credentialId.toWire() },
|
|
498
591
|
{ meta: authMeta() },
|
|
499
592
|
);
|
|
500
593
|
return response;
|
|
@@ -529,12 +622,17 @@ export async function requestPasswordReset(
|
|
|
529
622
|
return response;
|
|
530
623
|
}
|
|
531
624
|
|
|
625
|
+
/**
|
|
626
|
+
* Verify the reset `resetSessionId` with its `token`; the page reads both
|
|
627
|
+
* from the emailed link (`ResetSessionId.parse` of its text form). Later
|
|
628
|
+
* steps name the reset by the operation in the answer's `history`.
|
|
629
|
+
*/
|
|
532
630
|
export async function verifyPasswordReset(
|
|
533
|
-
|
|
631
|
+
resetSessionId: ResetSessionId,
|
|
534
632
|
token: string,
|
|
535
633
|
): Promise<VerifyPasswordResetResponse> {
|
|
536
634
|
const { response } = await client().verifyPasswordReset({
|
|
537
|
-
|
|
635
|
+
resetSessionId: resetSessionId.toWire(),
|
|
538
636
|
token,
|
|
539
637
|
});
|
|
540
638
|
return response;
|
|
@@ -555,24 +653,29 @@ export async function executePasswordReset(
|
|
|
555
653
|
return response;
|
|
556
654
|
}
|
|
557
655
|
|
|
656
|
+
/** A completed reset: the session it signed in, absent when it signed in none. */
|
|
657
|
+
export type PasswordResetResult = WithId<
|
|
658
|
+
CompletePasswordResetResponse,
|
|
659
|
+
"sessionId",
|
|
660
|
+
SessionId | undefined
|
|
661
|
+
>;
|
|
662
|
+
|
|
558
663
|
/**
|
|
559
664
|
* Complete the reset with the replacement password's record and, when the
|
|
560
665
|
* client proved it, the proof; without a proof the password installs
|
|
561
|
-
* policy-unverified.
|
|
666
|
+
* policy-unverified. The operation carries the verified reset's authority.
|
|
562
667
|
*/
|
|
563
668
|
export async function completePasswordReset(
|
|
564
|
-
resetSessionId: string,
|
|
565
669
|
operationId: Uint8Array,
|
|
566
670
|
registrationRecord: Uint8Array,
|
|
567
671
|
proof?: PasswordRegistrationProof,
|
|
568
|
-
): Promise<
|
|
672
|
+
): Promise<PasswordResetResult> {
|
|
569
673
|
const { response } = await client().completePasswordReset({
|
|
570
|
-
resetSessionId,
|
|
571
674
|
operationId: operation(operationId),
|
|
572
675
|
registrationRecord,
|
|
573
676
|
proof,
|
|
574
677
|
});
|
|
575
|
-
return response;
|
|
678
|
+
return { ...response, sessionId: optional(SessionId, response.sessionId) };
|
|
576
679
|
}
|
|
577
680
|
|
|
578
681
|
/** The password policy the server's proof checks a new password against. */
|
|
@@ -609,18 +712,27 @@ export async function opaqueZkppRegistrationStart(
|
|
|
609
712
|
return response;
|
|
610
713
|
}
|
|
611
714
|
|
|
715
|
+
export type RegistrationFinishResult = WithId<
|
|
716
|
+
OpaqueZkppRegistrationFinishResponse,
|
|
717
|
+
"credentialId",
|
|
718
|
+
CredentialId
|
|
719
|
+
>;
|
|
720
|
+
|
|
612
721
|
/** Finish a registration with the record and, when the client proved, the proof. */
|
|
613
722
|
export async function opaqueZkppRegistrationFinish(
|
|
614
723
|
operationId: Uint8Array,
|
|
615
724
|
registrationRecord: Uint8Array,
|
|
616
725
|
proof?: PasswordRegistrationProof,
|
|
617
|
-
): Promise<
|
|
726
|
+
): Promise<RegistrationFinishResult> {
|
|
618
727
|
const { response } = await client().opaqueZkppRegistrationFinish({
|
|
619
728
|
operationId: operation(operationId),
|
|
620
729
|
registrationRecord,
|
|
621
730
|
proof,
|
|
622
731
|
});
|
|
623
|
-
return
|
|
732
|
+
return {
|
|
733
|
+
...response,
|
|
734
|
+
credentialId: required(CredentialId, response.credentialId),
|
|
735
|
+
};
|
|
624
736
|
}
|
|
625
737
|
|
|
626
738
|
/**
|
|
@@ -645,12 +757,16 @@ export async function evaluatePasswordHistory(
|
|
|
645
757
|
* the current password, empty when the change does not prove it.
|
|
646
758
|
*/
|
|
647
759
|
export async function passwordChangeChallenge(
|
|
648
|
-
credentialId:
|
|
760
|
+
credentialId: CredentialId,
|
|
649
761
|
registrationRequest: Uint8Array,
|
|
650
762
|
credentialRequest: Uint8Array = new Uint8Array(),
|
|
651
763
|
): Promise<PasswordChangeChallengeResponse> {
|
|
652
764
|
const { response } = await account().passwordChangeChallenge(
|
|
653
|
-
{
|
|
765
|
+
{
|
|
766
|
+
credentialId: credentialId.toWire(),
|
|
767
|
+
credentialRequest,
|
|
768
|
+
registrationRequest,
|
|
769
|
+
},
|
|
654
770
|
{ meta: authMeta() },
|
|
655
771
|
);
|
|
656
772
|
return response;
|
|
@@ -663,13 +779,13 @@ export async function passwordChangeChallenge(
|
|
|
663
779
|
*/
|
|
664
780
|
export async function passwordChangeExecute(
|
|
665
781
|
operationId: Uint8Array,
|
|
666
|
-
credentialId:
|
|
782
|
+
credentialId: CredentialId,
|
|
667
783
|
credentialFinalization: Uint8Array = new Uint8Array(),
|
|
668
784
|
): Promise<PasswordChangeExecuteResponse> {
|
|
669
785
|
const { response } = await account().passwordChangeExecute(
|
|
670
786
|
{
|
|
671
787
|
operationId: operation(operationId),
|
|
672
|
-
credentialId,
|
|
788
|
+
credentialId: credentialId.toWire(),
|
|
673
789
|
credentialFinalization,
|
|
674
790
|
},
|
|
675
791
|
{ meta: authMeta() },
|
|
@@ -693,14 +809,14 @@ export async function passwordChangeRequirementMs(): Promise<number> {
|
|
|
693
809
|
/** Finish the change with the new password's record and, when proved, the proof. */
|
|
694
810
|
export async function passwordChangeFinish(
|
|
695
811
|
operationId: Uint8Array,
|
|
696
|
-
credentialId:
|
|
812
|
+
credentialId: CredentialId,
|
|
697
813
|
registrationRecord: Uint8Array,
|
|
698
814
|
proof?: PasswordRegistrationProof,
|
|
699
815
|
): Promise<void> {
|
|
700
816
|
await account().passwordChangeFinish(
|
|
701
817
|
{
|
|
702
818
|
operationId: operation(operationId),
|
|
703
|
-
credentialId,
|
|
819
|
+
credentialId: credentialId.toWire(),
|
|
704
820
|
registrationRecord,
|
|
705
821
|
proof,
|
|
706
822
|
},
|
|
@@ -710,59 +826,42 @@ export async function passwordChangeFinish(
|
|
|
710
826
|
|
|
711
827
|
// ── OPAQUE ──
|
|
712
828
|
|
|
829
|
+
/** The login the start began, for its finish to name. */
|
|
830
|
+
export type LoginStartResult = WithId<
|
|
831
|
+
OpaqueLoginStartResponse,
|
|
832
|
+
"loginId",
|
|
833
|
+
OpaqueLoginId
|
|
834
|
+
>;
|
|
835
|
+
|
|
713
836
|
export async function opaqueLoginStart(
|
|
714
837
|
principal: string,
|
|
715
838
|
credentialRequest: Uint8Array,
|
|
716
|
-
): Promise<
|
|
839
|
+
): Promise<LoginStartResult> {
|
|
717
840
|
const { response } = await client().opaqueLoginStart({
|
|
718
841
|
principal,
|
|
719
842
|
credentialRequest,
|
|
720
843
|
});
|
|
721
|
-
return response;
|
|
844
|
+
return { ...response, loginId: required(OpaqueLoginId, response.loginId) };
|
|
722
845
|
}
|
|
723
846
|
|
|
847
|
+
export type LoginFinishResult = WithId<
|
|
848
|
+
OpaqueLoginFinishResponse,
|
|
849
|
+
"sessionId",
|
|
850
|
+
SessionId
|
|
851
|
+
>;
|
|
852
|
+
|
|
853
|
+
/** Finish the login `loginId` (from its start) with the client's KE3. */
|
|
724
854
|
export async function opaqueLoginFinish(
|
|
725
855
|
principal: string,
|
|
726
856
|
credentialFinalization: Uint8Array,
|
|
727
|
-
|
|
728
|
-
): Promise<
|
|
857
|
+
loginId: OpaqueLoginId,
|
|
858
|
+
): Promise<LoginFinishResult> {
|
|
729
859
|
const { response } = await client().opaqueLoginFinish({
|
|
730
860
|
principal,
|
|
731
861
|
credentialFinalization,
|
|
732
|
-
|
|
862
|
+
loginId: loginId.toWire(),
|
|
733
863
|
});
|
|
734
|
-
return response;
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
/**
|
|
738
|
-
* `claimToken`: the instance claim token (`sidclaim_...`) from the service log.
|
|
739
|
-
* Required while the installation has no administrator; the new profile then
|
|
740
|
-
* becomes its first administrator.
|
|
741
|
-
*/
|
|
742
|
-
export async function opaqueRegistrationStart(
|
|
743
|
-
principal: string,
|
|
744
|
-
registrationRequest: Uint8Array,
|
|
745
|
-
claimToken?: string,
|
|
746
|
-
): Promise<OpaqueRegistrationStartResponse> {
|
|
747
|
-
const { response } = await client().opaqueRegistrationStart({
|
|
748
|
-
principal,
|
|
749
|
-
registrationRequest,
|
|
750
|
-
claimToken,
|
|
751
|
-
});
|
|
752
|
-
return response;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
export async function opaqueRegistrationFinish(
|
|
756
|
-
principal: string,
|
|
757
|
-
registrationRecord: Uint8Array,
|
|
758
|
-
serverSetup: string,
|
|
759
|
-
): Promise<OpaqueRegistrationFinishResponse> {
|
|
760
|
-
const { response } = await client().opaqueRegistrationFinish({
|
|
761
|
-
principal,
|
|
762
|
-
registrationRecord,
|
|
763
|
-
serverSetup,
|
|
764
|
-
});
|
|
765
|
-
return response;
|
|
864
|
+
return { ...response, sessionId: required(SessionId, response.sessionId) };
|
|
766
865
|
}
|
|
767
866
|
|
|
768
867
|
// Re-export types for convenience
|
|
@@ -770,8 +869,6 @@ export { StepUpMethod };
|
|
|
770
869
|
export type {
|
|
771
870
|
OpaqueLoginStartResponse,
|
|
772
871
|
OpaqueLoginFinishResponse,
|
|
773
|
-
OpaqueRegistrationStartResponse,
|
|
774
|
-
OpaqueRegistrationFinishResponse,
|
|
775
872
|
UserOrganization,
|
|
776
873
|
MfaVerifyResponse,
|
|
777
874
|
TotpEnrollmentChallenge,
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
* Otherwise the app's own session comes from its BFF: the handler reads it
|
|
11
11
|
* from the BFF's /auth/userinfo and navigates within the app.
|
|
12
12
|
*/
|
|
13
|
+
import type { SessionId } from "@structured-id/ids";
|
|
13
14
|
import { useRouter } from "vue-router";
|
|
14
15
|
import { useAuthStore } from "../../index";
|
|
15
16
|
import { checkBffSession } from "../../index";
|
|
16
17
|
|
|
17
18
|
export interface LoginSuccessResult {
|
|
18
|
-
sessionId?:
|
|
19
|
+
sessionId?: SessionId;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
/** Options of {@link useLoginSuccess}. */
|