@sentropic/auth-ui 0.2.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/LICENSE +21 -0
- package/README.md +163 -0
- package/dist/contracts.d.ts +7 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +7 -0
- package/dist/contracts.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +12 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/labels.d.ts +5 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +180 -0
- package/dist/labels.js.map +1 -0
- package/dist/transport-fetch.d.ts +25 -0
- package/dist/transport-fetch.d.ts.map +1 -0
- package/dist/transport-fetch.js +98 -0
- package/dist/transport-fetch.js.map +1 -0
- package/dist/transport-types.d.ts +77 -0
- package/dist/transport-types.d.ts.map +1 -0
- package/dist/transport-types.js +2 -0
- package/dist/transport-types.js.map +1 -0
- package/dist/transport.d.ts +3 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +29 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/webauthn.d.ts +26 -0
- package/dist/webauthn.d.ts.map +1 -0
- package/dist/webauthn.js +76 -0
- package/dist/webauthn.js.map +1 -0
- package/package.json +86 -0
- package/src/components/AuthDevicePair.svelte +173 -0
- package/src/components/AuthDevicePair.svelte.d.ts +17 -0
- package/src/components/AuthDevices.svelte +313 -0
- package/src/components/AuthDevices.svelte.d.ts +18 -0
- package/src/components/AuthLogin.svelte +222 -0
- package/src/components/AuthLogin.svelte.d.ts +18 -0
- package/src/components/AuthMagicLinkVerify.svelte +165 -0
- package/src/components/AuthMagicLinkVerify.svelte.d.ts +20 -0
- package/src/components/AuthRegister.svelte +394 -0
- package/src/components/AuthRegister.svelte.d.ts +25 -0
- package/src/contracts.ts +6 -0
- package/src/errors.ts +18 -0
- package/src/index.ts +2 -0
- package/src/labels.ts +186 -0
- package/src/transport-fetch.ts +170 -0
- package/src/transport-types.ts +105 -0
- package/src/transport.ts +33 -0
- package/src/types.ts +153 -0
- package/src/webauthn.ts +133 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Fabien Antoine
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# @sentropic/auth-ui
|
|
2
|
+
|
|
3
|
+
Reusable Svelte authentication UI (passkeys + email OTP + magic link + device management) for apps that mount `@sentropic/auth-hono` (or compatible) auth routes.
|
|
4
|
+
|
|
5
|
+
The package is **host-adapter driven**. It owns the user-facing flow, the WebAuthn ceremony, the labels, and the visual layout — but it never touches the app's session store, navigation, API helpers, or backend implementation. Consumers inject a transport, callbacks, and labels and keep ownership of side-effects.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @sentropic/auth-ui
|
|
11
|
+
# peer deps you already have:
|
|
12
|
+
# svelte ^5.0.0
|
|
13
|
+
# @simplewebauthn/browser ^13.2.2
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```svelte
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
import { goto } from '$app/navigation';
|
|
21
|
+
import AuthLogin from '@sentropic/auth-ui/components/AuthLogin.svelte';
|
|
22
|
+
import {
|
|
23
|
+
createDefaultFetchTransport,
|
|
24
|
+
createFrenchAuthUiLabels,
|
|
25
|
+
type AuthUiSession,
|
|
26
|
+
} from '@sentropic/auth-ui';
|
|
27
|
+
|
|
28
|
+
const transport = createDefaultFetchTransport({
|
|
29
|
+
baseUrl: '/auth',
|
|
30
|
+
onUnauthorized: () => goto('/auth/login'),
|
|
31
|
+
});
|
|
32
|
+
const labels = createFrenchAuthUiLabels();
|
|
33
|
+
|
|
34
|
+
async function handleLoggedIn(session: AuthUiSession) {
|
|
35
|
+
// host owns the side-effects (store, cookies, redirect)
|
|
36
|
+
sessionStorage.setItem('sessionToken', session.sessionToken ?? '');
|
|
37
|
+
await goto('/dashboard');
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<AuthLogin {transport} {labels} onLoggedIn={handleLoggedIn} />
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Public surface
|
|
45
|
+
|
|
46
|
+
| Export path | Contents |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `@sentropic/auth-ui` | `AuthUiTransport`, `AuthUiSession`, `AuthUiError`, `AuthUiLabels`, `createDefaultAuthUiLabels`, `createFrenchAuthUiLabels`, `createDefaultAuthUiBranding`, `assertAuthUiTransport`, `normalizeAuthEmail`, `createAuthUiError`, `createDefaultFetchTransport`, WebAuthn helpers |
|
|
49
|
+
| `@sentropic/auth-ui/components/AuthLogin.svelte` | Passkey login screen (discoverable credentials, lost-device path) |
|
|
50
|
+
| `@sentropic/auth-ui/components/AuthRegister.svelte` | Email-code → passkey registration; optional `skipEmailVerification` for hosts that own pre-auth |
|
|
51
|
+
| `@sentropic/auth-ui/components/AuthMagicLinkVerify.svelte` | Verifies a magic-link token from a host-supplied source |
|
|
52
|
+
| `@sentropic/auth-ui/components/AuthDevices.svelte` | Lists / renames / revokes registered passkeys |
|
|
53
|
+
| `@sentropic/auth-ui/components/AuthDevicePair.svelte` | Approves a device-code pairing (`approveDevicePairing` contract) |
|
|
54
|
+
|
|
55
|
+
All five components accept a `labels?: Partial<AuthUiLabels>` prop so hosts can override copy without forking. Each takes a `transport: AuthUiTransport` and one or more host callbacks (`onLoggedIn`, `onRegistered`, `onVerified`, `onPaired`, `onUnauthorized`, `onError`). Visual customisation flows through CSS custom properties (`--auth-primary`, `--auth-bg`, `--auth-text`, `--auth-radius`, `--auth-font-family`, …) and slots (`no-account`, `register-new-device`, `back-to-login`, `back-to-devices`, `pair-cta`, `add-device`, `login-link`, `cancel`).
|
|
56
|
+
|
|
57
|
+
## Transport boundary
|
|
58
|
+
|
|
59
|
+
`AuthUiTransport` is the only contract between the package and the backend. Implement it yourself, or use `createDefaultFetchTransport({ baseUrl, fetch?, headers?, onUnauthorized?, withCredentials? })` if your backend matches the `@sentropic/auth-hono` route shape:
|
|
60
|
+
|
|
61
|
+
| Method | Backend route |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `requestEmailCode` | `POST {baseUrl}/email/verify-request` |
|
|
64
|
+
| `verifyEmailCode` | `POST {baseUrl}/email/verify-code` |
|
|
65
|
+
| `verifyMagicLink` | `POST {baseUrl}/magic-link/verify` |
|
|
66
|
+
| `createPasskeyRegistrationOptions` | `POST {baseUrl}/register/options` |
|
|
67
|
+
| `verifyPasskeyRegistration` | `POST {baseUrl}/register/verify` |
|
|
68
|
+
| `createPasskeyAuthenticationOptions` | `POST {baseUrl}/login/options` |
|
|
69
|
+
| `verifyPasskeyAuthentication` | `POST {baseUrl}/login/verify` |
|
|
70
|
+
| `refreshSession` | `POST {baseUrl}/session/refresh` |
|
|
71
|
+
| `logout` | `DELETE {baseUrl}/session` |
|
|
72
|
+
| `listCredentials` | `GET {baseUrl}/credentials` |
|
|
73
|
+
| `renameCredential` | `PUT {baseUrl}/credentials/{id}` |
|
|
74
|
+
| `revokeCredential` | `DELETE {baseUrl}/credentials/{id}` |
|
|
75
|
+
| `approveDevicePairing` | `POST {baseUrl}/device/approve` (auto-maps `userCode`/`deviceName` to snake_case body) |
|
|
76
|
+
|
|
77
|
+
## Mounting recipes
|
|
78
|
+
|
|
79
|
+
### Sentropic (`/auth/*`)
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
// ui/src/lib/services/auth-transport.ts
|
|
83
|
+
import { createDefaultFetchTransport, createDefaultAuthUiLabels, createFrenchAuthUiLabels, type AuthUiLabels } from '@sentropic/auth-ui';
|
|
84
|
+
import { apiFetch } from '$lib/utils/api';
|
|
85
|
+
|
|
86
|
+
export const createSentropicAuthTransport = (options: { onUnauthorized?: () => void } = {}) =>
|
|
87
|
+
createDefaultFetchTransport({
|
|
88
|
+
baseUrl: '/auth',
|
|
89
|
+
fetch: (input, init) => apiFetch(input, init),
|
|
90
|
+
onUnauthorized: options.onUnauthorized,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export const resolveAuthUiLabels = (locale: string | null | undefined): AuthUiLabels =>
|
|
94
|
+
(locale ?? 'fr').toLowerCase().startsWith('fr')
|
|
95
|
+
? createFrenchAuthUiLabels()
|
|
96
|
+
: createDefaultAuthUiLabels();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```svelte
|
|
100
|
+
<!-- ui/src/routes/auth/login/+page.svelte -->
|
|
101
|
+
<script lang="ts">
|
|
102
|
+
import { goto } from '$app/navigation';
|
|
103
|
+
import { locale } from 'svelte-i18n';
|
|
104
|
+
import AuthLogin from '@sentropic/auth-ui/components/AuthLogin.svelte';
|
|
105
|
+
import { setUser } from '$lib/stores/session';
|
|
106
|
+
import { createSentropicAuthTransport, resolveAuthUiLabels, toSentropicUser } from '$lib/services/auth-transport';
|
|
107
|
+
|
|
108
|
+
const transport = createSentropicAuthTransport();
|
|
109
|
+
$: labels = resolveAuthUiLabels($locale);
|
|
110
|
+
|
|
111
|
+
async function handleLoggedIn(session) {
|
|
112
|
+
setUser(toSentropicUser(session.user));
|
|
113
|
+
await goto('/neutral');
|
|
114
|
+
}
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
<AuthLogin {transport} {labels} onLoggedIn={handleLoggedIn} />
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Admin-flavoured host (`/admin/auth/*`)
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
const adminTransport = createDefaultFetchTransport({
|
|
124
|
+
baseUrl: '/admin/auth',
|
|
125
|
+
headers: { Authorization: `Bearer ${tenantToken}`, 'x-admin-tenant': tenant },
|
|
126
|
+
withCredentials: false,
|
|
127
|
+
onUnauthorized: () => location.assign('/admin/sign-in'),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const adminLabels = createFrenchAuthUiLabels({
|
|
131
|
+
loginTitle: 'Connexion admin',
|
|
132
|
+
loginButton: 'Se connecter (admin)',
|
|
133
|
+
registerTitle: 'Inviter un administrateur',
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
See `tests/example-admin-fetch-transport.test.ts` for a full walkthrough.
|
|
138
|
+
|
|
139
|
+
## Brand assets, FR labels, post-login redirects
|
|
140
|
+
|
|
141
|
+
- **Brand assets**: pass slot content (`no-account`, `register-new-device`, …) for app-specific link shapes (SvelteKit `<a>`, plain anchor, modal trigger). Use CSS variables for primary color, radius, fonts.
|
|
142
|
+
- **French labels**: `createFrenchAuthUiLabels(overrides?)` ships a complete FR baseline; partial overrides keep the unchanged keys.
|
|
143
|
+
- **Post-login redirects**: never built into the components — call `goto(returnUrl)` / `location.assign(...)` from `onLoggedIn` / `onRegistered` / `onVerified` / `onRedirect`. `AuthMagicLinkVerify` exposes `redirectDelayMs` (defaults to 1000 ms) so the success screen has time to render before the host redirect fires.
|
|
144
|
+
|
|
145
|
+
## Backend coupling (BR-39b)
|
|
146
|
+
|
|
147
|
+
`@sentropic/auth-hono` provides reusable Hono route factories that match this transport shape 1:1. It is **not required** to adopt this UI package — any backend that exposes the routes listed above will work. BR-39b removes the duplicated backend code from Sentropic, but the UI package was usable before that landed.
|
|
148
|
+
|
|
149
|
+
## Versioning
|
|
150
|
+
|
|
151
|
+
Follows semver. Every PR that touches `packages/auth-ui/src/**` must bump `version` in `packages/auth-ui/package.json` (patch for bugfix, minor for feature, major for breaking). The CI `enforce-package-bump` job blocks merge otherwise.
|
|
152
|
+
|
|
153
|
+
## First publish
|
|
154
|
+
|
|
155
|
+
A brand-new package requires a one-shot bootstrap:
|
|
156
|
+
|
|
157
|
+
1. Trigger `workflow_dispatch` on `ci.yml` with `bootstrap_publish_target=auth-ui` (uses the `NPM_TOKEN` secret).
|
|
158
|
+
2. On `https://www.npmjs.com/package/@sentropic/auth-ui/access`, attach the OIDC trusted publisher pointing to `rhanka/sentropic` workflow `ci.yml`.
|
|
159
|
+
3. From then on, steady-state CI publishes via OIDC trusted publishing on every merge to `main` that bumps the version.
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT — see `LICENSE`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AuthUiError, AuthUiErrorCode } from './types.js';
|
|
2
|
+
export declare const createAuthUiError: (code: AuthUiErrorCode, message: string, options?: {
|
|
3
|
+
retryable?: boolean;
|
|
4
|
+
cause?: unknown;
|
|
5
|
+
}) => AuthUiError;
|
|
6
|
+
export declare const normalizeAuthEmail: (email: string) => string;
|
|
7
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,iBAAiB,SACtB,eAAe,WACZ,MAAM,YACN;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KAChD,WASF,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAAW,MAAM,KAAG,MAAoC,CAAC"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const createAuthUiError = (code, message, options = {}) => {
|
|
2
|
+
const error = new Error(message);
|
|
3
|
+
Object.defineProperties(error, {
|
|
4
|
+
name: { value: 'AuthUiError', enumerable: true },
|
|
5
|
+
code: { value: code, enumerable: true },
|
|
6
|
+
retryable: { value: options.retryable ?? false, enumerable: true },
|
|
7
|
+
cause: { value: options.cause, enumerable: false },
|
|
8
|
+
});
|
|
9
|
+
return error;
|
|
10
|
+
};
|
|
11
|
+
export const normalizeAuthEmail = (email) => email.trim().toLowerCase();
|
|
12
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAqB,EACrB,OAAe,EACf,UAAoD,EAAE,EACzC,EAAE;IACf,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAgB,CAAC;IAChD,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE;QAC7B,IAAI,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,EAAE;QAChD,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE;QACvC,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,IAAI,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE;QAClE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE;KACnD,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
|
package/dist/labels.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AuthUiBranding, AuthUiLabels } from './types.js';
|
|
2
|
+
export declare const createDefaultAuthUiLabels: (overrides?: Partial<AuthUiLabels>) => AuthUiLabels;
|
|
3
|
+
export declare const createFrenchAuthUiLabels: (overrides?: Partial<AuthUiLabels>) => AuthUiLabels;
|
|
4
|
+
export declare const createDefaultAuthUiBranding: (overrides?: Partial<AuthUiBranding>) => AuthUiBranding;
|
|
5
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,yBAAyB,eAAe,QAAQ,YAAY,CAAC,KAAQ,YAoFhF,CAAC;AAEH,eAAO,MAAM,wBAAwB,eAAe,QAAQ,YAAY,CAAC,KAAQ,YAmF7E,CAAC;AAEL,eAAO,MAAM,2BAA2B,eAAe,QAAQ,cAAc,CAAC,KAAQ,cAYrF,CAAC"}
|
package/dist/labels.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
export const createDefaultAuthUiLabels = (overrides = {}) => ({
|
|
2
|
+
loading: 'Loading...',
|
|
3
|
+
save: 'Save',
|
|
4
|
+
cancel: 'Cancel',
|
|
5
|
+
emailPlaceholder: 'you@example.com',
|
|
6
|
+
webauthnRegisterNotice: 'You are about to register a new WebAuthn device. We will send you a confirmation email.',
|
|
7
|
+
verifyInProgress: 'Verification in progress...',
|
|
8
|
+
redirectingDashboard: 'Redirecting to your dashboard...',
|
|
9
|
+
registerDeviceNow: 'You will now register your WebAuthn device.',
|
|
10
|
+
loginTitle: 'Sign in',
|
|
11
|
+
loginSupportedHint: 'Use a passkey to continue.',
|
|
12
|
+
loginUnavailable: 'Passkeys are not available in this browser.',
|
|
13
|
+
loginUnsupportedBrowser: 'Your browser does not support WebAuthn. Use a modern browser (Chrome, Firefox, Safari, Edge).',
|
|
14
|
+
loginButton: 'Sign in with passkey',
|
|
15
|
+
loginButtonLoading: 'Signing in...',
|
|
16
|
+
loginLostDevice: 'Lost your device?',
|
|
17
|
+
loginLostDeviceTitle: 'Lost device',
|
|
18
|
+
loginNoAccount: "Don't have an account? Sign up",
|
|
19
|
+
loginRegisterNewDevice: 'Register a new device',
|
|
20
|
+
loginBackToLogin: 'Back to sign in',
|
|
21
|
+
registerTitle: 'Create an account',
|
|
22
|
+
registerSubtitle: 'Secure authentication with WebAuthn.',
|
|
23
|
+
registerUnsupportedBrowserTitle: 'Browser not supported',
|
|
24
|
+
registerUnsupportedBrowser: 'Your browser does not support WebAuthn. Use a modern browser (Chrome, Firefox, Safari, Edge).',
|
|
25
|
+
registerEmailLabel: 'Email',
|
|
26
|
+
registerGetCode: 'Get verification code',
|
|
27
|
+
registerSendingCode: 'Sending code...',
|
|
28
|
+
registerAlreadyHaveAccount: 'Already have an account? Sign in',
|
|
29
|
+
registerCodeLabel: 'Verification code',
|
|
30
|
+
registerCodeHelp: 'Enter the 6-digit code we just emailed you.',
|
|
31
|
+
registerVerifyCode: 'Verify code',
|
|
32
|
+
registerVerifyingCode: 'Verifying...',
|
|
33
|
+
registerChangeEmail: 'Change email',
|
|
34
|
+
registerCodeVerifiedTitle: 'Code verified',
|
|
35
|
+
registerPasskeyButton: 'Register my WebAuthn device',
|
|
36
|
+
registerRegistering: 'Registering...',
|
|
37
|
+
registerSuccessTitle: 'Account created',
|
|
38
|
+
registerSuccessCodeSent: 'Verification code sent by email.',
|
|
39
|
+
registerSuccessRedirecting: 'Account created. Redirecting...',
|
|
40
|
+
registerErrorInvalidEmail: 'Please enter a valid email address.',
|
|
41
|
+
registerErrorSendCode: 'Failed to send the verification code.',
|
|
42
|
+
magicLinkTitle: 'Verifying magic link',
|
|
43
|
+
magicLinkVerifying: 'Verifying your link...',
|
|
44
|
+
magicLinkSuccess: 'You are signed in.',
|
|
45
|
+
magicLinkSuccessTitle: 'Signed in.',
|
|
46
|
+
magicLinkErrorTitle: 'Verification failed',
|
|
47
|
+
magicLinkBackToLogin: 'Back to sign in',
|
|
48
|
+
magicLinkErrorMissingToken: 'Token missing from the URL.',
|
|
49
|
+
magicLinkErrorVerifyFailed: 'Failed to verify the magic link.',
|
|
50
|
+
devicesTitle: 'My devices',
|
|
51
|
+
devicesSubtitle: 'Manage WebAuthn devices registered for this account.',
|
|
52
|
+
devicesEmpty: 'No devices registered yet.',
|
|
53
|
+
devicesRegister: 'Register a device',
|
|
54
|
+
devicesAddNew: 'Add a new device',
|
|
55
|
+
devicesRename: 'Rename',
|
|
56
|
+
devicesRevoke: 'Revoke',
|
|
57
|
+
devicesUvEnabled: 'UV enabled',
|
|
58
|
+
devicesAddedOn: 'Added on {date}',
|
|
59
|
+
devicesLastUsed: 'Last used: {date}',
|
|
60
|
+
devicesConfirmRevoke: 'Are you sure you want to revoke the device "{deviceName}"? You will no longer be able to sign in with it.',
|
|
61
|
+
devicesErrorLoad: 'Failed to load devices.',
|
|
62
|
+
devicesErrorUpdate: 'Update failed.',
|
|
63
|
+
devicesErrorRevoke: 'Revoke failed.',
|
|
64
|
+
devicePairTitle: 'Pair a device',
|
|
65
|
+
devicePairSubtitle: 'Enter the code displayed by the companion app on your workstation.',
|
|
66
|
+
devicePairCodeLabel: 'Pairing code',
|
|
67
|
+
devicePairCodePlaceholder: 'PAIR-XXXX',
|
|
68
|
+
devicePairDeviceNameLabel: 'Device name',
|
|
69
|
+
devicePairDeviceNamePlaceholder: 'My workstation',
|
|
70
|
+
devicePairConfirm: 'Pair device',
|
|
71
|
+
devicePairConfirming: 'Pairing...',
|
|
72
|
+
devicePairSuccess: 'Device paired. You can return to the companion app.',
|
|
73
|
+
devicePairBack: 'Back to devices',
|
|
74
|
+
devicePairErrorCodeRequired: 'The pairing code is required.',
|
|
75
|
+
devicePairErrorNotFound: 'Invalid or expired code.',
|
|
76
|
+
devicePairErrorGeneric: 'Failed to pair the device.',
|
|
77
|
+
passkeyNotSupported: 'WebAuthn is not supported in this browser',
|
|
78
|
+
passkeyCancelled: 'Passkey operation cancelled by user',
|
|
79
|
+
passkeyAlreadyRegistered: 'This authenticator is already registered',
|
|
80
|
+
passkeyNoMatchingAuthenticator: 'No matching authenticator found',
|
|
81
|
+
passkeyAuthenticatorNotSupported: 'This authenticator is not supported',
|
|
82
|
+
passkeyRegistrationCancelled: 'You cancelled the registration.',
|
|
83
|
+
passkeyAuthenticationCancelled: 'You cancelled the authentication.',
|
|
84
|
+
...overrides,
|
|
85
|
+
});
|
|
86
|
+
export const createFrenchAuthUiLabels = (overrides = {}) => createDefaultAuthUiLabels({
|
|
87
|
+
loading: 'Chargement…',
|
|
88
|
+
save: 'Enregistrer',
|
|
89
|
+
cancel: 'Annuler',
|
|
90
|
+
emailPlaceholder: 'vous@example.com',
|
|
91
|
+
webauthnRegisterNotice: "Vous allez enregistrer un nouvel appareil WebAuthn. Nous vous enverrons un email de confirmation.",
|
|
92
|
+
verifyInProgress: 'Vérification en cours…',
|
|
93
|
+
redirectingDashboard: 'Redirection vers le tableau de bord…',
|
|
94
|
+
registerDeviceNow: 'Vous allez maintenant enregistrer votre appareil WebAuthn',
|
|
95
|
+
loginTitle: 'Connexion',
|
|
96
|
+
loginSupportedHint: 'Utilisez votre passkey ou biométrie',
|
|
97
|
+
loginUnavailable: 'WebAuthn non disponible sur ce navigateur',
|
|
98
|
+
loginUnsupportedBrowser: 'Votre navigateur ne supporte pas WebAuthn. Utilisez un navigateur moderne (Chrome, Firefox, Safari, Edge).',
|
|
99
|
+
loginButton: 'Se connecter avec WebAuthn',
|
|
100
|
+
loginButtonLoading: 'Connexion…',
|
|
101
|
+
loginLostDevice: "J'ai perdu mon appareil",
|
|
102
|
+
loginLostDeviceTitle: "Perte d'appareil",
|
|
103
|
+
loginNoAccount: "Pas encore de compte ? S'inscrire",
|
|
104
|
+
loginRegisterNewDevice: 'Enregistrer un nouvel appareil (workflow complet)',
|
|
105
|
+
loginBackToLogin: 'Retour à la connexion normale',
|
|
106
|
+
registerTitle: 'Créer un compte',
|
|
107
|
+
registerSubtitle: 'Authentification sécurisée avec WebAuthn',
|
|
108
|
+
registerUnsupportedBrowserTitle: 'Navigateur non compatible',
|
|
109
|
+
registerUnsupportedBrowser: 'Votre navigateur ne supporte pas WebAuthn. Utilisez un navigateur moderne (Chrome, Firefox, Safari, Edge).',
|
|
110
|
+
registerEmailLabel: 'Email',
|
|
111
|
+
registerGetCode: 'Obtenir un code',
|
|
112
|
+
registerSendingCode: 'Envoi…',
|
|
113
|
+
registerAlreadyHaveAccount: 'Déjà un compte ? Se connecter',
|
|
114
|
+
registerCodeLabel: 'Code à 6 chiffres',
|
|
115
|
+
registerCodeHelp: 'Saisissez le code reçu par email',
|
|
116
|
+
registerVerifyCode: 'Vérifier le code',
|
|
117
|
+
registerVerifyingCode: 'Vérification…',
|
|
118
|
+
registerChangeEmail: "Modifier l'email",
|
|
119
|
+
registerCodeVerifiedTitle: 'Code vérifié !',
|
|
120
|
+
registerPasskeyButton: 'Enregistrer mon appareil WebAuthn',
|
|
121
|
+
registerRegistering: 'Enregistrement…',
|
|
122
|
+
registerSuccessTitle: 'Inscription réussie !',
|
|
123
|
+
registerSuccessCodeSent: 'Code envoyé par email',
|
|
124
|
+
registerSuccessRedirecting: 'Inscription réussie ! Redirection…',
|
|
125
|
+
registerErrorInvalidEmail: 'Veuillez saisir une adresse email valide',
|
|
126
|
+
registerErrorSendCode: "Erreur lors de l'envoi du code",
|
|
127
|
+
magicLinkTitle: 'Vérification du lien magique',
|
|
128
|
+
magicLinkVerifying: 'Vérification en cours…',
|
|
129
|
+
magicLinkSuccess: 'Vous êtes connecté.',
|
|
130
|
+
magicLinkSuccessTitle: 'Connexion réussie !',
|
|
131
|
+
magicLinkErrorTitle: 'Erreur de vérification',
|
|
132
|
+
magicLinkBackToLogin: 'Retour à la connexion',
|
|
133
|
+
magicLinkErrorMissingToken: 'Token manquant dans l\'URL',
|
|
134
|
+
magicLinkErrorVerifyFailed: 'Erreur lors de la vérification du lien magique',
|
|
135
|
+
devicesTitle: 'Mes appareils',
|
|
136
|
+
devicesSubtitle: "Gérez les appareils enregistrés pour l'authentification WebAuthn",
|
|
137
|
+
devicesEmpty: 'Aucun appareil enregistré',
|
|
138
|
+
devicesRegister: 'Enregistrer un appareil',
|
|
139
|
+
devicesAddNew: 'Ajouter un nouvel appareil',
|
|
140
|
+
devicesRename: 'Renommer',
|
|
141
|
+
devicesRevoke: 'Révoquer',
|
|
142
|
+
devicesUvEnabled: 'UV activée',
|
|
143
|
+
devicesAddedOn: 'Ajouté le {date}',
|
|
144
|
+
devicesLastUsed: 'Dernière utilisation : {date}',
|
|
145
|
+
devicesConfirmRevoke: 'Êtes-vous sûr de vouloir révoquer l\'appareil "{deviceName}" ? Vous ne pourrez plus vous connecter avec cet appareil.',
|
|
146
|
+
devicesErrorLoad: 'Erreur lors du chargement des appareils',
|
|
147
|
+
devicesErrorUpdate: 'Erreur lors de la mise à jour',
|
|
148
|
+
devicesErrorRevoke: 'Erreur lors de la révocation',
|
|
149
|
+
devicePairTitle: 'Appairer un appareil',
|
|
150
|
+
devicePairSubtitle: "Saisissez le code affiché par l'application compagnon sur votre poste de travail.",
|
|
151
|
+
devicePairCodeLabel: "Code d'appairage",
|
|
152
|
+
devicePairCodePlaceholder: 'PAIR-XXXX',
|
|
153
|
+
devicePairDeviceNameLabel: "Nom de l'appareil",
|
|
154
|
+
devicePairDeviceNamePlaceholder: 'Mon poste de travail',
|
|
155
|
+
devicePairConfirm: "Appairer l'appareil",
|
|
156
|
+
devicePairConfirming: 'Appairage…',
|
|
157
|
+
devicePairSuccess: 'Appareil appairé. Vous pouvez retourner à l\'application sur votre poste de travail.',
|
|
158
|
+
devicePairBack: 'Retour aux appareils',
|
|
159
|
+
devicePairErrorCodeRequired: "Le code d'appairage est requis.",
|
|
160
|
+
devicePairErrorNotFound: 'Code invalide ou expiré.',
|
|
161
|
+
devicePairErrorGeneric: "Échec de l'appairage de l'appareil.",
|
|
162
|
+
passkeyRegistrationCancelled: "Vous avez annulé l'inscription",
|
|
163
|
+
passkeyAuthenticationCancelled: "Vous avez annulé l'authentification",
|
|
164
|
+
passkeyAlreadyRegistered: 'Cet appareil est déjà enregistré',
|
|
165
|
+
passkeyNoMatchingAuthenticator: 'Aucun appareil reconnu',
|
|
166
|
+
passkeyAuthenticatorNotSupported: "Cet authentificateur n'est pas supporté",
|
|
167
|
+
...overrides,
|
|
168
|
+
});
|
|
169
|
+
export const createDefaultAuthUiBranding = (overrides = {}) => {
|
|
170
|
+
const branding = {
|
|
171
|
+
primaryColor: '#4f46e5',
|
|
172
|
+
accentColor: '#0f766e',
|
|
173
|
+
...overrides,
|
|
174
|
+
};
|
|
175
|
+
if (branding.productName && !branding.logoAlt) {
|
|
176
|
+
branding.logoAlt = branding.productName;
|
|
177
|
+
}
|
|
178
|
+
return branding;
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AuthUiTransport } from './transport-types.js';
|
|
2
|
+
export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
3
|
+
export interface CreateDefaultFetchTransportOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Base URL prefix mounted in front of the auth routes (e.g. "/auth", "/admin/auth").
|
|
6
|
+
* No trailing slash.
|
|
7
|
+
*/
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
fetch?: FetchLike;
|
|
10
|
+
/**
|
|
11
|
+
* Static headers merged into every request (e.g. tenant id, bearer token).
|
|
12
|
+
*/
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Invoked when an authenticated request receives a 401 response, so hosts can
|
|
16
|
+
* clear their session state and redirect to login.
|
|
17
|
+
*/
|
|
18
|
+
onUnauthorized?: () => void | Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Toggle `credentials: "include"` so the browser sends cookies. Default `true`.
|
|
21
|
+
*/
|
|
22
|
+
withCredentials?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare const createDefaultFetchTransport: (options: CreateDefaultFetchTransportOptions) => AuthUiTransport;
|
|
25
|
+
//# sourceMappingURL=transport-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport-fetch.d.ts","sourceRoot":"","sources":["../src/transport-fetch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,eAAe,EAehB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjF,MAAM,WAAW,kCAAkC;IACjD;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA2BD,eAAO,MAAM,2BAA2B,YAC7B,kCAAkC,KAC1C,eAgGF,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createAuthUiError } from './errors.js';
|
|
2
|
+
const safeJson = async (response) => {
|
|
3
|
+
const text = await response.text();
|
|
4
|
+
if (!text) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(text);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return text;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const extractErrorMessage = (payload, fallback) => {
|
|
15
|
+
if (payload && typeof payload === 'object') {
|
|
16
|
+
const record = payload;
|
|
17
|
+
if (typeof record.message === 'string' && record.message) {
|
|
18
|
+
return record.message;
|
|
19
|
+
}
|
|
20
|
+
if (typeof record.error === 'string' && record.error) {
|
|
21
|
+
return record.error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return fallback;
|
|
25
|
+
};
|
|
26
|
+
export const createDefaultFetchTransport = (options) => {
|
|
27
|
+
const baseUrl = options.baseUrl.replace(/\/$/, '');
|
|
28
|
+
const fetchImpl = options.fetch ?? (typeof fetch === 'function' ? fetch.bind(globalThis) : undefined);
|
|
29
|
+
const withCredentials = options.withCredentials ?? true;
|
|
30
|
+
if (!fetchImpl) {
|
|
31
|
+
throw createAuthUiError('invalid_input', 'No global fetch found; pass options.fetch when constructing the auth transport.');
|
|
32
|
+
}
|
|
33
|
+
const request = async (path, init) => {
|
|
34
|
+
const headers = { Accept: 'application/json', ...(options.headers ?? {}) };
|
|
35
|
+
let body;
|
|
36
|
+
if (init.body !== undefined) {
|
|
37
|
+
headers['Content-Type'] = 'application/json';
|
|
38
|
+
body = JSON.stringify(init.body);
|
|
39
|
+
}
|
|
40
|
+
let response;
|
|
41
|
+
try {
|
|
42
|
+
response = await fetchImpl(`${baseUrl}${path}`, {
|
|
43
|
+
method: init.method,
|
|
44
|
+
headers,
|
|
45
|
+
body,
|
|
46
|
+
credentials: withCredentials ? 'include' : 'same-origin',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (cause) {
|
|
50
|
+
return {
|
|
51
|
+
ok: false,
|
|
52
|
+
error: createAuthUiError('transport_error', 'Network request failed', { retryable: true, cause }),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const payload = await safeJson(response);
|
|
56
|
+
if (response.status === 401 && init.authenticated) {
|
|
57
|
+
void options.onUnauthorized?.();
|
|
58
|
+
}
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const message = extractErrorMessage(payload, `Request failed with status ${response.status}`);
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
error: createAuthUiError('transport_error', message, {
|
|
64
|
+
retryable: response.status >= 500,
|
|
65
|
+
cause: payload,
|
|
66
|
+
}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return { ok: true, value: payload };
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
requestEmailCode: (input) => request('/email/verify-request', { method: 'POST', body: input }),
|
|
73
|
+
verifyEmailCode: (input) => request('/email/verify-code', { method: 'POST', body: input }),
|
|
74
|
+
verifyMagicLink: (input) => request('/magic-link/verify', { method: 'POST', body: input }),
|
|
75
|
+
createPasskeyRegistrationOptions: (input) => request('/register/options', { method: 'POST', body: input }),
|
|
76
|
+
verifyPasskeyRegistration: (input) => request('/register/verify', { method: 'POST', body: input }),
|
|
77
|
+
createPasskeyAuthenticationOptions: (input) => request('/login/options', { method: 'POST', body: input }),
|
|
78
|
+
verifyPasskeyAuthentication: (input) => request('/login/verify', { method: 'POST', body: input }),
|
|
79
|
+
refreshSession: () => request('/session/refresh', { method: 'POST', authenticated: true }),
|
|
80
|
+
logout: () => request('/session', { method: 'DELETE', authenticated: true }),
|
|
81
|
+
listCredentials: () => request('/credentials', { method: 'GET', authenticated: true }),
|
|
82
|
+
renameCredential: (input) => request(`/credentials/${encodeURIComponent(input.credentialId)}`, {
|
|
83
|
+
method: 'PUT',
|
|
84
|
+
body: { deviceName: input.deviceName },
|
|
85
|
+
authenticated: true,
|
|
86
|
+
}),
|
|
87
|
+
revokeCredential: (input) => request(`/credentials/${encodeURIComponent(input.credentialId)}`, {
|
|
88
|
+
method: 'DELETE',
|
|
89
|
+
authenticated: true,
|
|
90
|
+
}),
|
|
91
|
+
approveDevicePairing: (input) => request('/device/approve', {
|
|
92
|
+
method: 'POST',
|
|
93
|
+
body: { user_code: input.userCode, device_name: input.deviceName },
|
|
94
|
+
authenticated: true,
|
|
95
|
+
}),
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=transport-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport-fetch.js","sourceRoot":"","sources":["../src/transport-fetch.ts"],"names":[],"mappings":"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"}
|