@schemavaults/auth-react-provider 0.10.37 → 0.11.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.
@@ -2,6 +2,8 @@ export { useAuth } from "./use-auth";
2
2
  export type * from "./use-auth";
3
3
  export { useCurrentUser } from "./use-current-user";
4
4
  export type * from "./use-current-user";
5
+ export { useCurrentUserWithRevalidation } from "./use-current-user-swr";
6
+ export type * from "./use-current-user-swr";
5
7
  export { useAdmin } from "./use-admin";
6
8
  export type * from "./use-admin";
7
9
  export { useAppEnvironment } from "./use-app-environment";
@@ -24,3 +26,7 @@ export { useDefaultAccessTokenAudiences } from "./use-default-access-token-audie
24
26
  export { useAutoReacquireDefaultAccessTokens } from "./use-auto-reacquire-default-access-tokens";
25
27
  export { useOnLogout } from "./use-on-logout";
26
28
  export type * from "./use-on-logout";
29
+ export { useMfaStatusSwr } from "./use-mfa-status-swr";
30
+ export type * from "./use-mfa-status-swr";
31
+ export { useMfa } from "./use-mfa";
32
+ export type * from "./use-mfa";
@@ -1,5 +1,6 @@
1
1
  export { useAuth } from "./use-auth";
2
2
  export { useCurrentUser } from "./use-current-user";
3
+ export { useCurrentUserWithRevalidation } from "./use-current-user-swr";
3
4
  export { useAdmin } from "./use-admin";
4
5
  export { useAppEnvironment } from "./use-app-environment";
5
6
  export { useTradeAuthorizationCodeForTokensEffect } from "./use-trade-authorization-code-for-tokens";
@@ -13,4 +14,6 @@ export { useIsAuthServer } from "./use-is-auth-server";
13
14
  export { useDefaultAccessTokenAudiences } from "./use-default-access-token-audiences";
14
15
  export { useAutoReacquireDefaultAccessTokens } from "./use-auto-reacquire-default-access-tokens";
15
16
  export { useOnLogout } from "./use-on-logout";
17
+ export { useMfaStatusSwr } from "./use-mfa-status-swr";
18
+ export { useMfa } from "./use-mfa";
16
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG1D,OAAO,EAAE,wCAAwC,EAAE,MAAM,2CAA2C,CAAC;AAGrG,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAG5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAG/E,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AAGrF,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAEtF,OAAO,EAAE,mCAAmC,EAAE,MAAM,4CAA4C,CAAC;AAEjG,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAGxE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG1D,OAAO,EAAE,wCAAwC,EAAE,MAAM,2CAA2C,CAAC;AAGrG,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAG5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAG/E,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AAGrF,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAEtF,OAAO,EAAE,mCAAmC,EAAE,MAAM,4CAA4C,CAAC;AAEjG,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC"}
@@ -5,6 +5,10 @@ import { useAppEnvironment, } from "./use-app-environment";
5
5
  import { useDebugWithSpecifiedBooleanOrLookupDefault } from "./use-debug";
