@atlasauth/js 0.41.0 → 0.43.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/account-security.d.ts +156 -0
- package/dist/account-security.js +149 -0
- package/dist/account-security.js.map +1 -1
- package/dist/api-keys.d.ts +14 -1
- package/dist/api-keys.js +5 -0
- package/dist/api-keys.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/machine-enrolment.d.ts +26 -0
- package/dist/machine-enrolment.js +17 -0
- package/dist/machine-enrolment.js.map +1 -0
- package/dist/organizations.d.ts +64 -0
- package/dist/organizations.js +34 -1
- package/dist/organizations.js.map +1 -1
- package/dist/passkey-sign-in.d.ts +5 -0
- package/dist/passkey-sign-in.js +1 -1
- package/dist/passkey-sign-in.js.map +1 -1
- package/dist/security-section.d.ts +110 -0
- package/dist/security-section.js +273 -0
- package/dist/security-section.js.map +1 -0
- package/dist/sign-in-flow.d.ts +24 -2
- package/dist/sign-in-flow.js +37 -14
- package/dist/sign-in-flow.js.map +1 -1
- package/dist/sign-in-screen.d.ts +156 -0
- package/dist/sign-in-screen.js +298 -0
- package/dist/sign-in-screen.js.map +1 -0
- package/dist/step-up-flow.d.ts +59 -0
- package/dist/step-up-flow.js +83 -0
- package/dist/step-up-flow.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSignInScreen = createSignInScreen;
|
|
4
|
+
/**
|
|
5
|
+
* The view-model of a sign-in screen, with no UI and no framework.
|
|
6
|
+
*
|
|
7
|
+
* `createSignInScreen()` drives `createSignInFlow()` and answers the questions a
|
|
8
|
+
* screen asks: which step am I on, which methods can the person use, which
|
|
9
|
+
* fields do I draw, what do I show when it fails. You render `getView()`, call
|
|
10
|
+
* the actions, and re-render on `subscribe`. The server still decides the next
|
|
11
|
+
* step; this only shapes the flow's answers for a form. Errors come back as
|
|
12
|
+
* sentences in the app's language (`localization`), never as codes.
|
|
13
|
+
*
|
|
14
|
+
* The steps after the credentials are driven too: setting up a second factor
|
|
15
|
+
* (authenticator app with its QR code, or texts), saving the recovery codes,
|
|
16
|
+
* accepting policies and the required actions (new password, verify email,
|
|
17
|
+
* profile, a server-driven form, identity verification). `other` is only a step
|
|
18
|
+
* this SDK does not know yet; `flow` is there for it.
|
|
19
|
+
*/
|
|
20
|
+
const errors_1 = require("./errors");
|
|
21
|
+
const sign_in_flow_1 = require("./sign-in-flow");
|
|
22
|
+
const FIRST_FACTOR_METHODS = ['password', 'email_code'];
|
|
23
|
+
const SECOND_FACTOR_METHODS = ['totp', 'backup_code', 'sms', 'email_code', 'passkey'];
|
|
24
|
+
/** Dismissing a system sheet or a passkey prompt is the person's choice, not an error to show. */
|
|
25
|
+
const SILENT = new Set(['passkey_cancelled', 'native_cancelled']);
|
|
26
|
+
const FIELDS = {
|
|
27
|
+
identifier: { name: 'identifier', kind: 'text', autoComplete: 'username', secure: false },
|
|
28
|
+
password: { name: 'password', kind: 'password', autoComplete: 'current-password', secure: true },
|
|
29
|
+
code: { name: 'code', kind: 'code', autoComplete: 'one-time-code', secure: false },
|
|
30
|
+
backup: { name: 'code', kind: 'code', autoComplete: 'off', secure: false },
|
|
31
|
+
};
|
|
32
|
+
const FIELD_CODE = FIELDS.code;
|
|
33
|
+
const FIELD_SECOND_CODE = { name: 'second_code', kind: 'code', autoComplete: 'one-time-code', secure: false };
|
|
34
|
+
const FIELD_PHONE = { name: 'phone', kind: 'phone', autoComplete: 'tel', secure: false };
|
|
35
|
+
const FIELD_NEW_PASSWORD = { name: 'new_password', kind: 'password', autoComplete: 'new-password', secure: true };
|
|
36
|
+
const profileField = (f) => ({
|
|
37
|
+
name: f.key,
|
|
38
|
+
kind: f.type === 'password' ? 'password' : 'text',
|
|
39
|
+
autoComplete: f.type === 'password' ? 'new-password' : 'off',
|
|
40
|
+
secure: f.type === 'password',
|
|
41
|
+
label: f.label,
|
|
42
|
+
required: f.required,
|
|
43
|
+
...(f.options?.length ? { options: f.options } : {}),
|
|
44
|
+
});
|
|
45
|
+
const screenStep = (step) => {
|
|
46
|
+
switch (step.type) {
|
|
47
|
+
case 'needs_identifier': return 'identifier';
|
|
48
|
+
case 'needs_first_factor': return 'first_factor';
|
|
49
|
+
case 'needs_second_factor': return 'second_factor';
|
|
50
|
+
case 'needs_captcha': return 'captcha';
|
|
51
|
+
case 'redirect': return 'redirect';
|
|
52
|
+
case 'complete': return 'complete';
|
|
53
|
+
case 'needs_mfa_enrollment': return 'enroll_second_factor';
|
|
54
|
+
case 'show_recovery_codes': return 'recovery_codes';
|
|
55
|
+
case 'needs_policy_acceptance': return 'policies';
|
|
56
|
+
case 'needs_email_verification': return 'email_verification';
|
|
57
|
+
case 'needs_required_action': return 'required_action';
|
|
58
|
+
default: return 'other';
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function createSignInScreen(opts) {
|
|
62
|
+
const flow = (0, sign_in_flow_1.createSignInFlow)(opts);
|
|
63
|
+
const native = opts.nativeSignIn ?? {};
|
|
64
|
+
const listeners = new Set();
|
|
65
|
+
let selected = null;
|
|
66
|
+
let sentFor = null;
|
|
67
|
+
let lastStep = 'identifier';
|
|
68
|
+
const alternatives = () => {
|
|
69
|
+
const out = [];
|
|
70
|
+
if (native.passkey)
|
|
71
|
+
out.push('passkey');
|
|
72
|
+
if (native.apple)
|
|
73
|
+
out.push('apple');
|
|
74
|
+
if (native.google)
|
|
75
|
+
out.push('google');
|
|
76
|
+
return out;
|
|
77
|
+
};
|
|
78
|
+
const build = (snap) => {
|
|
79
|
+
const step = screenStep(snap.step);
|
|
80
|
+
if (step !== lastStep) {
|
|
81
|
+
lastStep = step;
|
|
82
|
+
selected = null;
|
|
83
|
+
sentFor = null;
|
|
84
|
+
}
|
|
85
|
+
const fs = snap.step;
|
|
86
|
+
const methods = fs.type === 'needs_first_factor'
|
|
87
|
+
? FIRST_FACTOR_METHODS.filter((m) => fs.factors.includes(m))
|
|
88
|
+
: fs.type === 'needs_second_factor'
|
|
89
|
+
? SECOND_FACTOR_METHODS.filter((m) => fs.factors.includes(m))
|
|
90
|
+
: fs.type === 'needs_mfa_enrollment'
|
|
91
|
+
? fs.methods.map((m) => (m === 'phone_code' ? 'sms' : 'totp'))
|
|
92
|
+
: [];
|
|
93
|
+
const method = methods.length ? (selected && methods.includes(selected) ? selected : methods[0]) : null;
|
|
94
|
+
const enrolling = fs.type === 'needs_mfa_enrollment' ? fs.enrollment : null;
|
|
95
|
+
const enrollment = fs.type === 'needs_mfa_enrollment'
|
|
96
|
+
? {
|
|
97
|
+
totp: enrolling?.strategy === 'totp' && enrolling.secret ? { secret: enrolling.secret, uri: enrolling.uri ?? '', qrSvg: enrolling.qrSvg ?? null, qrCode: enrolling.qrCode ?? null } : null,
|
|
98
|
+
totpCodes: fs.totpCodes,
|
|
99
|
+
phone: enrolling?.strategy === 'phone_code' ? (enrolling.phone ?? null) : null,
|
|
100
|
+
}
|
|
101
|
+
: null;
|
|
102
|
+
const action = fs.type === 'needs_required_action' ? fs.action : null;
|
|
103
|
+
const requiredAction = fs.type === 'needs_required_action' && action
|
|
104
|
+
? {
|
|
105
|
+
kind: action.kind,
|
|
106
|
+
title: action.kind === 'journey_form' ? action.title : null,
|
|
107
|
+
intro: action.kind === 'journey_form' ? action.intro : null,
|
|
108
|
+
url: action.kind === 'identity_verification' || action.kind === 'custom' ? action.url : null,
|
|
109
|
+
status: action.kind === 'identity_verification' ? action.status : null,
|
|
110
|
+
remaining: fs.remaining,
|
|
111
|
+
skippable: action.kind === 'complete_profile' && action.fields.every((f) => !f.required),
|
|
112
|
+
}
|
|
113
|
+
: null;
|
|
114
|
+
let fields = [];
|
|
115
|
+
if (step === 'identifier')
|
|
116
|
+
fields = [FIELDS.identifier];
|
|
117
|
+
else if (step === 'first_factor' || step === 'second_factor') {
|
|
118
|
+
fields = method === 'password' ? [FIELDS.password] : method === 'backup_code' ? [FIELDS.backup] : method && method !== 'passkey' ? [FIELDS.code] : [];
|
|
119
|
+
}
|
|
120
|
+
else if (step === 'enroll_second_factor') {
|
|
121
|
+
if (method === 'sms')
|
|
122
|
+
fields = enrollment?.phone ? [FIELD_CODE] : [FIELD_PHONE];
|
|
123
|
+
else if (method === 'totp' && enrollment?.totp)
|
|
124
|
+
fields = enrollment.totpCodes === 2 ? [FIELD_CODE, FIELD_SECOND_CODE] : [FIELD_CODE];
|
|
125
|
+
}
|
|
126
|
+
else if (step === 'email_verification')
|
|
127
|
+
fields = [FIELD_CODE];
|
|
128
|
+
else if (action) {
|
|
129
|
+
switch (action.kind) {
|
|
130
|
+
case 'update_password':
|
|
131
|
+
fields = [FIELD_NEW_PASSWORD];
|
|
132
|
+
break;
|
|
133
|
+
case 'verify_email':
|
|
134
|
+
fields = [FIELD_CODE];
|
|
135
|
+
break;
|
|
136
|
+
case 'update_profile':
|
|
137
|
+
fields = [
|
|
138
|
+
{ name: 'first_name', kind: 'text', autoComplete: 'off', secure: false },
|
|
139
|
+
{ name: 'last_name', kind: 'text', autoComplete: 'off', secure: false },
|
|
140
|
+
{ name: 'username', kind: 'text', autoComplete: 'username', secure: false },
|
|
141
|
+
];
|
|
142
|
+
break;
|
|
143
|
+
case 'complete_profile':
|
|
144
|
+
case 'journey_form':
|
|
145
|
+
fields = action.fields.map(profileField);
|
|
146
|
+
break;
|
|
147
|
+
default: break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const sends = method === 'email_code' || (method === 'sms' && step === 'second_factor');
|
|
151
|
+
const failure = snap.errors[0];
|
|
152
|
+
const silent = failure && SILENT.has((failure.reason ?? failure.code).toLowerCase());
|
|
153
|
+
return {
|
|
154
|
+
step,
|
|
155
|
+
methods,
|
|
156
|
+
method,
|
|
157
|
+
alternatives: step === 'identifier' ? alternatives() : [],
|
|
158
|
+
fields,
|
|
159
|
+
needsSend: (sends && sentFor !== method) || (action?.kind === 'verify_email' && sentFor === null),
|
|
160
|
+
codeSent: (sends && sentFor === method) || (action?.kind === 'verify_email' && sentFor !== null),
|
|
161
|
+
sentTo: snap.sentTo,
|
|
162
|
+
busy: snap.busy,
|
|
163
|
+
error: failure && !silent ? (0, errors_1.localizedErrorMessage)(failure, opts.localization) : snap.reason && !failure ? (0, errors_1.localizedErrorMessage)({ reason: snap.reason }, opts.localization) : null,
|
|
164
|
+
reason: failure ? (silent ? null : (failure.reason ?? snap.reason)) : snap.reason,
|
|
165
|
+
attemptId: snap.attemptId,
|
|
166
|
+
enrollment,
|
|
167
|
+
recoveryCodes: fs.type === 'show_recovery_codes' ? fs.codes : null,
|
|
168
|
+
policies: fs.type === 'needs_policy_acceptance' ? fs.policies : [],
|
|
169
|
+
requiredAction,
|
|
170
|
+
flowStep: snap.step,
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
let view = build(flow.getSnapshot());
|
|
174
|
+
flow.subscribe((snap) => {
|
|
175
|
+
view = build(snap);
|
|
176
|
+
for (const l of listeners)
|
|
177
|
+
l(view);
|
|
178
|
+
maybeAutoStart(view);
|
|
179
|
+
});
|
|
180
|
+
const refresh = () => {
|
|
181
|
+
view = build(flow.getSnapshot());
|
|
182
|
+
for (const l of listeners)
|
|
183
|
+
l(view);
|
|
184
|
+
};
|
|
185
|
+
const done = async (p) => void (await p);
|
|
186
|
+
const sendCode = async () => {
|
|
187
|
+
const { method, step, requiredAction } = view;
|
|
188
|
+
if (requiredAction?.kind === 'verify_email') {
|
|
189
|
+
sentFor = 'email_code';
|
|
190
|
+
return done(flow.sendEmailVerification());
|
|
191
|
+
}
|
|
192
|
+
if (step === 'enroll_second_factor')
|
|
193
|
+
return;
|
|
194
|
+
if (method !== 'email_code' && method !== 'sms')
|
|
195
|
+
return;
|
|
196
|
+
sentFor = method;
|
|
197
|
+
await done(step === 'first_factor' ? flow.sendEmailCode() : flow.sendSecondFactorCode(method));
|
|
198
|
+
};
|
|
199
|
+
// A lone authenticator-app option has nothing to choose: start its setup once per attempt.
|
|
200
|
+
let autoStarted = null;
|
|
201
|
+
const maybeAutoStart = (v) => {
|
|
202
|
+
if (v.step === 'enroll_second_factor' && v.method === 'totp' && !v.enrollment?.totp && !v.busy && autoStarted !== v.attemptId && v.methods.length === 1) {
|
|
203
|
+
autoStarted = v.attemptId;
|
|
204
|
+
void flow.startTotpEnrollment();
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
maybeAutoStart(view);
|
|
208
|
+
return {
|
|
209
|
+
getView: () => view,
|
|
210
|
+
subscribe(listener) {
|
|
211
|
+
listeners.add(listener);
|
|
212
|
+
return () => void listeners.delete(listener);
|
|
213
|
+
},
|
|
214
|
+
flow,
|
|
215
|
+
async selectMethod(method) {
|
|
216
|
+
if (!view.methods.includes(method))
|
|
217
|
+
return;
|
|
218
|
+
selected = method;
|
|
219
|
+
refresh();
|
|
220
|
+
if (view.step === 'enroll_second_factor' && method === 'totp' && !view.enrollment?.totp)
|
|
221
|
+
await done(flow.startTotpEnrollment());
|
|
222
|
+
},
|
|
223
|
+
sendCode,
|
|
224
|
+
resend: sendCode,
|
|
225
|
+
async submit(values = {}) {
|
|
226
|
+
const { step, method } = view;
|
|
227
|
+
const code = (values.code ?? '').trim();
|
|
228
|
+
if (step === 'identifier')
|
|
229
|
+
return done(flow.submitIdentifier((values.identifier ?? '').trim()));
|
|
230
|
+
if (step === 'first_factor') {
|
|
231
|
+
if (method === 'password')
|
|
232
|
+
return done(flow.submitPassword(values.password ?? ''));
|
|
233
|
+
if (method === 'email_code')
|
|
234
|
+
return done(flow.submitEmailCode(code));
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (step === 'enroll_second_factor') {
|
|
238
|
+
if (method === 'sms' && !view.enrollment?.phone)
|
|
239
|
+
return done(flow.sendEnrollmentPhone((values.phone ?? '').trim()));
|
|
240
|
+
if (method === 'totp' || method === 'sms')
|
|
241
|
+
return done(flow.submitEnrollmentCode(code, (values.second_code ?? '').trim()));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (step === 'email_verification')
|
|
245
|
+
return done(flow.submitEmailCode(code));
|
|
246
|
+
if (step === 'required_action') {
|
|
247
|
+
const kind = view.requiredAction?.kind;
|
|
248
|
+
if (kind === 'update_password')
|
|
249
|
+
return done(flow.updatePassword(values.new_password ?? ''));
|
|
250
|
+
if (kind === 'verify_email')
|
|
251
|
+
return done(flow.submitEmailVerificationCode(code));
|
|
252
|
+
if (kind === 'update_profile') {
|
|
253
|
+
return done(flow.updateProfile({
|
|
254
|
+
...(values.first_name !== undefined ? { firstName: values.first_name } : {}),
|
|
255
|
+
...(values.last_name !== undefined ? { lastName: values.last_name } : {}),
|
|
256
|
+
...(values.username !== undefined ? { username: values.username } : {}),
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
if (kind === 'complete_profile' || kind === 'journey_form') {
|
|
260
|
+
const { skip, ...rest } = values;
|
|
261
|
+
return done(flow.submitRequiredFields(rest, skip === 'true' ? { skip: true } : {}));
|
|
262
|
+
}
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (step === 'second_factor') {
|
|
266
|
+
if (method === 'passkey')
|
|
267
|
+
return done(flow.submitPasskeySecondFactor(values.remember_device === 'true' ? { rememberDevice: true } : {}));
|
|
268
|
+
if (method === 'totp' || method === 'backup_code' || method === 'sms' || method === 'email_code') {
|
|
269
|
+
return done(flow.submitSecondFactor(code, method, values.remember_device === 'true' ? { rememberDevice: true } : {}));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
acknowledgeRecoveryCodes: () => done(flow.acknowledgeRecoveryCodes()),
|
|
274
|
+
acceptPolicies(options = {}) {
|
|
275
|
+
const acceptances = view.policies
|
|
276
|
+
.filter((p) => !options.only || options.only.includes(p.policy))
|
|
277
|
+
.map((p) => ({
|
|
278
|
+
policy: p.policy,
|
|
279
|
+
version_id: p.version_id,
|
|
280
|
+
content_sha256: p.content_sha256,
|
|
281
|
+
...(p.display === 'checkbox' || p.display === 'scroll' || p.display === 'link' ? { display: p.display } : {}),
|
|
282
|
+
...(options.scrolledToEnd ? { scrolled_to_end: true } : {}),
|
|
283
|
+
...(options.viewMs !== undefined ? { view_ms: options.viewMs } : {}),
|
|
284
|
+
}));
|
|
285
|
+
return done(flow.acceptPolicies(acceptances));
|
|
286
|
+
},
|
|
287
|
+
startIdentityVerification: (redirectUrl) => done(flow.startIdentityVerification(redirectUrl)),
|
|
288
|
+
checkIdentityVerification: () => done(flow.checkIdentityVerification()),
|
|
289
|
+
signInWithPasskey: () => done(flow.signInWithPasskey()),
|
|
290
|
+
signInWithApple: () => done(flow.signInNative('apple')),
|
|
291
|
+
signInWithGoogle: () => done(flow.signInNative('google')),
|
|
292
|
+
submitCaptcha: (token) => done(flow.submitCaptcha(token)),
|
|
293
|
+
reset() {
|
|
294
|
+
flow.reset();
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=sign-in-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign-in-screen.js","sourceRoot":"","sources":["../src/sign-in-screen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step-up with no DOM: re-authenticate a signed-in session (cookie or bearer)
|
|
3
|
+
* by asking YOUR code for a credential, then retry the call that was refused.
|
|
4
|
+
*
|
|
5
|
+
* `createStepUp({ client, choose })` returns `withStepUp(call)`: it runs `call`,
|
|
6
|
+
* and when the server refuses it with STEP_UP_REQUIRED it asks `choose` for one
|
|
7
|
+
* of the factors the account holds (and the refusal accepts), re-verifies with
|
|
8
|
+
* `POST /v1/client/me/step_up`, and runs `call` once more. A passkey is run by
|
|
9
|
+
* `passkeyAssertion` (React Native: `nativePasskeyAssertion(Passkey)` from
|
|
10
|
+
* `@atlasauth/expo-passkeys`); everything else is a code or password you collect.
|
|
11
|
+
*/
|
|
12
|
+
import type { FieldError } from './attempt';
|
|
13
|
+
import type { FapiClient, FapiResponse } from './fapi';
|
|
14
|
+
import { type PasskeyAssertionProvider } from './passkey-second-factor';
|
|
15
|
+
import { type StepUpResult } from './step-up';
|
|
16
|
+
export type StepUpFactor = 'password' | 'passkey' | 'totp' | 'backup_code' | 'email_code';
|
|
17
|
+
/** What the person picked. A passkey needs no input here: the platform prompt runs next. */
|
|
18
|
+
export type StepUpChoice = {
|
|
19
|
+
strategy: 'password';
|
|
20
|
+
password: string;
|
|
21
|
+
} | {
|
|
22
|
+
strategy: 'totp' | 'backup_code' | 'email_code';
|
|
23
|
+
code: string;
|
|
24
|
+
} | {
|
|
25
|
+
strategy: 'passkey';
|
|
26
|
+
};
|
|
27
|
+
/** What `choose` is asked for. */
|
|
28
|
+
export interface StepUpRequest {
|
|
29
|
+
/** The refused action (`email_change`, …), when the server named it. */
|
|
30
|
+
action: string | null;
|
|
31
|
+
/** The factors to offer: held by the account and accepted for this action. Never empty. */
|
|
32
|
+
factors: StepUpFactor[];
|
|
33
|
+
maxAgeSeconds: number | null;
|
|
34
|
+
/** The previous try failed (wrong code, cancelled passkey): show it and ask again. */
|
|
35
|
+
error: FieldError | null;
|
|
36
|
+
/** Email the step-up code (for the `email_code` factor). */
|
|
37
|
+
sendEmailCode(): Promise<FapiResponse<unknown>>;
|
|
38
|
+
}
|
|
39
|
+
export interface StepUpFlowOptions {
|
|
40
|
+
client: FapiClient;
|
|
41
|
+
/** Ask the person which factor to use and collect it; return null to cancel. */
|
|
42
|
+
choose: (request: StepUpRequest) => Promise<StepUpChoice | null> | StepUpChoice | null;
|
|
43
|
+
/** Runs the passkey prompt where there is no WebAuthn. Without it the browser's WebAuthn is used. */
|
|
44
|
+
passkeyAssertion?: PasskeyAssertionProvider;
|
|
45
|
+
/** Wrong credentials allowed before the last error is thrown. Default 3. */
|
|
46
|
+
maxAttempts?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The step-up factors the signed-in account holds, or null when that cannot be
|
|
50
|
+
* read (the caller then offers everything the refusal accepts).
|
|
51
|
+
* `email_code` is always held: it goes to the primary address.
|
|
52
|
+
*/
|
|
53
|
+
export declare function heldStepUpFactors(client: FapiClient): Promise<StepUpFactor[] | null>;
|
|
54
|
+
export declare function createStepUp(opts: StepUpFlowOptions): {
|
|
55
|
+
/** Run `call`; on STEP_UP_REQUIRED re-authenticate and run it once more. Throws `StepUpCancelledError` when `choose` returns null. */
|
|
56
|
+
withStepUp<T>(call: () => Promise<FapiResponse<T>>): Promise<FapiResponse<T>>;
|
|
57
|
+
/** Re-authenticate now (for example before opening a security page). */
|
|
58
|
+
reauthenticate(action?: string): Promise<StepUpResult>;
|
|
59
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.heldStepUpFactors = heldStepUpFactors;
|
|
4
|
+
exports.createStepUp = createStepUp;
|
|
5
|
+
const passkey_second_factor_1 = require("./passkey-second-factor");
|
|
6
|
+
const step_up_1 = require("./step-up");
|
|
7
|
+
/**
|
|
8
|
+
* The step-up factors the signed-in account holds, or null when that cannot be
|
|
9
|
+
* read (the caller then offers everything the refusal accepts).
|
|
10
|
+
* `email_code` is always held: it goes to the primary address.
|
|
11
|
+
*/
|
|
12
|
+
async function heldStepUpFactors(client) {
|
|
13
|
+
const [me, mfa, passkeys] = await Promise.all([
|
|
14
|
+
client.get('/v1/client/me'),
|
|
15
|
+
client.get('/v1/client/me/mfa'),
|
|
16
|
+
client.get('/v1/client/me/passkeys'),
|
|
17
|
+
]);
|
|
18
|
+
if (!me.ok || !mfa.ok)
|
|
19
|
+
return null;
|
|
20
|
+
const held = [];
|
|
21
|
+
if (me.data?.has_password === true)
|
|
22
|
+
held.push('password');
|
|
23
|
+
if (passkeys.ok && (passkeys.data?.data?.length ?? 0) > 0)
|
|
24
|
+
held.push('passkey');
|
|
25
|
+
if (mfa.data?.data?.some((f) => f.type === 'totp' && f.verified !== false))
|
|
26
|
+
held.push('totp');
|
|
27
|
+
if ((mfa.data?.backup_codes_remaining ?? 0) > 0)
|
|
28
|
+
held.push('backup_code');
|
|
29
|
+
held.push('email_code');
|
|
30
|
+
return held;
|
|
31
|
+
}
|
|
32
|
+
const KNOWN = ['password', 'passkey', 'totp', 'backup_code', 'email_code'];
|
|
33
|
+
function createStepUp(opts) {
|
|
34
|
+
const { client } = opts;
|
|
35
|
+
/** Passkey step-up: the server's challenge, the platform prompt, the assertion body. Returns the input, or the error to show. */
|
|
36
|
+
const passkeyInput = async () => {
|
|
37
|
+
const started = await client.post('/v1/client/me/step_up/passkey', {});
|
|
38
|
+
if (!started.ok || !started.data)
|
|
39
|
+
return started.errors[0] ?? { code: 'UNAUTHENTICATED', message: 'Could not start the passkey check.' };
|
|
40
|
+
try {
|
|
41
|
+
const a = await (0, passkey_second_factor_1.passkeySecondFactorAssertion)(started.data, opts.passkeyAssertion ? { passkeyAssertion: opts.passkeyAssertion } : {});
|
|
42
|
+
return { strategy: 'passkey', challenge: a.challenge, credential_id: a.credential_id, authenticator_data: a.authenticator_data, client_data_json: a.client_data_json, signature: a.signature };
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
return { code: 'passkey_cancelled', reason: 'passkey_cancelled', message: e instanceof Error ? e.message : 'The passkey prompt was cancelled.' };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/** One prompt per refusal: the held factors are read once, then every retry of the prompt reuses them. */
|
|
49
|
+
const makePrompt = () => {
|
|
50
|
+
let held;
|
|
51
|
+
return async (p) => {
|
|
52
|
+
held ??= heldStepUpFactors(client);
|
|
53
|
+
const mine = await held;
|
|
54
|
+
const accepted = p.acceptedFactors.filter((f) => KNOWN.includes(f));
|
|
55
|
+
const narrowed = mine ? accepted.filter((f) => mine.includes(f)) : accepted;
|
|
56
|
+
// Never trap the person with nothing to pick: if the read and the refusal disagree, offer what the refusal accepts.
|
|
57
|
+
const factors = narrowed.length ? narrowed : accepted;
|
|
58
|
+
let error = p.error;
|
|
59
|
+
for (;;) {
|
|
60
|
+
const choice = await opts.choose({ action: p.action, factors, maxAgeSeconds: p.maxAgeSeconds, error, sendEmailCode: p.sendEmailCode });
|
|
61
|
+
if (!choice)
|
|
62
|
+
return null;
|
|
63
|
+
if (choice.strategy !== 'passkey')
|
|
64
|
+
return choice;
|
|
65
|
+
const input = await passkeyInput();
|
|
66
|
+
if ('strategy' in input)
|
|
67
|
+
return input;
|
|
68
|
+
error = input;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
/** Run `call`; on STEP_UP_REQUIRED re-authenticate and run it once more. Throws `StepUpCancelledError` when `choose` returns null. */
|
|
74
|
+
withStepUp(call) {
|
|
75
|
+
return (0, step_up_1.retryWithStepUp)(call, { client, prompt: makePrompt(), ...(opts.maxAttempts ? { maxAttempts: opts.maxAttempts } : {}) });
|
|
76
|
+
},
|
|
77
|
+
/** Re-authenticate now (for example before opening a security page). */
|
|
78
|
+
reauthenticate(action = 'sensitive_action') {
|
|
79
|
+
return (0, step_up_1.requireStepUp)(action, { client, prompt: makePrompt(), ...(opts.maxAttempts ? { maxAttempts: opts.maxAttempts } : {}) });
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=step-up-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-up-flow.js","sourceRoot":"","sources":["../src/step-up-flow.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -7,5 +7,5 @@ exports.ATLAS_JS_VERSION = void 0;
|
|
|
7
7
|
* package.json at runtime) so the bundle stays dependency-free and tests stay
|
|
8
8
|
* deterministic; `version.test.ts` fails when it drifts from package.json.
|
|
9
9
|
*/
|
|
10
|
-
exports.ATLAS_JS_VERSION = '0.
|
|
10
|
+
exports.ATLAS_JS_VERSION = '0.43.0';
|
|
11
11
|
//# sourceMappingURL=version.js.map
|