mulguard 1.0.1
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/README.md +368 -0
- package/dist/actions-CExpv_dD.js +1 -0
- package/dist/actions-DeCfLtHA.mjs +184 -0
- package/dist/client/hooks.d.ts +122 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js +1 -0
- package/dist/client/index.mjs +476 -0
- package/dist/client/provider.d.ts +25 -0
- package/dist/client/server-actions-helper.d.ts +22 -0
- package/dist/components/AccountPicker.d.ts +11 -0
- package/dist/components/OAuthButton.d.ts +11 -0
- package/dist/components/PassKeyButton.d.ts +11 -0
- package/dist/components/PassKeyRegister.d.ts +10 -0
- package/dist/components/TwoFactorSetup.d.ts +8 -0
- package/dist/components/TwoFactorVerify.d.ts +9 -0
- package/dist/core/account-picker/encryption.d.ts +22 -0
- package/dist/core/account-picker/index.d.ts +22 -0
- package/dist/core/auth/index.d.ts +40 -0
- package/dist/core/auth/oauth-providers.d.ts +69 -0
- package/dist/core/auth/oauth-state-store.d.ts +44 -0
- package/dist/core/auth/oauth.d.ts +20 -0
- package/dist/core/auth/passkey.d.ts +35 -0
- package/dist/core/auth/password.d.ts +22 -0
- package/dist/core/auth/signin-unified.d.ts +33 -0
- package/dist/core/auth/two-factor.d.ts +28 -0
- package/dist/core/client/index.d.ts +132 -0
- package/dist/core/client/token-refresh-manager.d.ts +48 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/security/csrf.d.ts +46 -0
- package/dist/core/security/headers.d.ts +24 -0
- package/dist/core/security/index.d.ts +28 -0
- package/dist/core/security/rate-limit.d.ts +39 -0
- package/dist/core/security/validation.d.ts +53 -0
- package/dist/core/security/xss.d.ts +20 -0
- package/dist/core/session/index.d.ts +35 -0
- package/dist/core/types/auth.d.ts +131 -0
- package/dist/core/types/errors.d.ts +44 -0
- package/dist/core/types/index.d.ts +369 -0
- package/dist/core/utils/auth-helpers.d.ts +136 -0
- package/dist/core/utils/logger.d.ts +17 -0
- package/dist/handlers/api.d.ts +10 -0
- package/dist/handlers/route.d.ts +22 -0
- package/dist/index/index.js +1 -0
- package/dist/index/index.mjs +1633 -0
- package/dist/index.d.ts +21 -0
- package/dist/middleware/index.d.ts +28 -0
- package/dist/middleware/proxy.d.ts +53 -0
- package/dist/middleware/security.d.ts +9 -0
- package/dist/mulguard.d.ts +263 -0
- package/dist/oauth-state-CzIWQq3s.js +1 -0
- package/dist/oauth-state-LE-qeq-K.mjs +282 -0
- package/dist/server/actions.d.ts +86 -0
- package/dist/server/auth.d.ts +65 -0
- package/dist/server/cookies.d.ts +42 -0
- package/dist/server/helpers.d.ts +10 -0
- package/dist/server/index.d.ts +14 -0
- package/dist/server/index.js +1 -0
- package/dist/server/index.mjs +31 -0
- package/dist/server/middleware.d.ts +39 -0
- package/dist/server/oauth-state.d.ts +24 -0
- package/dist/server/session-helpers.d.ts +26 -0
- package/dist/server/session.d.ts +28 -0
- package/dist/server/utils.d.ts +10 -0
- package/dist/signin-unified-BS2gxaG1.mjs +30 -0
- package/dist/signin-unified-Cw41EFkc.js +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),x=require("../signin-unified-Cw41EFkc.js"),O=require("react/jsx-runtime");function h(){return typeof window>"u"}async function v(){try{return await Promise.resolve().then(()=>require("../actions-CExpv_dD.js")).then(l=>l.actions)}catch{return null}}async function N(e,l){if(h())return e.verify2FA?e.verify2FA(l):{success:!1,error:"2FA verification is not configured"};try{const r=await v();if(r)return await r.verify2FAAction(e,l)}catch{}try{const r=await fetch("/api/auth/verify-2fa",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(l)});if(!r.ok){const a=await r.json().catch(()=>({}));return{success:!1,error:a.error||"2FA verification failed",errorCode:a.errorCode}}return await r.json()}catch(r){return{success:!1,error:r instanceof Error?r.message:"2FA verification failed"}}}async function _(e,l){var r;if(h())return(r=e.signIn)!=null&&r.email?e.signIn.email(l):{success:!1,error:"Email sign in is not configured"};try{const a=await v();if(a)return await a.signInEmailAction(e,l)}catch{}try{const a=await fetch("/api/auth/sign-in",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({provider:"email",credentials:l})});if(!a.ok){const u=await a.json().catch(()=>({}));return{success:!1,error:u.error||"Sign in failed",errorCode:u.errorCode}}return await a.json()}catch(a){return{success:!1,error:a instanceof Error?a.message:"Sign in failed"}}}async function D(e,l){if(h())return e.signUp?e.signUp(l):{success:!1,error:"Sign up is not configured"};try{const r=await v();if(r)return await r.signUpAction(e,l)}catch{}try{const r=await fetch("/api/auth/sign-up",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(l)});if(!r.ok){const a=await r.json().catch(()=>({}));return{success:!1,error:a.error||"Sign up failed",errorCode:a.errorCode}}return await r.json()}catch(r){return{success:!1,error:r instanceof Error?r.message:"Sign up failed"}}}function A(e){const[l,r]=o.useState(null),[a,u]=o.useState(!0),c=o.useCallback(async(s=!1)=>{u(!0);try{const n="/api/auth/session"+(s?`?t=${Date.now()}`:""),i=await fetch(n,{method:"GET",credentials:"include",headers:{"Content-Type":"application/json","Cache-Control":"no-cache, no-store, must-revalidate",Pragma:"no-cache",Expires:"0"},cache:"no-store"});if(i.status===401||i.status===403){r(null);return}if(i.ok){const t=await i.json();t.session?r(t.session):r(null)}else r(null)}catch(n){process.env.NODE_ENV==="development"&&console.error("Failed to load session:",n),r(null)}finally{u(!1)}},[e]),g=o.useCallback(s=>{if(!s||!s.expiresAt||!e.refreshSession)return()=>{};const n=new Date(s.expiresAt),i=new Date,t=n.getTime()-i.getTime(),f=5*60*1e3;if(t>0&&t<f)return e.refreshSession().catch(()=>{}),()=>{};if(t>f){const p=t-f,k=setTimeout(()=>{var S;(S=e.refreshSession)==null||S.call(e).catch(()=>{})},p);return()=>clearTimeout(k)}return()=>{}},[e]);o.useEffect(()=>{let s=null;(async()=>{await c();try{const t=await fetch("/api/auth/session",{method:"GET",credentials:"include",headers:{"Content-Type":"application/json"},cache:"no-store"});if(t.ok){const f=await t.json();f.session?s=g(f.session):r(null)}else r(null)}catch(t){process.env.NODE_ENV==="development"&&console.debug("Failed to schedule proactive refresh:",t),r(null)}})();const i=setInterval(()=>{fetch("/api/auth/session",{method:"GET",credentials:"include",headers:{"Content-Type":"application/json"},cache:"no-store"}).then(t=>t.status===401||t.status===403?(r(null),s&&(s(),s=null),typeof window<"u"&&window.location.pathname!=="/auth/login"&&window.location.replace("/auth/login?reason=session_expired"),null):t.json()).then(t=>{t&&(t.session?(r(t.session),s&&s(),s=g(t.session)):(r(null),s&&(s(),s=null)))}).catch(()=>{r(null),s&&(s(),s=null)})},60*1e3);return()=>{clearInterval(i),s&&s()}},[c,g]);const y=o.useCallback(async s=>{try{const n=await _(e,s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"Sign in failed"}}},[e,c]),w=o.useCallback(async s=>{if(!e.signIn.oauth)throw new Error("OAuth sign in is not configured");return e.signIn.oauth(s)},[e]),d=o.useCallback(async s=>{if(!e.signIn.passkey)return{success:!1,error:"PassKey sign in is not configured"};try{const n=await e.signIn.passkey(s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"PassKey authentication failed"}}},[e,c]),m=o.useCallback(async s=>{if(!e.signUp)return{success:!1,error:"Sign up is not configured"};try{const n=await D(e,s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"Sign up failed"}}},[e,c]),I=o.useCallback(async()=>{var s,n;try{if(r(null),u(!0),typeof window<"u"){try{window.sessionStorage.clear()}catch{}try{const i=(s=e._getSessionConfig)==null?void 0:s.call(e),t=(i==null?void 0:i.cookieName)||"__mulguard_session";try{window.localStorage.removeItem(t)}catch{}}catch{}}if(await e.signOut(),await c(!0),r(null),u(!1),typeof window<"u"){const i="/auth/login",t=window.location.pathname,f=window.location.search;if(t===i||t.startsWith("/auth/")){window.location.reload();return}const p=new URL(i,window.location.origin);t&&t!=="/"&&p.searchParams.set("redirect",t+f),window.location.replace(p.toString())}}catch(i){if(process.env.NODE_ENV==="development"&&console.error("Sign out error:",i),r(null),u(!1),typeof window<"u"){try{window.sessionStorage.clear();const f=(n=e._getSessionConfig)==null?void 0:n.call(e),p=(f==null?void 0:f.cookieName)||"__mulguard_session";try{window.localStorage.removeItem(p)}catch{}}catch{}const t="/auth/login";window.location.pathname!==t&&!window.location.pathname.startsWith("/auth/")?window.location.replace(t):window.location.reload()}}},[e,c]),U=o.useCallback(async s=>{if(!e.resetPassword)throw new Error("Password reset is not configured");return e.resetPassword(s)},[e]),T=o.useCallback(async s=>{if(!e.verifyEmail)throw new Error("Email verification is not configured");return e.verifyEmail(s)},[e]),F=o.useCallback(async s=>{if(!e.verify2FA)return{success:!1,error:"2FA verification is not configured"};try{const n=await N(e,s);return n.success&&(await new Promise(i=>setTimeout(i,100)),await c()),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"2FA verification failed"}}},[e,c]),j=o.useCallback(async(s,n)=>x.signIn(e,s,n),[e]);return{session:l,isLoading:a,signIn:j,signInMethods:{email:y,oauth:w,passkey:d,otp:o.useCallback(async(s,n)=>{if(!e.signIn.otp)return{success:!1,error:"OTP sign in is not configured"};try{const i=await e.signIn.otp(s,n);return i.success&&await c(),i}catch(i){return{success:!1,error:i instanceof Error?i.message:"OTP sign in failed"}}},[e,c])},signUp:m,signOut:I,resetPassword:U,verifyEmail:T,verify2FA:F}}function C(e){const[l,r]=o.useState(null),[a,u]=o.useState(!0),[c,g]=o.useState(null),y=o.useCallback(async()=>{u(!0),g(null);try{const w=await e.getSession();r(w)}catch(w){const d=w instanceof Error?w:new Error("Failed to load session");g(d),r(null)}finally{u(!1)}},[e]);return o.useEffect(()=>{y();const w=setInterval(()=>{y()},5*60*1e3);return()=>clearInterval(w)},[y]),{session:l,isLoading:a,error:c}}function E(e){const[l,r]=o.useState([]),[a,u]=o.useState(!0),c=o.useCallback(async()=>{if(!e.accountPicker){r([]),u(!1);return}u(!0);try{const d=await e.accountPicker.getLastUsers();r(d)}catch(d){process.env.NODE_ENV==="development"&&console.error("Failed to load last users:",d),r([])}finally{u(!1)}},[e]);o.useEffect(()=>{c()},[c]);const g=o.useCallback(async(d,m)=>{e.accountPicker&&(await e.accountPicker.rememberUser(d,m),await c())},[e,c]),y=o.useCallback(async d=>{e.accountPicker&&(await e.accountPicker.clearUser(d),await c())},[e,c]),w=o.useCallback(async()=>{e.accountPicker&&(await e.accountPicker.clearAll(),await c())},[e,c]);return{lastUsers:l,isLoading:a,rememberUser:g,clearUser:y,clearAll:w,refresh:c}}const P=o.createContext(null);function L({auth:e,children:l}){const r=C(e),a=E(e);return O.jsx(P.Provider,{value:{auth:e,session:r,accountPicker:a},children:l})}function b(){const e=o.useContext(P);if(!e)throw new Error("useAuthContext must be used within AuthProvider");return e}function R(){const{auth:e}=b();return A(e)}exports.AuthProvider=L;exports.useAccountPicker=E;exports.useAuth=A;exports.useAuthContext=b;exports.useAuthFromContext=R;exports.useSession=C;
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { useState as y, useCallback as l, useEffect as v, createContext as j, useContext as O } from "react";
|
|
2
|
+
import { s as x } from "../signin-unified-BS2gxaG1.mjs";
|
|
3
|
+
import { jsx as N } from "react/jsx-runtime";
|
|
4
|
+
function E() {
|
|
5
|
+
return typeof window > "u";
|
|
6
|
+
}
|
|
7
|
+
async function S() {
|
|
8
|
+
try {
|
|
9
|
+
return await import("../actions-DeCfLtHA.mjs").then((a) => a.f);
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function _(e, a) {
|
|
15
|
+
if (E())
|
|
16
|
+
return e.verify2FA ? e.verify2FA(a) : {
|
|
17
|
+
success: !1,
|
|
18
|
+
error: "2FA verification is not configured"
|
|
19
|
+
};
|
|
20
|
+
try {
|
|
21
|
+
const r = await S();
|
|
22
|
+
if (r)
|
|
23
|
+
return await r.verify2FAAction(e, a);
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const r = await fetch("/api/auth/verify-2fa", {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: {
|
|
30
|
+
"Content-Type": "application/json"
|
|
31
|
+
},
|
|
32
|
+
credentials: "include",
|
|
33
|
+
body: JSON.stringify(a)
|
|
34
|
+
});
|
|
35
|
+
if (!r.ok) {
|
|
36
|
+
const c = await r.json().catch(() => ({}));
|
|
37
|
+
return {
|
|
38
|
+
success: !1,
|
|
39
|
+
error: c.error || "2FA verification failed",
|
|
40
|
+
errorCode: c.errorCode
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return await r.json();
|
|
44
|
+
} catch (r) {
|
|
45
|
+
return {
|
|
46
|
+
success: !1,
|
|
47
|
+
error: r instanceof Error ? r.message : "2FA verification failed"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function b(e, a) {
|
|
52
|
+
var r;
|
|
53
|
+
if (E())
|
|
54
|
+
return (r = e.signIn) != null && r.email ? e.signIn.email(a) : {
|
|
55
|
+
success: !1,
|
|
56
|
+
error: "Email sign in is not configured"
|
|
57
|
+
};
|
|
58
|
+
try {
|
|
59
|
+
const c = await S();
|
|
60
|
+
if (c)
|
|
61
|
+
return await c.signInEmailAction(e, a);
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const c = await fetch("/api/auth/sign-in", {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: {
|
|
68
|
+
"Content-Type": "application/json"
|
|
69
|
+
},
|
|
70
|
+
credentials: "include",
|
|
71
|
+
body: JSON.stringify({ provider: "email", credentials: a })
|
|
72
|
+
});
|
|
73
|
+
if (!c.ok) {
|
|
74
|
+
const f = await c.json().catch(() => ({}));
|
|
75
|
+
return {
|
|
76
|
+
success: !1,
|
|
77
|
+
error: f.error || "Sign in failed",
|
|
78
|
+
errorCode: f.errorCode
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return await c.json();
|
|
82
|
+
} catch (c) {
|
|
83
|
+
return {
|
|
84
|
+
success: !1,
|
|
85
|
+
error: c instanceof Error ? c.message : "Sign in failed"
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function D(e, a) {
|
|
90
|
+
if (E())
|
|
91
|
+
return e.signUp ? e.signUp(a) : {
|
|
92
|
+
success: !1,
|
|
93
|
+
error: "Sign up is not configured"
|
|
94
|
+
};
|
|
95
|
+
try {
|
|
96
|
+
const r = await S();
|
|
97
|
+
if (r)
|
|
98
|
+
return await r.signUpAction(e, a);
|
|
99
|
+
} catch {
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const r = await fetch("/api/auth/sign-up", {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: {
|
|
105
|
+
"Content-Type": "application/json"
|
|
106
|
+
},
|
|
107
|
+
credentials: "include",
|
|
108
|
+
body: JSON.stringify(a)
|
|
109
|
+
});
|
|
110
|
+
if (!r.ok) {
|
|
111
|
+
const c = await r.json().catch(() => ({}));
|
|
112
|
+
return {
|
|
113
|
+
success: !1,
|
|
114
|
+
error: c.error || "Sign up failed",
|
|
115
|
+
errorCode: c.errorCode
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return await r.json();
|
|
119
|
+
} catch (r) {
|
|
120
|
+
return {
|
|
121
|
+
success: !1,
|
|
122
|
+
error: r instanceof Error ? r.message : "Sign up failed"
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function L(e) {
|
|
127
|
+
const [a, r] = y(null), [c, f] = y(!0), i = l(async (n = !1) => {
|
|
128
|
+
f(!0);
|
|
129
|
+
try {
|
|
130
|
+
const s = "/api/auth/session" + (n ? `?t=${Date.now()}` : ""), t = await fetch(s, {
|
|
131
|
+
method: "GET",
|
|
132
|
+
credentials: "include",
|
|
133
|
+
// Include cookies in request
|
|
134
|
+
headers: {
|
|
135
|
+
"Content-Type": "application/json",
|
|
136
|
+
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
137
|
+
// ✅ FIX: Prevent caching
|
|
138
|
+
Pragma: "no-cache",
|
|
139
|
+
Expires: "0"
|
|
140
|
+
},
|
|
141
|
+
cache: "no-store"
|
|
142
|
+
// ✅ FIX: Prevent caching
|
|
143
|
+
});
|
|
144
|
+
if (t.status === 401 || t.status === 403) {
|
|
145
|
+
r(null);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (t.ok) {
|
|
149
|
+
const o = await t.json();
|
|
150
|
+
o.session ? r(o.session) : r(null);
|
|
151
|
+
} else
|
|
152
|
+
r(null);
|
|
153
|
+
} catch (s) {
|
|
154
|
+
process.env.NODE_ENV === "development" && console.error("Failed to load session:", s), r(null);
|
|
155
|
+
} finally {
|
|
156
|
+
f(!1);
|
|
157
|
+
}
|
|
158
|
+
}, [e]), g = l((n) => {
|
|
159
|
+
if (!n || !n.expiresAt || !e.refreshSession)
|
|
160
|
+
return () => {
|
|
161
|
+
};
|
|
162
|
+
const s = new Date(n.expiresAt), t = /* @__PURE__ */ new Date(), o = s.getTime() - t.getTime(), u = 5 * 60 * 1e3;
|
|
163
|
+
if (o > 0 && o < u)
|
|
164
|
+
return e.refreshSession().catch(() => {
|
|
165
|
+
}), () => {
|
|
166
|
+
};
|
|
167
|
+
if (o > u) {
|
|
168
|
+
const m = o - u, A = setTimeout(() => {
|
|
169
|
+
var P;
|
|
170
|
+
(P = e.refreshSession) == null || P.call(e).catch(() => {
|
|
171
|
+
});
|
|
172
|
+
}, m);
|
|
173
|
+
return () => clearTimeout(A);
|
|
174
|
+
}
|
|
175
|
+
return () => {
|
|
176
|
+
};
|
|
177
|
+
}, [e]);
|
|
178
|
+
v(() => {
|
|
179
|
+
let n = null;
|
|
180
|
+
(async () => {
|
|
181
|
+
await i();
|
|
182
|
+
try {
|
|
183
|
+
const o = await fetch("/api/auth/session", {
|
|
184
|
+
method: "GET",
|
|
185
|
+
credentials: "include",
|
|
186
|
+
headers: {
|
|
187
|
+
"Content-Type": "application/json"
|
|
188
|
+
},
|
|
189
|
+
cache: "no-store"
|
|
190
|
+
// ✅ FIX: Prevent caching
|
|
191
|
+
});
|
|
192
|
+
if (o.ok) {
|
|
193
|
+
const u = await o.json();
|
|
194
|
+
u.session ? n = g(u.session) : r(null);
|
|
195
|
+
} else
|
|
196
|
+
r(null);
|
|
197
|
+
} catch (o) {
|
|
198
|
+
process.env.NODE_ENV === "development" && console.debug("Failed to schedule proactive refresh:", o), r(null);
|
|
199
|
+
}
|
|
200
|
+
})();
|
|
201
|
+
const t = setInterval(() => {
|
|
202
|
+
fetch("/api/auth/session", {
|
|
203
|
+
method: "GET",
|
|
204
|
+
credentials: "include",
|
|
205
|
+
headers: {
|
|
206
|
+
"Content-Type": "application/json"
|
|
207
|
+
},
|
|
208
|
+
cache: "no-store"
|
|
209
|
+
// ✅ FIX: Prevent caching
|
|
210
|
+
}).then((o) => o.status === 401 || o.status === 403 ? (r(null), n && (n(), n = null), typeof window < "u" && window.location.pathname !== "/auth/login" && window.location.replace("/auth/login?reason=session_expired"), null) : o.json()).then((o) => {
|
|
211
|
+
o && (o.session ? (r(o.session), n && n(), n = g(o.session)) : (r(null), n && (n(), n = null)));
|
|
212
|
+
}).catch(() => {
|
|
213
|
+
r(null), n && (n(), n = null);
|
|
214
|
+
});
|
|
215
|
+
}, 60 * 1e3);
|
|
216
|
+
return () => {
|
|
217
|
+
clearInterval(t), n && n();
|
|
218
|
+
};
|
|
219
|
+
}, [i, g]);
|
|
220
|
+
const p = l(
|
|
221
|
+
async (n) => {
|
|
222
|
+
try {
|
|
223
|
+
const s = await b(e, n);
|
|
224
|
+
return s.success && await i(), s;
|
|
225
|
+
} catch (s) {
|
|
226
|
+
return {
|
|
227
|
+
success: !1,
|
|
228
|
+
error: s instanceof Error ? s.message : "Sign in failed"
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
[e, i]
|
|
233
|
+
), w = l(
|
|
234
|
+
async (n) => {
|
|
235
|
+
if (!e.signIn.oauth)
|
|
236
|
+
throw new Error("OAuth sign in is not configured");
|
|
237
|
+
return e.signIn.oauth(n);
|
|
238
|
+
},
|
|
239
|
+
[e]
|
|
240
|
+
), d = l(
|
|
241
|
+
async (n) => {
|
|
242
|
+
if (!e.signIn.passkey)
|
|
243
|
+
return {
|
|
244
|
+
success: !1,
|
|
245
|
+
error: "PassKey sign in is not configured"
|
|
246
|
+
};
|
|
247
|
+
try {
|
|
248
|
+
const s = await e.signIn.passkey(n);
|
|
249
|
+
return s.success && await i(), s;
|
|
250
|
+
} catch (s) {
|
|
251
|
+
return {
|
|
252
|
+
success: !1,
|
|
253
|
+
error: s instanceof Error ? s.message : "PassKey authentication failed"
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
[e, i]
|
|
258
|
+
), h = l(
|
|
259
|
+
async (n) => {
|
|
260
|
+
if (!e.signUp)
|
|
261
|
+
return {
|
|
262
|
+
success: !1,
|
|
263
|
+
error: "Sign up is not configured"
|
|
264
|
+
};
|
|
265
|
+
try {
|
|
266
|
+
const s = await D(e, n);
|
|
267
|
+
return s.success && await i(), s;
|
|
268
|
+
} catch (s) {
|
|
269
|
+
return {
|
|
270
|
+
success: !1,
|
|
271
|
+
error: s instanceof Error ? s.message : "Sign up failed"
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
[e, i]
|
|
276
|
+
), k = l(async () => {
|
|
277
|
+
var n, s;
|
|
278
|
+
try {
|
|
279
|
+
if (r(null), f(!0), typeof window < "u") {
|
|
280
|
+
try {
|
|
281
|
+
window.sessionStorage.clear();
|
|
282
|
+
} catch {
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
const t = (n = e._getSessionConfig) == null ? void 0 : n.call(e), o = (t == null ? void 0 : t.cookieName) || "__mulguard_session";
|
|
286
|
+
try {
|
|
287
|
+
window.localStorage.removeItem(o);
|
|
288
|
+
} catch {
|
|
289
|
+
}
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (await e.signOut(), await i(!0), r(null), f(!1), typeof window < "u") {
|
|
294
|
+
const t = "/auth/login", o = window.location.pathname, u = window.location.search;
|
|
295
|
+
if (o === t || o.startsWith("/auth/")) {
|
|
296
|
+
window.location.reload();
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const m = new URL(t, window.location.origin);
|
|
300
|
+
o && o !== "/" && m.searchParams.set("redirect", o + u), window.location.replace(m.toString());
|
|
301
|
+
}
|
|
302
|
+
} catch (t) {
|
|
303
|
+
if (process.env.NODE_ENV === "development" && console.error("Sign out error:", t), r(null), f(!1), typeof window < "u") {
|
|
304
|
+
try {
|
|
305
|
+
window.sessionStorage.clear();
|
|
306
|
+
const u = (s = e._getSessionConfig) == null ? void 0 : s.call(e), m = (u == null ? void 0 : u.cookieName) || "__mulguard_session";
|
|
307
|
+
try {
|
|
308
|
+
window.localStorage.removeItem(m);
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
} catch {
|
|
312
|
+
}
|
|
313
|
+
const o = "/auth/login";
|
|
314
|
+
window.location.pathname !== o && !window.location.pathname.startsWith("/auth/") ? window.location.replace(o) : window.location.reload();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}, [e, i]), U = l(
|
|
318
|
+
async (n) => {
|
|
319
|
+
if (!e.resetPassword)
|
|
320
|
+
throw new Error("Password reset is not configured");
|
|
321
|
+
return e.resetPassword(n);
|
|
322
|
+
},
|
|
323
|
+
[e]
|
|
324
|
+
), C = l(
|
|
325
|
+
async (n) => {
|
|
326
|
+
if (!e.verifyEmail)
|
|
327
|
+
throw new Error("Email verification is not configured");
|
|
328
|
+
return e.verifyEmail(n);
|
|
329
|
+
},
|
|
330
|
+
[e]
|
|
331
|
+
), T = l(
|
|
332
|
+
async (n) => {
|
|
333
|
+
if (!e.verify2FA)
|
|
334
|
+
return {
|
|
335
|
+
success: !1,
|
|
336
|
+
error: "2FA verification is not configured"
|
|
337
|
+
};
|
|
338
|
+
try {
|
|
339
|
+
const s = await _(e, n);
|
|
340
|
+
return s.success && (await new Promise((t) => setTimeout(t, 100)), await i()), s;
|
|
341
|
+
} catch (s) {
|
|
342
|
+
return {
|
|
343
|
+
success: !1,
|
|
344
|
+
error: s instanceof Error ? s.message : "2FA verification failed"
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
[e, i]
|
|
349
|
+
), F = l(
|
|
350
|
+
async (n, s) => x(e, n, s),
|
|
351
|
+
[e]
|
|
352
|
+
);
|
|
353
|
+
return {
|
|
354
|
+
session: a,
|
|
355
|
+
isLoading: c,
|
|
356
|
+
signIn: F,
|
|
357
|
+
signInMethods: {
|
|
358
|
+
email: p,
|
|
359
|
+
oauth: w,
|
|
360
|
+
passkey: d,
|
|
361
|
+
otp: l(
|
|
362
|
+
async (n, s) => {
|
|
363
|
+
if (!e.signIn.otp)
|
|
364
|
+
return {
|
|
365
|
+
success: !1,
|
|
366
|
+
error: "OTP sign in is not configured"
|
|
367
|
+
};
|
|
368
|
+
try {
|
|
369
|
+
const t = await e.signIn.otp(n, s);
|
|
370
|
+
return t.success && await i(), t;
|
|
371
|
+
} catch (t) {
|
|
372
|
+
return {
|
|
373
|
+
success: !1,
|
|
374
|
+
error: t instanceof Error ? t.message : "OTP sign in failed"
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
[e, i]
|
|
379
|
+
)
|
|
380
|
+
},
|
|
381
|
+
signUp: h,
|
|
382
|
+
signOut: k,
|
|
383
|
+
resetPassword: U,
|
|
384
|
+
verifyEmail: C,
|
|
385
|
+
verify2FA: T
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function W(e) {
|
|
389
|
+
const [a, r] = y(null), [c, f] = y(!0), [i, g] = y(null), p = l(async () => {
|
|
390
|
+
f(!0), g(null);
|
|
391
|
+
try {
|
|
392
|
+
const w = await e.getSession();
|
|
393
|
+
r(w);
|
|
394
|
+
} catch (w) {
|
|
395
|
+
const d = w instanceof Error ? w : new Error("Failed to load session");
|
|
396
|
+
g(d), r(null);
|
|
397
|
+
} finally {
|
|
398
|
+
f(!1);
|
|
399
|
+
}
|
|
400
|
+
}, [e]);
|
|
401
|
+
return v(() => {
|
|
402
|
+
p();
|
|
403
|
+
const w = setInterval(() => {
|
|
404
|
+
p();
|
|
405
|
+
}, 5 * 60 * 1e3);
|
|
406
|
+
return () => clearInterval(w);
|
|
407
|
+
}, [p]), {
|
|
408
|
+
session: a,
|
|
409
|
+
isLoading: c,
|
|
410
|
+
error: i
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function R(e) {
|
|
414
|
+
const [a, r] = y([]), [c, f] = y(!0), i = l(async () => {
|
|
415
|
+
if (!e.accountPicker) {
|
|
416
|
+
r([]), f(!1);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
f(!0);
|
|
420
|
+
try {
|
|
421
|
+
const d = await e.accountPicker.getLastUsers();
|
|
422
|
+
r(d);
|
|
423
|
+
} catch (d) {
|
|
424
|
+
process.env.NODE_ENV === "development" && console.error("Failed to load last users:", d), r([]);
|
|
425
|
+
} finally {
|
|
426
|
+
f(!1);
|
|
427
|
+
}
|
|
428
|
+
}, [e]);
|
|
429
|
+
v(() => {
|
|
430
|
+
i();
|
|
431
|
+
}, [i]);
|
|
432
|
+
const g = l(
|
|
433
|
+
async (d, h) => {
|
|
434
|
+
e.accountPicker && (await e.accountPicker.rememberUser(d, h), await i());
|
|
435
|
+
},
|
|
436
|
+
[e, i]
|
|
437
|
+
), p = l(
|
|
438
|
+
async (d) => {
|
|
439
|
+
e.accountPicker && (await e.accountPicker.clearUser(d), await i());
|
|
440
|
+
},
|
|
441
|
+
[e, i]
|
|
442
|
+
), w = l(async () => {
|
|
443
|
+
e.accountPicker && (await e.accountPicker.clearAll(), await i());
|
|
444
|
+
}, [e, i]);
|
|
445
|
+
return {
|
|
446
|
+
lastUsers: a,
|
|
447
|
+
isLoading: c,
|
|
448
|
+
rememberUser: g,
|
|
449
|
+
clearUser: p,
|
|
450
|
+
clearAll: w,
|
|
451
|
+
refresh: i
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
const I = j(null);
|
|
455
|
+
function K({ auth: e, children: a }) {
|
|
456
|
+
const r = W(e), c = R(e);
|
|
457
|
+
return /* @__PURE__ */ N(I.Provider, { value: { auth: e, session: r, accountPicker: c }, children: a });
|
|
458
|
+
}
|
|
459
|
+
function V() {
|
|
460
|
+
const e = O(I);
|
|
461
|
+
if (!e)
|
|
462
|
+
throw new Error("useAuthContext must be used within AuthProvider");
|
|
463
|
+
return e;
|
|
464
|
+
}
|
|
465
|
+
function $() {
|
|
466
|
+
const { auth: e } = V();
|
|
467
|
+
return L(e);
|
|
468
|
+
}
|
|
469
|
+
export {
|
|
470
|
+
K as AuthProvider,
|
|
471
|
+
R as useAccountPicker,
|
|
472
|
+
L as useAuth,
|
|
473
|
+
V as useAuthContext,
|
|
474
|
+
$ as useAuthFromContext,
|
|
475
|
+
W as useSession
|
|
476
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { MulguardInstance } from '../mulguard';
|
|
3
|
+
import { useSession, useAccountPicker } from './hooks';
|
|
4
|
+
interface AuthContextValue {
|
|
5
|
+
auth: MulguardInstance;
|
|
6
|
+
session: ReturnType<typeof useSession>;
|
|
7
|
+
accountPicker: ReturnType<typeof useAccountPicker>;
|
|
8
|
+
}
|
|
9
|
+
interface AuthProviderProps {
|
|
10
|
+
auth: MulguardInstance;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Auth Provider - provides auth instance to children
|
|
15
|
+
*/
|
|
16
|
+
export declare function AuthProvider({ auth, children }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Use auth context
|
|
19
|
+
*/
|
|
20
|
+
export declare function useAuthContext(): AuthContextValue;
|
|
21
|
+
/**
|
|
22
|
+
* Convenience hook that uses context
|
|
23
|
+
*/
|
|
24
|
+
export declare function useAuthFromContext(): import('./hooks').UseAuthReturn;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MulguardInstance } from '../mulguard';
|
|
2
|
+
import { Verify2FAData, AuthResult, EmailCredentials, RegisterData } from '../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* Verify 2FA with automatic fallback
|
|
5
|
+
* Tries Server Action first, then falls back to Route Handler
|
|
6
|
+
*/
|
|
7
|
+
export declare function verify2FAWithFallback(auth: MulguardInstance, data: Verify2FAData): Promise<AuthResult>;
|
|
8
|
+
/**
|
|
9
|
+
* Sign out with automatic fallback
|
|
10
|
+
*/
|
|
11
|
+
export declare function signOutWithFallback(auth: MulguardInstance): Promise<{
|
|
12
|
+
success: boolean;
|
|
13
|
+
error?: string;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Sign in with email with automatic fallback
|
|
17
|
+
*/
|
|
18
|
+
export declare function signInEmailWithFallback(auth: MulguardInstance, credentials: EmailCredentials): Promise<AuthResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Sign up with automatic fallback
|
|
21
|
+
*/
|
|
22
|
+
export declare function signUpWithFallback(auth: MulguardInstance, data: RegisterData): Promise<AuthResult>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MulguardInstance } from '../mulguard';
|
|
2
|
+
import { RememberedUser } from '../core/types';
|
|
3
|
+
interface AccountPickerProps {
|
|
4
|
+
auth: MulguardInstance;
|
|
5
|
+
onSelectUser?: (user: RememberedUser) => void;
|
|
6
|
+
onUseDifferentAccount?: () => void;
|
|
7
|
+
maxDisplay?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function AccountPicker({ auth, onSelectUser, onUseDifferentAccount, maxDisplay, className, }: AccountPickerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MulguardInstance } from '../mulguard';
|
|
2
|
+
interface OAuthButtonProps {
|
|
3
|
+
auth: MulguardInstance;
|
|
4
|
+
provider: string;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
onSuccess?: () => void;
|
|
8
|
+
onError?: (error: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function OAuthButton({ auth, provider, children, className, onSuccess, onError, }: OAuthButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MulguardInstance } from '../mulguard';
|
|
2
|
+
interface PassKeyButtonProps {
|
|
3
|
+
auth: MulguardInstance;
|
|
4
|
+
children?: React.ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
onSuccess?: () => void;
|
|
7
|
+
onError?: (error: string) => void;
|
|
8
|
+
userId?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function PassKeyButton({ auth, children, className, onSuccess, onError, userId, }: PassKeyButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MulguardInstance } from '../mulguard';
|
|
2
|
+
interface PassKeyRegisterProps {
|
|
3
|
+
auth: MulguardInstance;
|
|
4
|
+
onSuccess?: (passkeyId: string) => void;
|
|
5
|
+
onError?: (error: string) => void;
|
|
6
|
+
userId?: string;
|
|
7
|
+
defaultName?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function PassKeyRegister({ auth, onSuccess, onError, userId, defaultName, }: PassKeyRegisterProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MulguardInstance } from '../mulguard';
|
|
2
|
+
interface TwoFactorSetupProps {
|
|
3
|
+
auth: MulguardInstance;
|
|
4
|
+
onSuccess?: () => void;
|
|
5
|
+
onError?: (error: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function TwoFactorSetup({ auth, onSuccess, onError }: TwoFactorSetupProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MulguardInstance } from '../mulguard';
|
|
2
|
+
interface TwoFactorVerifyProps {
|
|
3
|
+
auth: MulguardInstance;
|
|
4
|
+
onSuccess?: () => void;
|
|
5
|
+
onError?: (error: string) => void;
|
|
6
|
+
onUseBackupCode?: () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function TwoFactorVerify({ auth, onSuccess, onError, onUseBackupCode }: TwoFactorVerifyProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Picker Encryption Utilities
|
|
3
|
+
* Supports multiple encryption methods for account picker storage
|
|
4
|
+
*/
|
|
5
|
+
export type EncryptionMethod = 'none' | 'base64' | 'aes-gcm';
|
|
6
|
+
/**
|
|
7
|
+
* Encryption result with metadata
|
|
8
|
+
*/
|
|
9
|
+
interface EncryptionResult {
|
|
10
|
+
data: string;
|
|
11
|
+
method: EncryptionMethod;
|
|
12
|
+
iv?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Encrypt data based on method
|
|
16
|
+
*/
|
|
17
|
+
export declare function encryptData(data: string, method?: EncryptionMethod): Promise<EncryptionResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Decrypt data - auto-detects method from stored data or uses provided method
|
|
20
|
+
*/
|
|
21
|
+
export declare function decryptData(encrypted: string, method?: EncryptionMethod): Promise<string>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RememberedUser, User } from '../types';
|
|
2
|
+
import { EncryptionMethod } from './encryption';
|
|
3
|
+
export type { EncryptionMethod } from './encryption';
|
|
4
|
+
export interface AccountPickerConfig {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
maxAccounts?: number;
|
|
7
|
+
/** @deprecated Use encryptionMethod instead. If true, defaults to 'base64' */
|
|
8
|
+
encryptStorage?: boolean;
|
|
9
|
+
/** Encryption method: 'none' | 'base64' | 'aes-gcm' (default: 'base64' for backward compatibility) */
|
|
10
|
+
encryptionMethod?: EncryptionMethod;
|
|
11
|
+
storageKey?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AccountPickerMethods {
|
|
14
|
+
getLastUsers(): Promise<RememberedUser[]>;
|
|
15
|
+
rememberUser(user: User, provider?: 'email' | 'oauth' | 'passkey'): Promise<void>;
|
|
16
|
+
clearUser(userId: string): Promise<void>;
|
|
17
|
+
clearAll(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create Account Picker methods
|
|
21
|
+
*/
|
|
22
|
+
export declare function createAccountPickerMethods(config: AccountPickerConfig): AccountPickerMethods;
|