@orangecheck/auth-client 2.0.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 +46 -1
- package/dist/index.d.ts +46 -1
- package/dist/index.js +252 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +249 -40
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -3
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
68
|
-
const [account, setAccount] =
|
|
69
|
-
const [status, setStatus] =
|
|
70
|
-
const [error, setError] =
|
|
71
|
-
const refresh =
|
|
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
|
-
|
|
101
|
+
React4__namespace.useEffect(() => {
|
|
101
102
|
void refresh();
|
|
102
103
|
}, [refresh]);
|
|
103
|
-
const signOut =
|
|
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 =
|
|
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 =
|
|
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
|
|
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] =
|
|
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] =
|
|
167
|
-
const wrapRef =
|
|
168
|
-
|
|
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] =
|
|
492
|
-
const [highlighted, setHighlighted] =
|
|
493
|
-
const blurTimer =
|
|
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
|
-
|
|
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 =
|
|
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] =
|
|
624
|
-
const [highlighted, setHighlighted] =
|
|
625
|
-
const innerRef =
|
|
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 =
|
|
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
|
-
|
|
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] =
|
|
794
|
-
const handleSuccess =
|
|
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] =
|
|
903
|
-
const [error, setError] =
|
|
904
|
-
const [submitting, setSubmitting] =
|
|
905
|
-
const [stage, setStage] =
|
|
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] =
|
|
1005
|
-
const [email, setEmail] =
|
|
1006
|
-
const [emailError, setEmailError] =
|
|
1007
|
-
const [code, setCode] =
|
|
1008
|
-
const [codeError, setCodeError] =
|
|
1009
|
-
const [token, setToken] =
|
|
1010
|
-
const [submitting, setSubmitting] =
|
|
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
|