@orangecheck/auth-client 1.1.0 → 2.1.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/index.d.mts CHANGED
@@ -108,4 +108,49 @@ interface OcSignInProps {
108
108
  }
109
109
  declare function OcSignIn({ audience, returnTo, onSuccess, authOrigin, initialPath, paths, className, }: OcSignInProps): React.ReactElement;
110
110
 
111
- export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession };
111
+ interface WebAuthnCredentialPublic {
112
+ id: string;
113
+ label: string;
114
+ authenticator_type: 'platform' | 'cross-platform' | 'unknown';
115
+ transports: string[];
116
+ user_verified: boolean;
117
+ created_at: string;
118
+ last_used_at: string | null;
119
+ }
120
+ type WebAuthnRegisterStatus = 'idle' | 'requesting-options' | 'authenticating' | 'verifying' | 'success' | 'error';
121
+ type WebAuthnAssertionStatus = WebAuthnRegisterStatus;
122
+ type WebAuthnListStatus = 'loading' | 'ready' | 'error';
123
+ interface UseHostOptions {
124
+ authOrigin?: string;
125
+ }
126
+ interface UseWebAuthnRegisterReturn {
127
+ status: WebAuthnRegisterStatus;
128
+ error: Error | null;
129
+ register: (args?: {
130
+ label?: string;
131
+ }) => Promise<WebAuthnCredentialPublic | null>;
132
+ reset: () => void;
133
+ }
134
+ declare function useWebAuthnRegister(opts?: UseHostOptions): UseWebAuthnRegisterReturn;
135
+ interface UseWebAuthnListReturn {
136
+ status: WebAuthnListStatus;
137
+ credentials: WebAuthnCredentialPublic[];
138
+ error: Error | null;
139
+ refetch: () => Promise<void>;
140
+ rename: (id: string, label: string) => Promise<WebAuthnCredentialPublic | null>;
141
+ remove: (id: string) => Promise<boolean>;
142
+ }
143
+ declare function useWebAuthnList(opts?: UseHostOptions): UseWebAuthnListReturn;
144
+ interface UseStepUpAuthReturn {
145
+ status: WebAuthnAssertionStatus;
146
+ error: Error | null;
147
+ stepUp: (args: {
148
+ purpose: string;
149
+ }) => Promise<{
150
+ step_up_at: number;
151
+ } | null>;
152
+ reset: () => void;
153
+ }
154
+ declare function useStepUpAuth(opts?: UseHostOptions): UseStepUpAuthReturn;
155
+
156
+ export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterStatus, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
package/dist/index.d.ts CHANGED
@@ -108,4 +108,49 @@ interface OcSignInProps {
108
108
  }
109
109
  declare function OcSignIn({ audience, returnTo, onSuccess, authOrigin, initialPath, paths, className, }: OcSignInProps): React.ReactElement;
110
110
 
111
- export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession };
111
+ interface WebAuthnCredentialPublic {
112
+ id: string;
113
+ label: string;
114
+ authenticator_type: 'platform' | 'cross-platform' | 'unknown';
115
+ transports: string[];
116
+ user_verified: boolean;
117
+ created_at: string;
118
+ last_used_at: string | null;
119
+ }
120
+ type WebAuthnRegisterStatus = 'idle' | 'requesting-options' | 'authenticating' | 'verifying' | 'success' | 'error';
121
+ type WebAuthnAssertionStatus = WebAuthnRegisterStatus;
122
+ type WebAuthnListStatus = 'loading' | 'ready' | 'error';
123
+ interface UseHostOptions {
124
+ authOrigin?: string;
125
+ }
126
+ interface UseWebAuthnRegisterReturn {
127
+ status: WebAuthnRegisterStatus;
128
+ error: Error | null;
129
+ register: (args?: {
130
+ label?: string;
131
+ }) => Promise<WebAuthnCredentialPublic | null>;
132
+ reset: () => void;
133
+ }
134
+ declare function useWebAuthnRegister(opts?: UseHostOptions): UseWebAuthnRegisterReturn;
135
+ interface UseWebAuthnListReturn {
136
+ status: WebAuthnListStatus;
137
+ credentials: WebAuthnCredentialPublic[];
138
+ error: Error | null;
139
+ refetch: () => Promise<void>;
140
+ rename: (id: string, label: string) => Promise<WebAuthnCredentialPublic | null>;
141
+ remove: (id: string) => Promise<boolean>;
142
+ }
143
+ declare function useWebAuthnList(opts?: UseHostOptions): UseWebAuthnListReturn;
144
+ interface UseStepUpAuthReturn {
145
+ status: WebAuthnAssertionStatus;
146
+ error: Error | null;
147
+ stepUp: (args: {
148
+ purpose: string;
149
+ }) => Promise<{
150
+ step_up_at: number;
151
+ } | null>;
152
+ reset: () => void;
153
+ }
154
+ declare function useStepUpAuth(opts?: UseHostOptions): UseStepUpAuthReturn;
155
+
156
+ export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterStatus, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var React2 = require('react');
3
+ var React4 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var browser = require('@simplewebauthn/browser');
5
6
 
