@atlasauth/js 0.16.0 → 0.17.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/captcha-controller.js +1 -1
  3. package/dist/captcha-controller.js.map +1 -1
  4. package/dist/captcha-widget.d.ts +20 -2
  5. package/dist/captcha-widget.js +79 -4
  6. package/dist/captcha-widget.js.map +1 -1
  7. package/dist/captcha.d.ts +5 -0
  8. package/dist/captcha.js +30 -0
  9. package/dist/captcha.js.map +1 -1
  10. package/dist/compat.d.ts +149 -0
  11. package/dist/compat.js +363 -0
  12. package/dist/compat.js.map +1 -0
  13. package/dist/device-authorization.d.ts +70 -0
  14. package/dist/device-authorization.js +97 -0
  15. package/dist/device-authorization.js.map +1 -0
  16. package/dist/email-code-check.d.ts +60 -0
  17. package/dist/email-code-check.js +51 -0
  18. package/dist/email-code-check.js.map +1 -0
  19. package/dist/frontchannel-logout.d.ts +36 -0
  20. package/dist/frontchannel-logout.js.map +1 -1
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.js +5 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/passkey-sign-up.d.ts +2 -2
  25. package/dist/passkey-sign-up.js +7 -1
  26. package/dist/passkey-sign-up.js.map +1 -1
  27. package/dist/passkey.d.ts +58 -2
  28. package/dist/passkey.js +61 -0
  29. package/dist/passkey.js.map +1 -1
  30. package/dist/sign-out-guard.d.ts +7 -0
  31. package/dist/sign-out-guard.js +38 -4
  32. package/dist/sign-out-guard.js.map +1 -1
  33. package/dist/sign-out.d.ts +23 -0
  34. package/dist/sign-out.js +37 -2
  35. package/dist/sign-out.js.map +1 -1
  36. package/dist/upstream-logout.d.ts +26 -0
  37. package/dist/upstream-logout.js +60 -0
  38. package/dist/upstream-logout.js.map +1 -0
  39. package/dist/version.d.ts +1 -1
  40. package/dist/version.js +1 -1
  41. package/package.json +12 -1