6
6
  export function useAuthClientStateWatcher({ onAuthStateChanged, ...opts }) {
7
7
  const auth = useAuth();
8
+ const ready = auth.ready;
9
+ const clientRef = auth.ready
10
+ ? auth.client
11
+ : null;
8
12
  const environment = useAppEnvironment();
9
13
  const debug = useDebugWithSpecifiedBooleanOrLookupDefault(environment, opts.debug);
10
14
  const handleAuthSDKStateChangeEvent = useEffectEvent(async function handleAuthSDKStateChangeEvent() {
@@ -12,10 +16,10 @@ export function useAuthClientStateWatcher({ onAuthStateChanged, ...opts }) {
12
16
  console.log("[useAuthClientStateWatcher] Auth SDK state changed.");
13
17
  }
14
18
  try {
15
- if (!auth.ready) {
19
+ if (!ready || !clientRef) {
16
20
  throw new Error("Cannot handle auth SDK state change event when auth client is not initialized");
17
21
  }
18
- const authClient = auth.client.current;
22
+ const authClient = clientRef.current;
19
23
  if (!authClient) {
20
24
  if (debug) {
21
25
  console.warn("[useAuthClientStateWatcher] Auth client is null.");
@@ -42,13 +46,13 @@ export function useAuthClientStateWatcher({ onAuthStateChanged, ...opts }) {
42
46
  }); // end of handleAuthSDKStateChangeEvent)
43
47
  // Attach an auth-state change listener to the auth client
44
48
  useEffect(() => {
45
- if (!auth.ready) {
49
+ if (!ready || !clientRef) {
46
50
  if (debug) {
47
51
  console.log("[useAuthClientStateWatcher] Auth client not ready, skipping...");
48
52
  }
49
53
  return;
50
54
  }
51
- const authClientRef = auth.client;
55
+ const authClientRef = clientRef;
52
56
  if (authClientRef.current) {
53
57
  if (debug) {
54
58
  console.log("[useAuthClientStateWatcher] Adding auth state change listener...");
@@ -79,6 +83,6 @@ export function useAuthClientStateWatcher({ onAuthStateChanged, ...opts }) {
79
83
  };
80
84
  return unsubscribe;
81
85
  }
82
- }, [auth, debug]);
86
+ }, [ready, clientRef, debug]);
83
87
  }
84
88
  //# sourceMappingURL=use-auth-client-state-watcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-auth-client-state-watcher.js","sourceRoot":"","sources":["../../src/hooks/use-auth-client-state-watcher.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-auth-client-state-watcher.js","sourceRoot":"","sources":["../../src/hooks/use-auth-client-state-watcher.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { UserData } from "@schemavaults/auth-common";
2
+ /**
3
+ * @name useCurrentUserWithRevalidation
4
+ * @description Like {@link useCurrentUser}, but additionally revalidates the
5
+ * current user against the auth server's `/api/auth/whoami` endpoint on an
6
+ * interval and on window focus. The in-memory auth client state remains the
7
+ * primary source of truth so login/logout transitions propagate instantly; the
8
+ * SWR layer serves as a self-healing fallback that picks up server-side role
9
+ * changes without a page refresh.
10
+ */
11
+ export declare function useCurrentUserWithRevalidation(): UserData | null;
12
+ export default useCurrentUserWithRevalidation;
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import useSWR from "swr";
3
+ import useAuth from "./use-auth";
4
+ import useAppId from "./use-app-id";
5
+ import useCurrentUser from "./use-current-user";
6
+ const WHOAMI_REFRESH_INTERVAL_MS = 60_000;
7
+ const WHOAMI_DEDUPING_INTERVAL_MS = 15_000;
8
+ /**
9
+ * @name useCurrentUserWithRevalidation
10
+ * @description Like {@link useCurrentUser}, but additionally revalidates the
11
+ * current user against the auth server's `/api/auth/whoami` endpoint on an
12
+ * interval and on window focus. The in-memory auth client state remains the
13
+ * primary source of truth so login/logout transitions propagate instantly; the
14
+ * SWR layer serves as a self-healing fallback that picks up server-side role
15
+ * changes without a page refresh.
16
+ */
17
+ export function useCurrentUserWithRevalidation() {
18
+ const inMemoryUser = useCurrentUser();
19
+ const auth = useAuth();
20
+ const app_id = useAppId();
21
+ const clientRef = auth.ready ? auth.client : null;
22
+ const enabled = !!(auth.ready && clientRef?.current && inMemoryUser);
23
+ const { data: revalidatedUser } = useSWR(enabled ? `/api/auth/whoami/${app_id}` : null, async () => {
24
+ const authClient = clientRef?.current ?? null;
25
+ if (!authClient) {
26
+ return null;
27
+ }
28
+ return await authClient.checkIfAuthenticatedWithServer();
29
+ }, {
30
+ refreshInterval: WHOAMI_REFRESH_INTERVAL_MS,
31
+ dedupingInterval: WHOAMI_DEDUPING_INTERVAL_MS,
32
+ revalidateOnFocus: true,
33
+ fallbackData: inMemoryUser,
34
+ });
35
+ return inMemoryUser ?? revalidatedUser ?? null;
36
+ }
37
+ export default useCurrentUserWithRevalidation;
38
+ //# sourceMappingURL=use-current-user-swr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-current-user-swr.js","sourceRoot":"","sources":["../../src/hooks/use-current-user-swr.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,OAAO,MAAM,MAAM,KAAK,CAAC;AACzB,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,QAAQ,MAAM,oBAAoB,CAAC;AAC1C,OAAO,cAAc,MAAM,0BAA0B,CAAC;AAEtD,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAC1C,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAE3C;;;;;;;;GAQG;AACH,MAAM,UAAU,8BAA8B;IAC5C,MAAM,YAAY,GAAG,cAAc,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,OAAO,IAAI,YAAY,CAAC,CAAC;IAErE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,MAAM,CACtC,OAAO,CAAC,CAAC,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAC7C,KAAK,IAA8B,EAAE;QACnC,MAAM,UAAU,GAAmC,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC;QAC9E,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAM,UAAU,CAAC,8BAA8B,EAAE,CAAC;IAC3D,CAAC,EACD;QACE,eAAe,EAAE,0BAA0B;QAC3C,gBAAgB,EAAE,2BAA2B;QAC7C,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,YAAY;KAC3B,CACF,CAAC;IAEF,OAAO,YAAY,IAAI,eAAe,IAAI,IAAI,CAAC;AACjD,CAAC;AAED,eAAe,8BAA8B,CAAC"}
@@ -1,50 +1,39 @@
1
1
  "use client";
2
+ import { useEffect, useState } from "react";
2
3
  import useAuth from "./use-auth";
3
- import useAppEnvironment from "./use-app-environment";
4
- import { useDebug } from "./use-debug";
5
- import { useState } from "react";
6
- import { useAuthClientStateWatcher } from "./use-auth-client-state-watcher";
7
- function getCurrentUser(auth) {
8
- return auth.currentUser;
9
- }
10
- function maybeGetCurrentUserFromAuthHook(authClientRef, debug = false) {
11
- if (authClientRef.ready &&
12
- authClientRef.client &&
13
- authClientRef.client.current) {
14
- const auth = authClientRef.client.current;
15
- const currentUser = getCurrentUser(auth);
16
- if (currentUser) {
17
- if (debug) {
18
- console.log("[maybeGetCurrentUserFromAuthHook] Loaded current user data from auth client: ", currentUser);
19
- }
20
- return currentUser;
4
+ export function useCurrentUser() {
5
+ const auth = useAuth();
6
+ const ready = auth.ready;
7
+ const clientRef = auth.ready ? auth.client : null;
8
+ const [user, setUser] = useState(() => {
9
+ if (!ready || !clientRef || !clientRef.current) {
10
+ return null;
21
11
  }
22
- if (debug) {
23
- console.log("[maybeGetCurrentUserFromAuthHook] Auth client appears to be ready-- but no current user was found!");
12
+ return clientRef.current.currentUser;
13
+ });
14
+ useEffect(() => {
15
+ if (!ready || !clientRef) {
16
+ return;
24
17
  }
25
- return currentUser;
26
- }
27
- return null;
28
- }
29
- export function useCurrentUser() {
30
- const environment = useAppEnvironment();
31
- const authClientRef = useAuth();
32
- const debug = useDebug(environment);
33
- const [user, setUser] = useState(maybeGetCurrentUserFromAuthHook(authClientRef, debug));
34
- useAuthClientStateWatcher({
35
- debug,
36
- onAuthStateChanged: async function updateCurrentUserOnAuthStateChanged({ auth, }) {
37
- const user = auth.currentUser;
38
- if (debug) {
39
- console.log("[updateCurrentUserOnAuthStateChanged] Updating current user: ", user);
40
- }
41
- setUser(user);
18
+ const authClient = clientRef.current;
19
+ if (!authClient) {
42
20
  return;
43
- },
44
- });
45
- if (debug) {
46
- console.warn("[useCurrentUser] Auth client is not ready yet, returning null for user data!");
47
- }
21
+ }
22
+ // Sync once on mount / when ready flips — closes the race where the auth
23
+ // client finishes initializing before a listener can attach.
24
+ setUser(authClient.currentUser);
25
+ const listener_id = authClient.onAuthStateChanged(() => {
26
+ setUser(authClient.currentUser);
27
+ });
28
+ return () => {
29
+ try {
30
+ authClient.removeAuthStateChangeListener(listener_id);
31
+ }
32
+ catch (e) {
33
+ console.error("[useCurrentUser] Failed to remove auth state change listener: ", e);
34
+ }
35
+ };
36
+ }, [ready, clientRef]);
48
37
  return user;
49
38
  }
50
39
  export default useCurrentUser;
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-user.js","sourceRoot":"","sources":["../../src/hooks/use-current-user.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,OAAO,iBAAiB,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,SAAS,cAAc,CAAC,IAA6B;IACnD,OAAO,IAAI,CAAC,WAAW,CAAC;AAC1B,CAAC;AAED,SAAS,+BAA+B,CACtC,aAAyC,EACzC,QAAiB,KAAK;IAEtB,IACE,aAAa,CAAC,KAAK;QACnB,aAAa,CAAC,MAAM;QACpB,aAAa,CAAC,MAAM,CAAC,OAAO,EAC5B,CAAC;QACD,MAAM,IAAI,GAA4B,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC;QACnE,MAAM,WAAW,GAAoB,cAAc,CAAC,IAAI,CAAC,CAAC;QAE1D,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CACT,+EAA+E,EAC/E,WAAW,CACZ,CAAC;YACJ,CAAC;YACD,OAAO,WAA8B,CAAC;QACxC,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CACT,oGAAoG,CACrG,CAAC;QACJ,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;IACxC,MAAM,aAAa,GAAG,OAAO,EAAE,CAAC;IAChC,MAAM,KAAK,GAAY,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE7C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAC9B,+BAA+B,CAAC,aAAa,EAAE,KAAK,CAAC,CACtD,CAAC;IAEF,yBAAyB,CAAC;QACxB,KAAK;QACL,kBAAkB,EAAE,KAAK,UAAU,mCAAmC,CAAC,EACrE,IAAI,GACL;YACC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;YAC9B,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CACT,+DAA+D,EAC/D,IAAI,CACL,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,OAAO;QACT,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CACV,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,OAAO,IAA8B,CAAC;AACxC,CAAC;AAED,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"use-current-user.js","sourceRoot":"","sources":["../../src/hooks/use-current-user.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,cAAc;IAC5B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAElD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAkB,GAAG,EAAE;QACrD,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAwB,EAAE;QAClC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QACD,MAAM,UAAU,GAAmC,SAAS,CAAC,OAAO,CAAC;QACrE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,yEAAyE;QACzE,6DAA6D;QAC7D,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAEhC,MAAM,WAAW,GAAW,UAAU,CAAC,kBAAkB,CAAC,GAAS,EAAE;YACnE,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,OAAO,GAAS,EAAE;YAChB,IAAI,CAAC;gBACH,UAAU,CAAC,6BAA6B,CAAC,WAAW,CAAC,CAAC;YACxD,CAAC;YAAC,OAAO,CAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CACX,gEAAgE,EAChE,CAAC,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAEvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { MfaStatusResponse } from "@schemavaults/auth-common";
2
+ import { type KeyedMutator } from "swr";
3
+ export interface UseMfaStatusSwrResult {
4
+ data: MfaStatusResponse | null;
5
+ isLoading: boolean;
6
+ refresh: KeyedMutator<MfaStatusResponse | null>;
7
+ }
8
+ /**
9
+ * Loads the current user's MFA enrollment status from
10
+ * /api/user/mfa/status. Returns null when the user is unauthenticated.
11
+ */
12
+ export declare function useMfaStatusSwr(): UseMfaStatusSwrResult;
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import useSWR from "swr";
3
+ import useAuth from "./use-auth";
4
+ import useCurrentUser from "./use-current-user";
5
+ const REFRESH_INTERVAL_MS = 60_000;
6
+ const DEDUPING_INTERVAL_MS = 15_000;
7
+ /**
8
+ * Loads the current user's MFA enrollment status from
9
+ * /api/user/mfa/status. Returns null when the user is unauthenticated.
10
+ */
11
+ export function useMfaStatusSwr() {
12
+ const auth = useAuth();
13
+ const inMemoryUser = useCurrentUser();
14
+ const clientRef = auth.ready ? auth.client : null;
15
+ const enabled = !!(auth.ready && clientRef?.current && inMemoryUser);
16
+ const { data, isLoading, mutate } = useSWR(enabled ? "/api/user/mfa/status" : null, async () => {
17
+ const authClient = clientRef?.current ?? null;
18
+ if (!authClient)
19
+ return null;
20
+ return await authClient.getMfaStatus();
21
+ }, {
22
+ refreshInterval: REFRESH_INTERVAL_MS,
23
+ dedupingInterval: DEDUPING_INTERVAL_MS,
24
+ revalidateOnFocus: true,
25
+ });
26
+ return {
27
+ data: data ?? null,
28
+ isLoading,
29
+ refresh: mutate,
30
+ };
31
+ }
32
+ //# sourceMappingURL=use-mfa-status-swr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mfa-status-swr.js","sourceRoot":"","sources":["../../src/hooks/use-mfa-status-swr.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,OAAO,MAA6B,MAAM,KAAK,CAAC;AAChD,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,cAAc,MAAM,0BAA0B,CAAC;AAEtD,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAQpC;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,YAAY,GAAG,cAAc,EAAE,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,OAAO,IAAI,YAAY,CAAC,CAAC;IAErE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CACxC,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,EACvC,KAAK,IAAuC,EAAE;QAC5C,MAAM,UAAU,GACd,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC;QAC7B,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAC7B,OAAO,MAAM,UAAU,CAAC,YAAY,EAAE,CAAC;IACzC,CAAC,EACD;QACE,eAAe,EAAE,mBAAmB;QACpC,gBAAgB,EAAE,oBAAoB;QACtC,iBAAiB,EAAE,IAAI;KACxB,CACF,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,IAAI,IAAI,IAAI;QAClB,SAAS;QACT,OAAO,EAAE,MAAM;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { MfaStatusResponse, MfaEnrollResponse, MfaVerifyEnrollmentResponse, AuthenticateResult } from "@schemavaults/auth-common";
2
+ export interface UseMfaResult {
3
+ status: MfaStatusResponse | null;
4
+ isLoading: boolean;
5
+ refresh: () => Promise<MfaStatusResponse | null | undefined>;
6
+ enrollTotp: () => Promise<MfaEnrollResponse>;
7
+ confirmTotpEnrollment: (factor_id: string, code: string) => Promise<MfaVerifyEnrollmentResponse>;
8
+ removeFactor: (factor_id: string, code: string) => Promise<void>;
9
+ regenerateRecoveryCodes: (code: string) => Promise<MfaVerifyEnrollmentResponse>;
10
+ submitChallenge: (challenge_id: string, client_app_id: string, proof: {
11
+ type: "totp";
12
+ code: string;
13
+ } | {
14
+ type: "recovery_code";
15
+ recovery_code: string;
16
+ }) => Promise<AuthenticateResult>;
17
+ }
18
+ /**
19
+ * Read + mutate the current user's MFA enrollment. Mutators automatically
20
+ * trigger an SWR revalidation so the surrounding UI reflects the new
21
+ * status without a manual refresh.
22
+ */
23
+ export declare function useMfa(): UseMfaResult;
@@ -0,0 +1,60 @@
1
+ "use client";
2
+ import { useCallback } from "react";
3
+ import useAuth from "./use-auth";
4
+ import { useMfaStatusSwr } from "./use-mfa-status-swr";
5
+ function requireClient(auth) {
6
+ if (!auth.ready) {
7
+ throw new Error("Auth client is not ready yet.");
8
+ }
9
+ const client = auth.client.current;
10
+ if (!client) {
11
+ throw new Error("Auth client is not available.");
12
+ }
13
+ return client;
14
+ }
15
+ /**
16
+ * Read + mutate the current user's MFA enrollment. Mutators automatically
17
+ * trigger an SWR revalidation so the surrounding UI reflects the new
18
+ * status without a manual refresh.
19
+ */
20
+ export function useMfa() {
21
+ const auth = useAuth();
22
+ const { data, isLoading, refresh } = useMfaStatusSwr();
23
+ const enrollTotp = useCallback(async () => {
24
+ const client = requireClient(auth);
25
+ const result = await client.enrollTotp();
26
+ return result;
27
+ }, [auth]);
28
+ const confirmTotpEnrollment = useCallback(async (factor_id, code) => {
29
+ const client = requireClient(auth);
30
+ const result = await client.confirmTotpEnrollment(factor_id, code);
31
+ await refresh();
32
+ return result;
33
+ }, [auth, refresh]);
34
+ const removeFactor = useCallback(async (factor_id, code) => {
35
+ const client = requireClient(auth);
36
+ await client.removeFactor(factor_id, code);
37
+ await refresh();
38
+ }, [auth, refresh]);
39
+ const regenerateRecoveryCodes = useCallback(async (code) => {
40
+ const client = requireClient(auth);
41
+ const result = await client.regenerateRecoveryCodes(code);
42
+ await refresh();
43
+ return result;
44
+ }, [auth, refresh]);
45
+ const submitChallenge = useCallback(async (challenge_id, client_app_id, proof) => {
46
+ const client = requireClient(auth);
47
+ return await client.verifyMfaChallenge(challenge_id, client_app_id, proof);
48
+ }, [auth]);
49
+ return {
50
+ status: data,
51
+ isLoading,
52
+ refresh,
53
+ enrollTotp,
54
+ confirmTotpEnrollment,
55
+ removeFactor,
56
+ regenerateRecoveryCodes,
57
+ submitChallenge,
58
+ };
59
+ }
60
+ //# sourceMappingURL=use-mfa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mfa.js","sourceRoot":"","sources":["../../src/hooks/use-mfa.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAQpC,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAwBvD,SAAS,aAAa,CACpB,IAAgC;IAEhC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM;IACpB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,eAAe,EAAE,CAAC;IAEvD,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACxC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,qBAAqB,GAAG,WAAW,CACvC,KAAK,EAAE,SAAiB,EAAE,IAAY,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACnE,MAAM,OAAO,EAAE,CAAC;QAChB,OAAO,MAAM,CAAC;IAChB,CAAC,EACD,CAAC,IAAI,EAAE,OAAO,CAAC,CAChB,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAC9B,KAAK,EAAE,SAAiB,EAAE,IAAY,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC,EACD,CAAC,IAAI,EAAE,OAAO,CAAC,CAChB,CAAC;IAEF,MAAM,uBAAuB,GAAG,WAAW,CACzC,KAAK,EAAE,IAAY,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,OAAO,EAAE,CAAC;QAChB,OAAO,MAAM,CAAC;IAChB,CAAC,EACD,CAAC,IAAI,EAAE,OAAO,CAAC,CAChB,CAAC;IAEF,MAAM,eAAe,GAAG,WAAW,CACjC,KAAK,EACH,YAAoB,EACpB,aAAqB,EACrB,KAEoD,EACpD,EAAE;QACF,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,MAAM,MAAM,CAAC,kBAAkB,CAAC,YAAY,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAC7E,CAAC,EACD,CAAC,IAAI,CAAC,CACP,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,SAAS;QACT,OAAO;QACP,UAAU;QACV,qBAAqB;QACrB,YAAY;QACZ,uBAAuB;QACvB,eAAe;KAChB,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@schemavaults/auth-react-provider",
3
3
  "description": "React hooks and components to make using the @schemavaults/auth-client-sdk a breeze",
4
- "version": "0.10.37",
4
+ "version": "0.11.0",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
7
7
  "repository": {
@@ -15,9 +15,9 @@
15
15
  "types": "dist/index.d.ts",
16
16
  "dependencies": {
17
17
  "zod": "3.25.8",
18
- "@schemavaults/auth-client-sdk": "0.9.47",
18
+ "@schemavaults/auth-client-sdk": "0.10.0",
19
19
  "@schemavaults/app-definitions": "0.6.23",
20
- "@schemavaults/auth-common": "0.10.15",
20
+ "@schemavaults/auth-common": "0.12.0",
21
21
  "cookies-next": "6.1.1",
22
22
  "uuid": "11.0.3",
23
23
  "swr": "2.3.4"