6
7
  function _interopNamespace(e) {
7
8
  if (e && e.__esModule) return e;
@@ -21,7 +22,7 @@ function _interopNamespace(e) {
21
22
  return Object.freeze(n);
22
23
  }
23
24
 
24
- var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
25
+ var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
25
26
 
26
27
  // src/provider.tsx
27
28
 
@@ -42,7 +43,7 @@ function buildSignInUrl(cfg, returnTo) {
42
43
  u.searchParams.set("return_to", returnTo);
43
44
  return u.toString();
44
45
  }
45
- var SessionContext = React2__namespace.createContext(null);
46
+ var SessionContext = React4__namespace.createContext(null);
46
47
  function normalizeAccount(raw) {
47
48
  if (!raw) return null;
48
49
  const didOc = raw.did_oc ?? raw.didOc;
@@ -64,11 +65,11 @@ function OcSessionProvider({
64
65
  config,
65
66
  defaultReturnTo
66
67
  }) {
67
- const cfg = React2__namespace.useMemo(() => resolveConfig(config), [config]);
68
- const [account, setAccount] = React2__namespace.useState(null);
69
- const [status, setStatus] = React2__namespace.useState("loading");
70
- const [error, setError] = React2__namespace.useState(null);
71
- const refresh = React2__namespace.useCallback(async () => {
68
+ const cfg = React4__namespace.useMemo(() => resolveConfig(config), [config]);
69
+ const [account, setAccount] = React4__namespace.useState(null);
70
+ const [status, setStatus] = React4__namespace.useState("loading");
71
+ const [error, setError] = React4__namespace.useState(null);
72
+ const refresh = React4__namespace.useCallback(async () => {
72
73
  if (typeof window === "undefined") return;
73
74
  try {
74
75
  const res = await fetch(cfg.mePath, {
@@ -97,10 +98,10 @@ function OcSessionProvider({
97
98
  setError(err instanceof Error ? err : new Error(String(err)));
98
99
  }
99
100
  }, [cfg.mePath]);
100
- React2__namespace.useEffect(() => {
101
+ React4__namespace.useEffect(() => {
101
102
  void refresh();
102
103
  }, [refresh]);
103
- const signOut = React2__namespace.useCallback(async () => {
104
+ const signOut = React4__namespace.useCallback(async () => {
104
105
  try {
105
106
  await fetch(`${cfg.authOrigin}${cfg.logoutPath}`, {
106
107
  method: "POST",
@@ -111,7 +112,7 @@ function OcSessionProvider({
111
112
  setAccount(null);
112
113
  setStatus("anonymous");
113
114
  }, [cfg.authOrigin, cfg.logoutPath]);
114
- const value = React2__namespace.useMemo(() => {
115
+ const value = React4__namespace.useMemo(() => {
115
116
  const returnTo = defaultReturnTo ?? (typeof window !== "undefined" ? window.location.href : void 0);
116
117
  return {
117
118
  status,
@@ -125,7 +126,7 @@ function OcSessionProvider({
125
126
  return /* @__PURE__ */ jsxRuntime.jsx(SessionContext.Provider, { value, children });
126
127
  }
127
128
  function useOcSession() {
128
- const ctx = React2__namespace.useContext(SessionContext);
129
+ const ctx = React4__namespace.useContext(SessionContext);
129
130
  if (!ctx) {
130
131
  throw new Error(
131
132
  "[@orangecheck/auth-client] useOcSession() must be called inside <OcSessionProvider>"
@@ -134,7 +135,7 @@ function useOcSession() {
134
135
  return ctx;
135
136
  }
136
137
  function useOptionalOcSession() {
137
- return React2__namespace.useContext(SessionContext);
138
+ return React4__namespace.useContext(SessionContext);
138
139
  }
139
140
  function shortenAddress(addr) {
140
141
  if (addr.length <= 12) return addr;
@@ -149,7 +150,7 @@ function isPrefixOf(value, target) {
149
150
  }
150
151
  var listboxIdCounter = 0;
151
152
  function useUniqueId(prefix) {
152
- const [id] = React2__namespace.useState(() => `${prefix}-${++listboxIdCounter}`);
153
+ const [id] = React4__namespace.useState(() => `${prefix}-${++listboxIdCounter}`);
153
154
  return id;
154
155
  }
155
156
  function OcAccountChip({
@@ -163,9 +164,9 @@ function OcAccountChip({
163
164
  }) {
164
165
  const { status, account, signInUrl: sessionSignInUrl, signOut } = useOcSession();
165
166
  const signInUrl = signInUrlOverride ?? sessionSignInUrl;
166
- const [open, setOpen] = React2__namespace.useState(false);
167
- const wrapRef = React2__namespace.useRef(null);
168
- React2__namespace.useEffect(() => {
167
+ const [open, setOpen] = React4__namespace.useState(false);
168
+ const wrapRef = React4__namespace.useRef(null);
169
+ React4__namespace.useEffect(() => {
169
170
  if (!open) return;
170
171
  function handleClickOutside(e) {
171
172
  if (wrapRef.current && !wrapRef.current.contains(e.target)) {
@@ -488,9 +489,9 @@ function useOcAddressSuggestion(options) {
488
489
  } = options;
489
490
  const { status, account } = useOcSession();
490
491
  const sessionAddress = status === "authenticated" ? account?.primaryBtc ?? null : null;
491
- const [open, setOpen] = React2__namespace.useState(false);
492
- const [highlighted, setHighlighted] = React2__namespace.useState(false);
493
- const blurTimer = React2__namespace.useRef(null);
492
+ const [open, setOpen] = React4__namespace.useState(false);
493
+ const [highlighted, setHighlighted] = React4__namespace.useState(false);
494
+ const blurTimer = React4__namespace.useRef(null);
494
495
  const listboxId = useUniqueId("oc-addr-listbox");
495
496
  const optionId = `${listboxId}-opt`;
496
497
  const valueMatchesSession = sessionAddress != null && value.toLowerCase() === sessionAddress.toLowerCase();
@@ -502,7 +503,7 @@ function useOcAddressSuggestion(options) {
502
503
  setOpen(false);
503
504
  setHighlighted(false);
504
505
  }
505
- React2__namespace.useEffect(() => {
506
+ React4__namespace.useEffect(() => {
506
507
  return () => {
507
508
  if (blurTimer.current != null) window.clearTimeout(blurTimer.current);
508
509
  };
@@ -605,7 +606,7 @@ function useOcAddressSuggestion(options) {
605
606
  ) : null;
606
607
  return { inputProps, popover };
607
608
  }
608
- var OcAddressInput = React2__namespace.forwardRef(
609
+ var OcAddressInput = React4__namespace.forwardRef(
609
610
  function OcAddressInput2({
610
611
  value,
611
612
  onValueChange,
@@ -620,15 +621,15 @@ var OcAddressInput = React2__namespace.forwardRef(
620
621
  }, forwardedRef) {
621
622
  const { status, account } = useOcSession();
622
623
  const sessionAddress = status === "authenticated" ? account?.primaryBtc ?? null : null;
623
- const [open, setOpen] = React2__namespace.useState(false);
624
- const [highlighted, setHighlighted] = React2__namespace.useState(false);
625
- const innerRef = React2__namespace.useRef(null);
624
+ const [open, setOpen] = React4__namespace.useState(false);
625
+ const [highlighted, setHighlighted] = React4__namespace.useState(false);
626
+ const innerRef = React4__namespace.useRef(null);
626
627
  const setRef = (node) => {
627
628
  innerRef.current = node;
628
629
  if (typeof forwardedRef === "function") forwardedRef(node);
629
630
  else if (forwardedRef) forwardedRef.current = node;
630
631
  };
631
- const blurTimer = React2__namespace.useRef(null);
632
+ const blurTimer = React4__namespace.useRef(null);
632
633
  const listboxId = useUniqueId("oc-addr-listbox");
633
634
  const optionId = `${listboxId}-opt`;
634
635
  const valueMatchesSession = sessionAddress != null && value.toLowerCase() === sessionAddress.toLowerCase();
@@ -675,7 +676,7 @@ var OcAddressInput = React2__namespace.forwardRef(
675
676
  }
676
677
  onKeyDown?.(e);
677
678
  }
678
- React2__namespace.useEffect(() => {
679
+ React4__namespace.useEffect(() => {
679
680
  return () => {
680
681
  if (blurTimer.current != null) window.clearTimeout(blurTimer.current);
681
682
  };
@@ -790,8 +791,8 @@ function OcSignIn({
790
791
  const walletEnabled = paths?.wallet ?? true;
791
792
  const emailEnabled = paths?.email ?? true;
792
793
  const safeReturn = safeReturnTo(returnTo);
793
- const [path, setPath] = React2__namespace.useState(initialPath);
794
- const handleSuccess = React2__namespace.useCallback(
794
+ const [path, setPath] = React4__namespace.useState(initialPath);
795
+ const handleSuccess = React4__namespace.useCallback(
795
796
  (account) => {
796
797
  if (onSuccess) {
797
798
  onSuccess(account);
@@ -899,10 +900,10 @@ function SigninTab({
899
900
  );
900
901
  }
901
902
  function WalletFlow({ authOrigin, audience, onSuccess }) {
902
- const [address, setAddress] = React2__namespace.useState("");
903
- const [error, setError] = React2__namespace.useState(null);
904
- const [submitting, setSubmitting] = React2__namespace.useState(false);
905
- const [stage, setStage] = React2__namespace.useState("enter");
903
+ const [address, setAddress] = React4__namespace.useState("");
904
+ const [error, setError] = React4__namespace.useState(null);
905
+ const [submitting, setSubmitting] = React4__namespace.useState(false);
906
+ const [stage, setStage] = React4__namespace.useState("enter");
906
907
  async function signIn(e) {
907
908
  e.preventDefault();
908
909
  const addr = address.trim();
@@ -1001,13 +1002,13 @@ function WalletFlow({ authOrigin, audience, onSuccess }) {
1001
1002
  ] });
1002
1003
  }
1003
1004
  function EmailFlow({ authOrigin, onSuccess }) {
1004
- const [stage, setStage] = React2__namespace.useState("enter");
1005
- const [email, setEmail] = React2__namespace.useState("");
1006
- const [emailError, setEmailError] = React2__namespace.useState(null);
1007
- const [code, setCode] = React2__namespace.useState("");
1008
- const [codeError, setCodeError] = React2__namespace.useState(null);
1009
- const [token, setToken] = React2__namespace.useState(null);
1010
- const [submitting, setSubmitting] = React2__namespace.useState(false);
1005
+ const [stage, setStage] = React4__namespace.useState("enter");
1006
+ const [email, setEmail] = React4__namespace.useState("");
1007
+ const [emailError, setEmailError] = React4__namespace.useState(null);
1008
+ const [code, setCode] = React4__namespace.useState("");
1009
+ const [codeError, setCodeError] = React4__namespace.useState(null);
1010
+ const [token, setToken] = React4__namespace.useState(null);
1011
+ const [submitting, setSubmitting] = React4__namespace.useState(false);
1011
1012
  async function start(e) {
1012
1013
  e.preventDefault();
1013
1014
  const trimmed = email.trim().toLowerCase();
@@ -1271,6 +1272,214 @@ function Hint({ children }) {
1271
1272
  }
1272
1273
  );
1273
1274
  }
1275
+ function resolveAuthOrigin(opts) {
1276
+ if (!opts) return resolveConfig(void 0).authOrigin;
1277
+ return resolveConfig(opts).authOrigin;
1278
+ }
1279
+ function isAbortError(err) {
1280
+ if (!(err instanceof Error)) return false;
1281
+ return /NotAllowed|aborted|cancel|user cancelled/i.test(err.message);
1282
+ }
1283
+ function useWebAuthnRegister(opts) {
1284
+ const authOrigin = resolveAuthOrigin(opts);
1285
+ const [status, setStatus] = React4__namespace.useState("idle");
1286
+ const [error, setError] = React4__namespace.useState(null);
1287
+ const reset = React4__namespace.useCallback(() => {
1288
+ setStatus("idle");
1289
+ setError(null);
1290
+ }, []);
1291
+ const register = React4__namespace.useCallback(
1292
+ async (args) => {
1293
+ setError(null);
1294
+ setStatus("requesting-options");
1295
+ try {
1296
+ const optsRes = await fetch(`${authOrigin}/api/auth/webauthn/register/options`, {
1297
+ method: "POST",
1298
+ credentials: "include",
1299
+ headers: { "Content-Type": "application/json" },
1300
+ body: JSON.stringify({ label: args?.label })
1301
+ });
1302
+ const optsBody = await optsRes.json();
1303
+ if (!optsRes.ok || !optsBody.ok || !optsBody.options || !optsBody.challenge_token) {
1304
+ throw new Error(optsBody.reason ?? `options_failed_${optsRes.status}`);
1305
+ }
1306
+ setStatus("authenticating");
1307
+ const attestation = await browser.startRegistration({
1308
+ optionsJSON: optsBody.options
1309
+ });
1310
+ setStatus("verifying");
1311
+ const verifyRes = await fetch(`${authOrigin}/api/auth/webauthn/register/verify`, {
1312
+ method: "POST",
1313
+ credentials: "include",
1314
+ headers: { "Content-Type": "application/json" },
1315
+ body: JSON.stringify({
1316
+ challenge_token: optsBody.challenge_token,
1317
+ response: attestation,
1318
+ label: args?.label
1319
+ })
1320
+ });
1321
+ const verifyBody = await verifyRes.json();
1322
+ if (!verifyRes.ok || !verifyBody.ok || !verifyBody.credential) {
1323
+ throw new Error(verifyBody.reason ?? `verify_failed_${verifyRes.status}`);
1324
+ }
1325
+ setStatus("success");
1326
+ return verifyBody.credential;
1327
+ } catch (e) {
1328
+ const err = e instanceof Error ? e : new Error(String(e));
1329
+ setError(err);
1330
+ setStatus("error");
1331
+ if (isAbortError(err)) {
1332
+ setError(new Error("cancelled"));
1333
+ }
1334
+ return null;
1335
+ }
1336
+ },
1337
+ [authOrigin]
1338
+ );
1339
+ return { status, error, register, reset };
1340
+ }
1341
+ function useWebAuthnList(opts) {
1342
+ const authOrigin = resolveAuthOrigin(opts);
1343
+ const { status: sessionStatus } = useOcSession();
1344
+ const [credentials, setCredentials] = React4__namespace.useState([]);
1345
+ const [status, setStatus] = React4__namespace.useState("loading");
1346
+ const [error, setError] = React4__namespace.useState(null);
1347
+ const refetch = React4__namespace.useCallback(async () => {
1348
+ setError(null);
1349
+ if (sessionStatus !== "authenticated") {
1350
+ setCredentials([]);
1351
+ setStatus("ready");
1352
+ return;
1353
+ }
1354
+ setStatus("loading");
1355
+ try {
1356
+ const r = await fetch(`${authOrigin}/api/auth/webauthn/credentials`, {
1357
+ credentials: "include"
1358
+ });
1359
+ if (r.status === 401) {
1360
+ setCredentials([]);
1361
+ setStatus("ready");
1362
+ return;
1363
+ }
1364
+ const j = await r.json();
1365
+ if (!j.ok || !j.credentials) {
1366
+ throw new Error(j.reason ?? "list_failed");
1367
+ }
1368
+ setCredentials(j.credentials);
1369
+ setStatus("ready");
1370
+ } catch (e) {
1371
+ setError(e instanceof Error ? e : new Error(String(e)));
1372
+ setStatus("error");
1373
+ }
1374
+ }, [authOrigin, sessionStatus]);
1375
+ React4__namespace.useEffect(() => {
1376
+ void refetch();
1377
+ }, [refetch]);
1378
+ const rename = React4__namespace.useCallback(
1379
+ async (id, label) => {
1380
+ try {
1381
+ const r = await fetch(`${authOrigin}/api/auth/webauthn/credentials/${id}`, {
1382
+ method: "PATCH",
1383
+ credentials: "include",
1384
+ headers: { "Content-Type": "application/json" },
1385
+ body: JSON.stringify({ label })
1386
+ });
1387
+ const j = await r.json();
1388
+ if (!j.ok || !j.credential) {
1389
+ setError(new Error(j.reason ?? "rename_failed"));
1390
+ return null;
1391
+ }
1392
+ await refetch();
1393
+ return j.credential;
1394
+ } catch (e) {
1395
+ setError(e instanceof Error ? e : new Error(String(e)));
1396
+ return null;
1397
+ }
1398
+ },
1399
+ [authOrigin, refetch]
1400
+ );
1401
+ const remove = React4__namespace.useCallback(
1402
+ async (id) => {
1403
+ try {
1404
+ const r = await fetch(`${authOrigin}/api/auth/webauthn/credentials/${id}`, {
1405
+ method: "DELETE",
1406
+ credentials: "include"
1407
+ });
1408
+ const j = await r.json();
1409
+ if (!j.ok) {
1410
+ setError(new Error(j.reason ?? "delete_failed"));
1411
+ return false;
1412
+ }
1413
+ await refetch();
1414
+ return true;
1415
+ } catch (e) {
1416
+ setError(e instanceof Error ? e : new Error(String(e)));
1417
+ return false;
1418
+ }
1419
+ },
1420
+ [authOrigin, refetch]
1421
+ );
1422
+ return { status, credentials, error, refetch, rename, remove };
1423
+ }
1424
+ function useStepUpAuth(opts) {
1425
+ const authOrigin = resolveAuthOrigin(opts);
1426
+ const { refresh } = useOcSession();
1427
+ const [status, setStatus] = React4__namespace.useState("idle");
1428
+ const [error, setError] = React4__namespace.useState(null);
1429
+ const reset = React4__namespace.useCallback(() => {
1430
+ setStatus("idle");
1431
+ setError(null);
1432
+ }, []);
1433
+ const stepUp = React4__namespace.useCallback(
1434
+ async (args) => {
1435
+ setError(null);
1436
+ setStatus("requesting-options");
1437
+ try {
1438
+ const optsRes = await fetch(`${authOrigin}/api/auth/webauthn/assertion/options`, {
1439
+ method: "POST",
1440
+ credentials: "include",
1441
+ headers: { "Content-Type": "application/json" },
1442
+ body: JSON.stringify({ purpose: args.purpose })
1443
+ });
1444
+ const optsBody = await optsRes.json();
1445
+ if (!optsRes.ok || !optsBody.ok || !optsBody.options || !optsBody.challenge_token) {
1446
+ throw new Error(optsBody.reason ?? `options_failed_${optsRes.status}`);
1447
+ }
1448
+ setStatus("authenticating");
1449
+ const assertion = await browser.startAuthentication({
1450
+ optionsJSON: optsBody.options
1451
+ });
1452
+ setStatus("verifying");
1453
+ const verifyRes = await fetch(
1454
+ `${authOrigin}/api/auth/webauthn/assertion/verify`,
1455
+ {
1456
+ method: "POST",
1457
+ credentials: "include",
1458
+ headers: { "Content-Type": "application/json" },
1459
+ body: JSON.stringify({
1460
+ challenge_token: optsBody.challenge_token,
1461
+ response: assertion
1462
+ })
1463
+ }
1464
+ );
1465
+ const verifyBody = await verifyRes.json();
1466
+ if (!verifyRes.ok || !verifyBody.ok || typeof verifyBody.step_up_at !== "number") {
1467
+ throw new Error(verifyBody.reason ?? `verify_failed_${verifyRes.status}`);
1468
+ }
1469
+ await refresh();
1470
+ setStatus("success");
1471
+ return { step_up_at: verifyBody.step_up_at };
1472
+ } catch (e) {
1473
+ const err = isAbortError(e) ? new Error("cancelled") : e instanceof Error ? e : new Error(String(e));
1474
+ setError(err);
1475
+ setStatus("error");
1476
+ return null;
1477
+ }
1478
+ },
1479
+ [authOrigin, refresh]
1480
+ );
1481
+ return { status, error, stepUp, reset };
1482
+ }
1274
1483
 
1275
1484
  exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
1276
1485
  exports.OcAccountChip = OcAccountChip;
@@ -1283,5 +1492,8 @@ exports.buildSignInUrl = buildSignInUrl;
1283
1492
  exports.useOcAddressSuggestion = useOcAddressSuggestion;
1284
1493
  exports.useOcSession = useOcSession;
1285
1494
  exports.useOptionalOcSession = useOptionalOcSession;
1495
+ exports.useStepUpAuth = useStepUpAuth;
1496
+ exports.useWebAuthnList = useWebAuthnList;
1497
+ exports.useWebAuthnRegister = useWebAuthnRegister;
1286
1498
  //# sourceMappingURL=index.js.map
1287
1499
  //# sourceMappingURL=index.js.map