@atlasauth/svelte 0.12.0 → 0.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/CHANGELOG.md +4 -0
- package/dist/accessors.d.ts +15 -1
- package/dist/accessors.js +21 -1
- package/dist/components/AttemptFlow.svelte +2 -1
- package/dist/components/SignIn.svelte +47 -3
- package/dist/i18n.js +3 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @atlasauth/svelte changelog
|
|
2
2
|
|
|
3
|
+
## 0.13.0 — 2026-10-30
|
|
4
|
+
|
|
5
|
+
- `<SignIn>` offers "Sign in with a passkey" and passkey autofill on the identifier field when the instance enables passkeys.
|
|
6
|
+
|
|
3
7
|
## 0.12.0 — 2026-10-28
|
|
4
8
|
|
|
5
9
|
- `ManageCiba` component lists sign-in approvals (approve or deny) and manages the CIBA PIN; mounted in the user profile.
|
package/dist/accessors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Readable } from 'svelte/store';
|
|
2
|
-
import { type OrganizationAuditLogOptions, type OrganizationAuditLogState, type CaptchaController, type FlowState, type InstanceSettings, type ProviderToken, type SignOutOptions, type SignOutResult, PolicyAcceptanceController, type MfaChoices, type MfaEnrollmentController, type MfaEnrollmentState } from '@atlasauth/js';
|
|
2
|
+
import { type OrganizationAuditLogOptions, type OrganizationAuditLogState, type CaptchaController, type FlowState, type InstanceSettings, type ProviderToken, type SignOutOptions, type SignOutResult, PolicyAcceptanceController, type MfaChoices, type MfaEnrollmentController, type MfaEnrollmentState, type PasskeySignInController } from '@atlasauth/js';
|
|
3
3
|
import { type AuthStatus } from './context';
|
|
4
4
|
import { type ProtectCondition } from './protect';
|
|
5
5
|
import type { AtlasOrganizationMembership, AtlasSession, AtlasUser } from './types';
|
|
@@ -174,6 +174,20 @@ export interface FlowController {
|
|
|
174
174
|
loadPolicies(): Promise<void>;
|
|
175
175
|
/** The user declined a policy a sign-in was waiting on: cancels the attempt and says why. */
|
|
176
176
|
declinePolicy(title: string): void;
|
|
177
|
+
/**
|
|
178
|
+
* "Continue with Atlas" (when `settings.signInWithAtlas` is set): starts the
|
|
179
|
+
* SSO sign-in and sends the browser to Atlas. Resolves the server's message
|
|
180
|
+
* when it could not start.
|
|
181
|
+
*/
|
|
182
|
+
signInWithAtlas(connectionId: string): Promise<{
|
|
183
|
+
error?: string;
|
|
184
|
+
}>;
|
|
185
|
+
/**
|
|
186
|
+
* Passkey sign-in (the "Sign in with a passkey" button and passkey autofill on
|
|
187
|
+
* the identifier field), offered when `settings.passkeySignIn` is on. The
|
|
188
|
+
* outcome goes through the same completion as every sign-in.
|
|
189
|
+
*/
|
|
190
|
+
passkey: PasskeySignInController;
|
|
177
191
|
/** Stop the magic-link poll loop and remove the captcha widgets — call from `onDestroy`. */
|
|
178
192
|
destroy(): void;
|
|
179
193
|
}
|
package/dist/accessors.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { derived, get, readable, writable } from 'svelte/store';
|
|
2
|
-
import { FapiClient, advanceWithCaptcha, atlasCaptchaLabels, createCaptchaController, createPasskeySignUp, createSignUp, finishPasskeySignUp, fetchInstanceSettings, fetchLastSignInMethod, flowNeedsCaptcha, signInCaptchaOptions, flowFromPending, pollAttempt, prepareFactor, shouldKeepPolling, createOrganizationAuditLog, createMfaEnrollment, acknowledgeRecoveryCodes, pendingRecoveryCodes, mfaChoicesFrom, prepareSecondFactorCode, resendSignUpVerification, PolicyAcceptanceController, loadPolicies as loadPolicyList, initialFlow as emptyFlow, } from '@atlasauth/js';
|
|
2
|
+
import { FapiClient, advanceWithCaptcha, atlasCaptchaLabels, createCaptchaController, createPasskeySignInController, createPasskeySignUp, createSignUp, finishPasskeySignUp, fetchInstanceSettings, fetchLastSignInMethod, startSignInWithAtlas, flowNeedsCaptcha, signInCaptchaOptions, flowFromPending, pollAttempt, prepareFactor, shouldKeepPolling, createOrganizationAuditLog, createMfaEnrollment, acknowledgeRecoveryCodes, pendingRecoveryCodes, mfaChoicesFrom, prepareSecondFactorCode, resendSignUpVerification, PolicyAcceptanceController, loadPolicies as loadPolicyList, initialFlow as emptyFlow, } from '@atlasauth/js';
|
|
3
3
|
import { useAtlas } from './context';
|
|
4
4
|
import { translate } from './i18n';
|
|
5
5
|
import { evaluate } from './protect';
|
|
@@ -261,7 +261,15 @@ function createFlow() {
|
|
|
261
261
|
maybeStartPolling();
|
|
262
262
|
return next.errors.length === 0;
|
|
263
263
|
}
|
|
264
|
+
const passkey = createPasskeySignInController({
|
|
265
|
+
client,
|
|
266
|
+
onStart: () => state.set({ ...get(state), busy: true, errors: [] }),
|
|
267
|
+
onResult: finish,
|
|
268
|
+
captcha: () => captcha,
|
|
269
|
+
cancelledMessage: () => t('signIn.passkeyCancelled'),
|
|
270
|
+
});
|
|
264
271
|
function destroy() {
|
|
272
|
+
passkey.stopAutofill();
|
|
265
273
|
stopPolling();
|
|
266
274
|
unsubscribeCaptcha();
|
|
267
275
|
unsubscribeEnrollment();
|
|
@@ -269,6 +277,16 @@ function createFlow() {
|
|
|
269
277
|
captcha.destroy();
|
|
270
278
|
signUpCaptcha.destroy();
|
|
271
279
|
}
|
|
280
|
+
async function signInWithAtlas(connectionId) {
|
|
281
|
+
if (typeof window === 'undefined')
|
|
282
|
+
return {};
|
|
283
|
+
const started = await startSignInWithAtlas(client, connectionId, window.location.href);
|
|
284
|
+
if ('url' in started) {
|
|
285
|
+
window.location.assign(started.url);
|
|
286
|
+
return {};
|
|
287
|
+
}
|
|
288
|
+
return { error: started.error };
|
|
289
|
+
}
|
|
272
290
|
return {
|
|
273
291
|
state: { subscribe: state.subscribe },
|
|
274
292
|
submit,
|
|
@@ -290,6 +308,8 @@ function createFlow() {
|
|
|
290
308
|
policies,
|
|
291
309
|
loadPolicies,
|
|
292
310
|
declinePolicy,
|
|
311
|
+
signInWithAtlas,
|
|
312
|
+
passkey,
|
|
293
313
|
destroy,
|
|
294
314
|
};
|
|
295
315
|
}
|
|
@@ -85,7 +85,7 @@ function usePassword() {
|
|
|
85
85
|
$: fields = (() => {
|
|
86
86
|
switch (step.kind) {
|
|
87
87
|
case "collect_identifier":
|
|
88
|
-
return [{ name: "identifier", labelKey: "signIn.identifierLabel", type: "email" }];
|
|
88
|
+
return [{ name: "identifier", labelKey: "signIn.identifierLabel", type: "email", autocomplete: "username webauthn" }];
|
|
89
89
|
case "collect_first_factor":
|
|
90
90
|
if (sent === "email_code") {
|
|
91
91
|
return [{ name: "code", labelKey: "signIn.emailCodeLabel", type: "text" }];
|
|
@@ -288,6 +288,7 @@ function handleSubmit(event) {
|
|
|
288
288
|
class={cls('formFieldInput', 'atlas-input')}
|
|
289
289
|
type={f.type}
|
|
290
290
|
name={f.name}
|
|
291
|
+
autocomplete={f.autocomplete}
|
|
291
292
|
value={values[f.name] ?? ''}
|
|
292
293
|
on:input={(e) => (values[f.name] = e.currentTarget.value)}
|
|
293
294
|
/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<script>import { onDestroy } from "svelte";
|
|
2
|
-
import { lastUsedMethodLabel, pendingRecoveryCodes, signUp as hostedSignUp } from "@atlasauth/js";
|
|
1
|
+
<script>import { onDestroy, onMount } from "svelte";
|
|
2
|
+
import { lastUsedMethodLabel, passkeysSupported, pendingRecoveryCodes, signUp as hostedSignUp } from "@atlasauth/js";
|
|
3
3
|
import { signIn } from "../accessors";
|
|
4
4
|
import { useAtlas } from "../context";
|
|
5
5
|
import { classFor } from "../appearance";
|
|
@@ -34,6 +34,24 @@ $: recoveryCodes = pendingRecoveryCodes($flowState);
|
|
|
34
34
|
$: lastLabel = !$flowState.attempt ? lastUsedMethodLabel($lastMethod, t) : null;
|
|
35
35
|
const drawn = (..._deps) => flow.captcha.needed ? flow.captcha : null;
|
|
36
36
|
$: captcha = drawn($settings, $flowState);
|
|
37
|
+
$: atlasConnection = !$flowState.attempt ? $settings?.signInWithAtlas?.connectionId ?? null : null;
|
|
38
|
+
let atlasError = null;
|
|
39
|
+
async function continueWithAtlas() {
|
|
40
|
+
if (!atlasConnection) return;
|
|
41
|
+
atlasError = null;
|
|
42
|
+
atlasError = (await flow.signInWithAtlas(atlasConnection)).error ?? null;
|
|
43
|
+
}
|
|
44
|
+
let supported = false;
|
|
45
|
+
onMount(() => {
|
|
46
|
+
supported = passkeysSupported();
|
|
47
|
+
});
|
|
48
|
+
$: passkeyOffered = supported && !$flowState.attempt && $settings?.passkeySignIn === true;
|
|
49
|
+
$: if (passkeyOffered) flow.passkey.armAutofill();
|
|
50
|
+
else flow.passkey.stopAutofill();
|
|
51
|
+
function submitIdentifier(values) {
|
|
52
|
+
flow.passkey.stopAutofill();
|
|
53
|
+
flow.submit(values);
|
|
54
|
+
}
|
|
37
55
|
</script>
|
|
38
56
|
|
|
39
57
|
{#if lastLabel}
|
|
@@ -42,6 +60,20 @@ $: captcha = drawn($settings, $flowState);
|
|
|
42
60
|
</p>
|
|
43
61
|
{/if}
|
|
44
62
|
|
|
63
|
+
{#if atlasConnection && !recoveryCodes}
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
class={classFor('socialButton', atlas.appearance, 'atlas-social-button')}
|
|
67
|
+
data-atlas-provider="atlas"
|
|
68
|
+
on:click={continueWithAtlas}
|
|
69
|
+
>
|
|
70
|
+
{t('signIn.continueWithAtlas')}
|
|
71
|
+
</button>
|
|
72
|
+
{#if atlasError}
|
|
73
|
+
<p class={classFor('formFieldError', atlas.appearance, 'atlas-error')} role="alert">{atlasError}</p>
|
|
74
|
+
{/if}
|
|
75
|
+
{/if}
|
|
76
|
+
|
|
45
77
|
{#if recoveryCodes}
|
|
46
78
|
<RecoveryCodes codes={recoveryCodes} busy={$flowState.busy} onSaved={flow.saveRecoveryCodes} />
|
|
47
79
|
{:else}
|
|
@@ -51,7 +83,7 @@ $: captcha = drawn($settings, $flowState);
|
|
|
51
83
|
errors={$flowState.errors}
|
|
52
84
|
sessionKept={$flowState.sessionKept}
|
|
53
85
|
titleKey="signIn.title"
|
|
54
|
-
onSubmit={
|
|
86
|
+
onSubmit={submitIdentifier}
|
|
55
87
|
onPrepare={flow.prepare}
|
|
56
88
|
onEmailSecondFactor={$settings?.account.emailSecondFactor ? flow.sendEmailSecondFactor : null}
|
|
57
89
|
onSmsSecondFactor={$settings && flow.mfaChoices().sms ? flow.sendSmsSecondFactor : null}
|
|
@@ -63,6 +95,18 @@ $: captcha = drawn($settings, $flowState);
|
|
|
63
95
|
/>
|
|
64
96
|
{/if}
|
|
65
97
|
|
|
98
|
+
{#if passkeyOffered && !recoveryCodes}
|
|
99
|
+
<button
|
|
100
|
+
type="button"
|
|
101
|
+
class={classFor('socialButton', atlas.appearance, 'atlas-social-button atlas-passkey-button')}
|
|
102
|
+
data-atlas-passkey-sign-in=""
|
|
103
|
+
disabled={$flowState.busy}
|
|
104
|
+
on:click={() => flow.passkey.signIn()}
|
|
105
|
+
>
|
|
106
|
+
{t('signIn.passkeyButton')}
|
|
107
|
+
</button>
|
|
108
|
+
{/if}
|
|
109
|
+
|
|
66
110
|
{#if promptHref}
|
|
67
111
|
<p class={classFor('footerAction', atlas.appearance, 'atlas-footer')} data-atlas-sign-up-prompt="">
|
|
68
112
|
{t('signIn.noAccount')} <a class="atlas-link" href={promptHref}>{t('signIn.signUpLink')}</a>
|
package/dist/i18n.js
CHANGED
|
@@ -22,6 +22,7 @@ export const EN_US = {
|
|
|
22
22
|
'signIn.signUpLink': 'Sign up',
|
|
23
23
|
'signIn.orDivider': 'or',
|
|
24
24
|
'signIn.socialButton': 'Continue with {provider}',
|
|
25
|
+
'signIn.continueWithAtlas': 'Continue with Atlas',
|
|
25
26
|
'signIn.emailCodeLabel': 'Verification code',
|
|
26
27
|
'signIn.emailCodeOption': 'Email me a code',
|
|
27
28
|
'signIn.emailLinkOption': 'Email me a sign-in link',
|
|
@@ -32,6 +33,8 @@ export const EN_US = {
|
|
|
32
33
|
'signIn.resendCode': 'Resend code',
|
|
33
34
|
'signIn.resendLink': 'Resend link',
|
|
34
35
|
'signIn.passwordOption': 'Use your password instead',
|
|
36
|
+
'signIn.passkeyButton': 'Sign in with a passkey',
|
|
37
|
+
'signIn.passkeyCancelled': "Passkey sign-in didn't finish. Try again, or use another way to sign in.",
|
|
35
38
|
'signIn.signedIn': 'You\'re signed in.',
|
|
36
39
|
'signIn.sessionNotKept': 'You signed in, but this browser didn\'t keep the session. If it blocks third-party cookies, allow cookies for this site and try again.',
|
|
37
40
|
'signIn.checkOtherTab': 'You can close this tab — you are signed in where you started.',
|
package/dist/version.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { AtlasSdkInfo } from '@atlasauth/js';
|
|
2
2
|
/** This package's version, sent as `X-Atlas-SDK` (kept in step with package.json by a test). */
|
|
3
|
-
export declare const ATLAS_SVELTE_VERSION = "0.
|
|
3
|
+
export declare const ATLAS_SVELTE_VERSION = "0.13.0";
|
|
4
4
|
export declare const ATLAS_SVELTE_SDK: AtlasSdkInfo;
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** This package's version, sent as `X-Atlas-SDK` (kept in step with package.json by a test). */
|
|
2
|
-
export const ATLAS_SVELTE_VERSION = '0.
|
|
2
|
+
export const ATLAS_SVELTE_VERSION = '0.13.0';
|
|
3
3
|
export const ATLAS_SVELTE_SDK = { name: '@atlasauth/svelte', version: ATLAS_SVELTE_VERSION };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlasauth/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"svelte": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@atlasauth/design": "0.3.0",
|
|
26
|
-
"@atlasauth/js": "0.
|
|
26
|
+
"@atlasauth/js": "0.27.0",
|
|
27
27
|
"@atlasauth/authz": "0.3.0",
|
|
28
|
-
"@atlasauth/backend": "0.
|
|
28
|
+
"@atlasauth/backend": "0.28.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"svelte": ">=4",
|