package/dist/compat.js ADDED
@@ -0,0 +1,363 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Auth0CompatClient = exports.Auth0CompatError = void 0;
4
+ exports.decodeJwtPayload = decodeJwtPayload;
5
+ exports.auth0UserFromClient = auth0UserFromClient;
6
+ exports.createAuth0CompatClient = createAuth0CompatClient;
7
+ /**
8
+ * `@atlasauth/js/compat` — a drop-in for `@auth0/auth0-spa-js` on Atlas, for
9
+ * framework-free browser apps (what `atlas migrate code --from auth0` rewrites
10
+ * `createAuth0Client` / `new Auth0Client` onto).
11
+ *
12
+ * The client keeps auth0-spa-js's method names and result shapes —
13
+ * `loginWithRedirect`, `handleRedirectCallback`, `isAuthenticated`, `getUser`,
14
+ * `getTokenSilently`, `logout`, … — on top of the Atlas Frontend API: the session
15
+ * lives in Atlas's own cookies, sign-in happens on your instance's hosted pages
16
+ * (or straight at a social provider when `authorizationParams.connection` is
17
+ * given), and tokens are Atlas session tokens. Move call sites to the native
18
+ * `@atlasauth/js` APIs at your own pace.
19
+ */
20
+ const fapi_1 = require("./fapi");
21
+ const redirect_1 = require("./redirect");
22
+ const sign_out_1 = require("./sign-out");
23
+ const dev_browser_1 = require("./dev-browser");
24
+ /** auth0-spa-js-style errors: `error` carries the OAuth-ish code apps branch on. */
25
+ class Auth0CompatError extends Error {
26
+ error;
27
+ constructor(error, message) {
28
+ super(message);
29
+ this.error = error;
30
+ this.name = 'Auth0CompatError';
31
+ }
32
+ }
33
+ exports.Auth0CompatError = Auth0CompatError;
34
+ /** Auth0 connection names → Atlas provider keys (others pass through). */
35
+ const CONNECTIONS = {
36
+ 'google-oauth2': 'google',
37
+ windowslive: 'microsoft',
38
+ 'microsoft-account': 'microsoft',
39
+ github: 'github',
40
+ apple: 'apple',
41
+ facebook: 'facebook',
42
+ linkedin: 'linkedin',
43
+ twitter: 'twitter',
44
+ discord: 'discord',
45
+ gitlab: 'gitlab',
46
+ bitbucket: 'bitbucket',
47
+ };
48
+ const APP_STATE_KEY = 'atlas:compat:appState';
49
+ /** Decode a JWT's payload (no verification: it came from our own FAPI). */
50
+ function decodeJwtPayload(jwt) {
51
+ const part = jwt.split('.')[1];
52
+ if (!part)
53
+ return null;
54
+ try {
55
+ const b64 = part.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(part.length / 4) * 4, '=');
56
+ const json = decodeURIComponent(Array.from(atob(b64), (c) => `%${c.charCodeAt(0).toString(16).padStart(2, '0')}`).join(''));
57
+ return JSON.parse(json);
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ /** Project the Frontend API user onto the OIDC profile shape. */
64
+ function auth0UserFromClient(user) {
65
+ if (!user)
66
+ return undefined;
67
+ const emails = user.email_addresses ?? [];
68
+ const email = emails.find((e) => e.primary) ?? emails.find((e) => e.verified) ?? emails[0];
69
+ const out = { sub: user.id };
70
+ const name = [user.first_name, user.last_name].filter(Boolean).join(' ') || user.username;
71
+ if (name)
72
+ out.name = name;
73
+ if (user.first_name)
74
+ out.given_name = user.first_name;
75
+ if (user.last_name)
76
+ out.family_name = user.last_name;
77
+ if (user.username)
78
+ out.nickname = user.username;
79
+ if (user.image_url)
80
+ out.picture = user.image_url;
81
+ if (email) {
82
+ out.email = email.email_address;
83
+ out.email_verified = email.verified;
84
+ }
85
+ return out;
86
+ }
87
+ function frontendApiFrom(options) {
88
+ const raw = options.frontendApi ?? options.domain ?? '';
89
+ if (!raw)
90
+ return '';
91
+ const withScheme = /^https?:\/\//i.test(raw) ? raw : `https://${raw}`;
92
+ return withScheme.replace(/\/+$/, '');
93
+ }
94
+ function withRedirect(url, redirectUrl) {
95
+ if (!redirectUrl)
96
+ return url;
97
+ return `${url}${url.includes('?') ? '&' : '?'}redirect_url=${encodeURIComponent(redirectUrl)}`;
98
+ }
99
+ function currentHref() {
100
+ return typeof window === 'undefined' ? undefined : window.location.href;
101
+ }
102
+ function storage() {
103
+ try {
104
+ return typeof window === 'undefined' ? null : window.sessionStorage;
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ /** The auth0-spa-js `Auth0Client`, on Atlas. */
111
+ class Auth0CompatClient {
112
+ publishableKey;
113
+ frontendApi;
114
+ fapi;
115
+ raw;
116
+ options;
117
+ state = null;
118
+ token = null;
119
+ constructor(options) {
120
+ const publishableKey = options.publishableKey ?? options.clientId;
121
+ if (!publishableKey)
122
+ throw new Error('Auth0CompatClient: publishableKey is required.');
123
+ this.publishableKey = publishableKey;
124
+ this.frontendApi = frontendApiFrom(options);
125
+ this.options = options;
126
+ const fetchImpl = options.fetchImpl ?? ((...args) => fetch(...args));
127
+ this.fapi = new fapi_1.FapiClient({ publishableKey, baseUrl: this.frontendApi, fetchImpl });
128
+ const doFetch = (0, dev_browser_1.withDevBrowser)(publishableKey, fetchImpl);
129
+ this.raw = (path, init = {}) => doFetch(`${this.frontendApi}${path}`, {
130
+ ...init,
131
+ credentials: 'include',
132
+ headers: {
133
+ 'x-publishable-key': publishableKey,
134
+ ...(init.body ? { 'content-type': 'application/json' } : {}),
135
+ ...init.headers,
136
+ },
137
+ });
138
+ }
139
+ signInUrl(signUp = false) {
140
+ if (signUp)
141
+ return this.options.signUpUrl ?? `${this.frontendApi}/hosted/sign-up`;
142
+ return this.options.signInUrl ?? `${this.frontendApi}/hosted/sign-in`;
143
+ }
144
+ /** Read the Frontend API client state (session, user, token). */
145
+ async load(force = false) {
146
+ if (!force && this.state && Date.now() - this.state.at < 2_000)
147
+ return this.state.body;
148
+ const response = await this.raw('/v1/client');
149
+ if (!response.ok)
150
+ throw new Error(`Atlas: could not read the session (HTTP ${response.status}).`);
151
+ const body = (await response.json());
152
+ this.state = { body, at: Date.now() };
153
+ if (body.session && body.jwt)
154
+ this.keepToken(body.jwt, body.session.id);
155
+ if (!body.session)
156
+ this.token = null;
157
+ return body;
158
+ }
159
+ keepToken(jwt, sessionId) {
160
+ const exp = Number(decodeJwtPayload(jwt)?.exp ?? 0) * 1000;
161
+ this.token = { jwt, exp, sessionId };
162
+ }
163
+ /** `checkSession()`: refresh the local view of the session; never throws. */
164
+ async checkSession() {
165
+ try {
166
+ await this.load(true);
167
+ }
168
+ catch {
169
+ // auth0-spa-js swallows login_required here too.
170
+ }
171
+ }
172
+ async isAuthenticated() {
173
+ const body = await this.load();
174
+ return Boolean(body.session && body.user);
175
+ }
176
+ async getUser() {
177
+ const body = await this.load();
178
+ return body.session ? auth0UserFromClient(body.user) : undefined;
179
+ }
180
+ async getIdTokenClaims() {
181
+ const jwt = await this.getTokenSilently().catch(() => null);
182
+ if (typeof jwt !== 'string')
183
+ return undefined;
184
+ const claims = decodeJwtPayload(jwt);
185
+ return claims ? { ...claims, __raw: jwt } : undefined;
186
+ }
187
+ async getTokenSilently(options = {}) {
188
+ const body = await this.load(options.cacheMode === 'off');
189
+ if (!body.session)
190
+ throw new Auth0CompatError('login_required', 'Login required');
191
+ let jwt = null;
192
+ let expiresIn = 0;
193
+ if (options.template) {
194
+ const t = await (0, fapi_1.getTemplateToken)(this.fapi, body.session.id, options.template);
195
+ if (!t)
196
+ throw new Auth0CompatError('login_required', `No token for template ${options.template}`);
197
+ jwt = t.jwt;
198
+ expiresIn = t.expiresIn;
199
+ }
200
+ else {
201
+ const usable = this.token && this.token.sessionId === body.session.id && this.token.exp - Date.now() > 10_000;
202
+ if (!usable || options.cacheMode === 'off') {
203
+ if (options.cacheMode === 'cache-only')
204
+ throw new Auth0CompatError('login_required', 'No cached token');
205
+ const response = await this.raw(`/v1/client/sessions/${encodeURIComponent(body.session.id)}/tokens`, { method: 'POST' });
206
+ if (!response.ok)
207
+ throw new Auth0CompatError('login_required', 'Login required');
208
+ const minted = (await response.json());
209
+ this.keepToken(minted.jwt, minted.session_id);
210
+ }
211
+ jwt = this.token.jwt;
212
+ expiresIn = Math.max(0, Math.floor((this.token.exp - Date.now()) / 1000));
213
+ }
214
+ return options.detailedResponse ? { access_token: jwt, id_token: jwt, expires_in: expiresIn } : jwt;
215
+ }
216
+ /** Sign in in a popup when needed, then return a token. */
217
+ async getTokenWithPopup(options = {}) {
218
+ if (!(await this.isAuthenticated()))
219
+ await this.loginWithPopup(options);
220
+ return this.getTokenSilently({ ...options, detailedResponse: false });
221
+ }
222
+ /**
223
+ * Navigate to sign-in. With `authorizationParams.connection` the user goes
224
+ * straight to that social provider; otherwise to the instance's hosted page.
225
+ * `appState` comes back from {@link handleRedirectCallback}.
226
+ */
227
+ async loginWithRedirect(options = {}) {
228
+ const params = options.authorizationParams ?? {};
229
+ const returnTo = params.redirect_uri ?? this.options.authorizationParams?.redirect_uri ?? currentHref();
230
+ if (options.appState !== undefined)
231
+ storage()?.setItem(APP_STATE_KEY, JSON.stringify(options.appState));
232
+ let url;
233
+ if (params.connection) {
234
+ const started = await (0, redirect_1.startOauthRedirect)(this.fapi, {
235
+ provider: CONNECTIONS[params.connection] ?? params.connection,
236
+ redirectUrl: returnTo ?? '/',
237
+ });
238
+ if (!started)
239
+ throw new Auth0CompatError('start_failed', `Could not start sign-in with ${params.connection}.`);
240
+ url = started.authorizationUrl;
241
+ }
242
+ else {
243
+ url = withRedirect(this.signInUrl(params.screen_hint === 'signup'), returnTo);
244
+ }
245
+ if (options.openUrl)
246
+ await options.openUrl(url);
247
+ else if (typeof window !== 'undefined')
248
+ window.location.assign(url);
249
+ }
250
+ /**
251
+ * Finish a redirect sign-in on the page you came back to: exchanges the
252
+ * one-time ticket in the URL (if any), removes it from the address bar, and
253
+ * returns the `appState` passed to `loginWithRedirect`.
254
+ */
255
+ async handleRedirectCallback(url) {
256
+ const href = url ?? currentHref() ?? '';
257
+ const search = href.includes('?') ? href.slice(href.indexOf('?')) : '';
258
+ const result = (0, redirect_1.readRedirectResult)(search.split('#')[0] ?? '');
259
+ if (result?.ticket) {
260
+ const response = await this.raw('/v1/client/tickets/exchange', {
261
+ method: 'POST',
262
+ body: JSON.stringify({ attempt_id: result.attemptId, ticket: result.ticket }),
263
+ });
264
+ if (!response.ok)
265
+ throw new Auth0CompatError('login_required', 'The sign-in could not be completed.');
266
+ }
267
+ else if (result?.status && result.status !== 'complete') {
268
+ throw new Auth0CompatError('login_required', `Sign-in needs another step (${result.status}).`);
269
+ }
270
+ if (!url && typeof window !== 'undefined' && result) {
271
+ window.history.replaceState({}, document.title, (0, redirect_1.stripRedirectParams)(window.location.href));
272
+ }
273
+ await this.load(true);
274
+ const raw = storage()?.getItem(APP_STATE_KEY);
275
+ storage()?.removeItem(APP_STATE_KEY);
276
+ let appState;
277
+ try {
278
+ appState = raw ? JSON.parse(raw) : undefined;
279
+ }
280
+ catch {
281
+ appState = undefined;
282
+ }
283
+ return appState === undefined ? {} : { appState };
284
+ }
285
+ /**
286
+ * Sign in in a popup: straight at a social provider with
287
+ * `authorizationParams.connection`, otherwise the hosted sign-in page (this
288
+ * waits until a session appears or the popup is closed, up to 5 minutes).
289
+ */
290
+ async loginWithPopup(options = {}) {
291
+ const params = options.authorizationParams ?? {};
292
+ if (params.connection) {
293
+ const outcome = await (0, redirect_1.startOauthPopup)(this.fapi, {
294
+ provider: CONNECTIONS[params.connection] ?? params.connection,
295
+ redirectUrl: currentHref() ?? '/',
296
+ });
297
+ if (outcome.blocked)
298
+ throw new Auth0CompatError('popup_blocked', 'The sign-in popup was blocked.');
299
+ if (outcome.ticket && outcome.attemptId) {
300
+ await this.raw('/v1/client/tickets/exchange', {
301
+ method: 'POST',
302
+ body: JSON.stringify({ attempt_id: outcome.attemptId, ticket: outcome.ticket }),
303
+ });
304
+ }
305
+ else if (!outcome.sessionDetected) {
306
+ throw new Auth0CompatError(outcome.error === 'popup_closed' ? 'popup_closed' : 'start_failed', outcome.error ?? 'Sign-in did not complete.');
307
+ }
308
+ await this.load(true);
309
+ return;
310
+ }
311
+ const popup = typeof window !== 'undefined' ? window.open(this.signInUrl(params.screen_hint === 'signup'), 'atlas-sign-in', 'width=500,height=650') : null;
312
+ if (!popup)
313
+ throw new Auth0CompatError('popup_blocked', 'The sign-in popup was blocked.');
314
+ const deadline = Date.now() + (options.timeoutInSeconds ?? 300) * 1000;
315
+ for (;;) {
316
+ await new Promise((r) => setTimeout(r, 1_000));
317
+ if (await this.isSignedInNow()) {
318
+ try {
319
+ popup.close();
320
+ }
321
+ catch {
322
+ /* cross-origin close */
323
+ }
324
+ return;
325
+ }
326
+ if (popup.closed)
327
+ throw new Auth0CompatError('popup_closed', 'The sign-in popup was closed.');
328
+ if (Date.now() > deadline)
329
+ throw new Auth0CompatError('timeout', 'Timed out waiting for sign-in.');
330
+ }
331
+ }
332
+ async isSignedInNow() {
333
+ try {
334
+ return Boolean((await this.load(true)).session);
335
+ }
336
+ catch {
337
+ return false;
338
+ }
339
+ }
340
+ /** Sign out (revokes the Atlas session), then go to `logoutParams.returnTo` (default: this site). */
341
+ async logout(options = {}) {
342
+ const body = this.state?.body ?? (await this.load().catch(() => null));
343
+ if (body?.session)
344
+ await (0, sign_out_1.revokeSession)(this.raw, body.session.id);
345
+ this.state = null;
346
+ this.token = null;
347
+ const url = options.logoutParams?.returnTo ?? (typeof window !== 'undefined' ? window.location.origin : '/');
348
+ if (options.openUrl === false)
349
+ return;
350
+ if (typeof options.openUrl === 'function')
351
+ await options.openUrl(url);
352
+ else if (typeof window !== 'undefined')
353
+ window.location.assign(url);
354
+ }
355
+ }
356
+ exports.Auth0CompatClient = Auth0CompatClient;
357
+ /** `createAuth0Client(options)`: a client that has already checked the session. */
358
+ async function createAuth0CompatClient(options) {
359
+ const client = new Auth0CompatClient(options);
360
+ await client.checkSession();
361
+ return client;
362
+ }
363
+ //# sourceMappingURL=compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.js","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { FapiClient } from './fapi';
2
+ /**
3
+ * Device sign-in (OAuth 2.0 Device Authorization Grant, RFC 8628) from YOUR app:
4
+ * the signed-in user types — or scans — the code their TV, console or CLI shows,
5
+ * and your own page approves it. The alternative to sending them to Atlas's
6
+ * hosted `/oauth2/device` page.
7
+ *
8
+ * const auth = await lookupDeviceAuthorization(client, typedCode);
9
+ * // show auth.client.name and auth.scopes, then:
10
+ * await approveDeviceAuthorization(client, auth); // or denyDeviceAuthorization
11
+ *
12
+ * The calls use the signed-in session (the cookie, or a native app's session
13
+ * token). When the application requires a recent re-authentication to approve a
14
+ * device (`requiresStepUp`), a stale session gets a
15
+ * {@link DeviceAuthorizationError} with `needsReverification` — re-authenticate
16
+ * (`reauthenticate()`), then approve again.
17
+ */
18
+ export interface DeviceAuthorizationScope {
19
+ scope: string;
20
+ /** A human description for the consent text. */
21
+ description: string;
22
+ }
23
+ export interface DeviceAuthorization {
24
+ object: 'device_authorization';
25
+ id: string;
26
+ /** The code as the device shows it, e.g. `WDJB-MJHT`. */
27
+ userCode: string;
28
+ status: 'pending' | 'approved' | 'denied';
29
+ client: {
30
+ clientId: string;
31
+ name: string;
32
+ logoUrl: string | null;
33
+ homepageUrl: string | null;
34
+ firstParty: boolean;
35
+ };
36
+ scopes: DeviceAuthorizationScope[];
37
+ /** The API the device asked for a token for, if any. */
38
+ audience: string | null;
39
+ /** Approving needs a recent re-authentication. */
40
+ requiresStepUp: boolean;
41
+ createdAt: number;
42
+ expiresAt: number;
43
+ }
44
+ /** A refused request. `code` is the server's stable error code (`NOT_FOUND`, `RATE_LIMITED`, `STEP_UP_REQUIRED`, …). */
45
+ export declare class DeviceAuthorizationError extends Error {
46
+ readonly code: string;
47
+ readonly status: number;
48
+ readonly param?: string;
49
+ readonly reason?: string;
50
+ readonly meta?: Record<string, unknown>;
51
+ constructor(status: number, code: string, message: string, param?: string, reason?: string, meta?: Record<string, unknown>);
52
+ /** True when approving needs a fresh re-authentication first. */
53
+ get needsReverification(): boolean;
54
+ /** True when the code is unknown, expired or already used. */
55
+ get isInvalidCode(): boolean;
56
+ }
57
+ /**
58
+ * Normalise what a person typed into the `XXXX-XXXX` form devices show:
59
+ * uppercase, spaces and dashes ignored. Returns the input unchanged when it is
60
+ * not 8 letters or digits, so the server answers "not valid".
61
+ */
62
+ export declare function formatUserCode(input: string): string;
63
+ /** Read a `user_code` from a verification URL the device displayed (`?user_code=`), if any. */
64
+ export declare function userCodeFromUrl(url: string | URL): string | null;
65
+ /** Look up a pending device sign-in by the code the device shows. */
66
+ export declare function lookupDeviceAuthorization(client: FapiClient, userCode: string): Promise<DeviceAuthorization>;
67
+ /** Approve the device sign-in for the signed-in user. The device's next poll receives its tokens. */
68
+ export declare function approveDeviceAuthorization(client: FapiClient, authorization: Pick<DeviceAuthorization, 'id' | 'userCode'>): Promise<DeviceAuthorization>;
69
+ /** Deny the device sign-in. The device's next poll is told `access_denied`. */
70
+ export declare function denyDeviceAuthorization(client: FapiClient, authorization: Pick<DeviceAuthorization, 'id' | 'userCode'>): Promise<DeviceAuthorization>;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeviceAuthorizationError = void 0;
4
+ exports.formatUserCode = formatUserCode;
5
+ exports.userCodeFromUrl = userCodeFromUrl;
6
+ exports.lookupDeviceAuthorization = lookupDeviceAuthorization;
7
+ exports.approveDeviceAuthorization = approveDeviceAuthorization;
8
+ exports.denyDeviceAuthorization = denyDeviceAuthorization;
9
+ /** A refused request. `code` is the server's stable error code (`NOT_FOUND`, `RATE_LIMITED`, `STEP_UP_REQUIRED`, …). */
10
+ class DeviceAuthorizationError extends Error {
11
+ code;
12
+ status;
13
+ param;
14
+ reason;
15
+ meta;
16
+ constructor(status, code, message, param, reason, meta) {
17
+ super(message);
18
+ this.name = 'DeviceAuthorizationError';
19
+ this.status = status;
20
+ this.code = code;
21
+ this.param = param;
22
+ if (reason)
23
+ this.reason = reason;
24
+ if (meta)
25
+ this.meta = meta;
26
+ }
27
+ /** True when approving needs a fresh re-authentication first. */
28
+ get needsReverification() {
29
+ return this.code === 'STEP_UP_REQUIRED';
30
+ }
31
+ /** True when the code is unknown, expired or already used. */
32
+ get isInvalidCode() {
33
+ return this.status === 404 || this.status === 409;
34
+ }
35
+ }
36
+ exports.DeviceAuthorizationError = DeviceAuthorizationError;
37
+ const BASE = '/v1/client/me/device_authorizations';
38
+ function fromWire(w) {
39
+ return {
40
+ object: 'device_authorization',
41
+ id: w.id,
42
+ userCode: w.user_code,
43
+ status: w.status,
44
+ client: {
45
+ clientId: w.client.client_id,
46
+ name: w.client.name,
47
+ logoUrl: w.client.logo_url ?? null,
48
+ homepageUrl: w.client.homepage_url ?? null,
49
+ firstParty: w.client.first_party === true,
50
+ },
51
+ scopes: w.scopes ?? [],
52
+ audience: w.audience ?? null,
53
+ requiresStepUp: w.requires_step_up === true,
54
+ createdAt: w.created_at,
55
+ expiresAt: w.expires_at,
56
+ };
57
+ }
58
+ async function call(client, path, body) {
59
+ const res = await client.request(path, { method: 'POST', body: JSON.stringify(body) });
60
+ if (!res.ok || !res.data) {
61
+ const first = res.errors[0];
62
+ throw new DeviceAuthorizationError(res.status, first?.code ?? 'UNKNOWN', first?.message ?? 'The request failed.', first?.param, first?.reason, first?.meta);
63
+ }
64
+ return fromWire(res.data);
65
+ }
66
+ /**
67
+ * Normalise what a person typed into the `XXXX-XXXX` form devices show:
68
+ * uppercase, spaces and dashes ignored. Returns the input unchanged when it is
69
+ * not 8 letters or digits, so the server answers "not valid".
70
+ */
71
+ function formatUserCode(input) {
72
+ const cleaned = input.toUpperCase().replace(/[^A-Z0-9]/g, '');
73
+ return cleaned.length === 8 ? `${cleaned.slice(0, 4)}-${cleaned.slice(4)}` : input.trim();
74
+ }
75
+ /** Read a `user_code` from a verification URL the device displayed (`?user_code=`), if any. */
76
+ function userCodeFromUrl(url) {
77
+ try {
78
+ const value = new URL(String(url)).searchParams.get('user_code');
79
+ return value ? formatUserCode(value) : null;
80
+ }
81
+ catch {
82
+ return null;
83
+ }
84
+ }
85
+ /** Look up a pending device sign-in by the code the device shows. */
86
+ async function lookupDeviceAuthorization(client, userCode) {
87
+ return call(client, `${BASE}/lookup`, { user_code: formatUserCode(userCode) });
88
+ }
89
+ /** Approve the device sign-in for the signed-in user. The device's next poll receives its tokens. */
90
+ async function approveDeviceAuthorization(client, authorization) {
91
+ return call(client, `${BASE}/${encodeURIComponent(authorization.id)}/approve`, { user_code: authorization.userCode });
92
+ }
93
+ /** Deny the device sign-in. The device's next poll is told `access_denied`. */
94
+ async function denyDeviceAuthorization(client, authorization) {
95
+ return call(client, `${BASE}/${encodeURIComponent(authorization.id)}/deny`, { user_code: authorization.userCode });
96
+ }
97
+ //# sourceMappingURL=device-authorization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../src/device-authorization.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Check an emailed one-time code WITHOUT using it up.
3
+ *
4
+ * Every email-code step has a `check` endpoint beside its `attempt` endpoint:
5
+ * the server answers whether the code is right and still live (and until when),
6
+ * and leaves it redeemable, so a form can show "code accepted" as the user
7
+ * types and only submit the step when they confirm. A wrong code spends one of
8
+ * the code's attempts exactly like a submission — checking is no way around the
9
+ * lockout — and the check endpoints share the credential-verify rate budget.
10
+ *
11
+ * sign-in first factor POST /v1/client/sign_ins/:id/check_first_factor
12
+ * sign-in second factor POST /v1/client/sign_ins/:id/check_second_factor
13
+ * sign-up verification POST /v1/client/sign_ups/:id/check_verification
14
+ * step-up POST /v1/client/me/step_up/check
15
+ * add-email verification POST /v1/client/me/email_addresses/:id/check_verification
16
+ */
17
+ import type { FapiClient, FapiResponse } from './fapi';
18
+ import { type AttemptView } from './attempt';
19
+ /** A right, live code. */
20
+ export interface EmailCodeCheck {
21
+ object: 'email_code_check';
22
+ valid: true;
23
+ /** When the code stops working (ISO 8601). */
24
+ expires_at: string;
25
+ /** Wrong entries left before the code is locked. */
26
+ attempts_remaining: number;
27
+ }
28
+ /** Where the code being checked belongs. */
29
+ export type EmailCodeTarget = {
30
+ kind: 'sign_in_first_factor';
31
+ attemptId: string;
32
+ } | {
33
+ kind: 'sign_in_second_factor';
34
+ attemptId: string;
35
+ } | {
36
+ kind: 'sign_up_verification';
37
+ attemptId: string;
38
+ } | {
39
+ kind: 'step_up';
40
+ } | {
41
+ kind: 'email_address';
42
+ emailAddressId: string;
43
+ };
44
+ /** The check endpoint and body for a target. */
45
+ export declare function emailCodeCheckRequest(target: EmailCodeTarget, code: string): {
46
+ path: string;
47
+ body: Record<string, unknown>;
48
+ };
49
+ /**
50
+ * Check a code. `ok` with `data` for a right, live code; otherwise the server's
51
+ * errors — `VERIFICATION_FAILED` (wrong, expired or unknown) or
52
+ * `TOO_MANY_ATTEMPTS` (the code is locked; request a new one).
53
+ */
54
+ export declare function checkEmailCode(client: FapiClient, target: EmailCodeTarget, code: string): Promise<FapiResponse<EmailCodeCheck>>;
55
+ /**
56
+ * The check target for the code step a flow is on, or null when the current
57
+ * step takes no emailed code. An emailed code on the first-factor step, the
58
+ * email second factor, and sign-up verification are covered.
59
+ */
60
+ export declare function emailCodeTargetForAttempt(attempt: AttemptView | null | undefined): EmailCodeTarget | null;