mulguard 1.1.3 → 1.1.4
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/core/auth/oauth-state-store-redis.d.ts +25 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/index/index.js +1 -1
- package/dist/index/index.mjs +254 -211
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { OAuthStateStore } from './oauth-state-store';
|
|
2
|
+
/**
|
|
3
|
+
* Redis client interface (compatible with ioredis and node-redis)
|
|
4
|
+
*/
|
|
5
|
+
export interface RedisClient {
|
|
6
|
+
set(key: string, value: string, mode?: string, duration?: number): Promise<string | null>;
|
|
7
|
+
get(key: string): Promise<string | null>;
|
|
8
|
+
del(key: string): Promise<number>;
|
|
9
|
+
keys(pattern: string): Promise<string[]>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates a Redis-based OAuth state store.
|
|
13
|
+
*
|
|
14
|
+
* @param redis - Redis client instance (ioredis or node-redis)
|
|
15
|
+
* @param keyPrefix - Key prefix for state keys (default: 'mulguard:oauth:state:')
|
|
16
|
+
* @returns OAuth state store implementation
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import Redis from 'ioredis'
|
|
21
|
+
* const redis = new Redis(process.env.REDIS_URL)
|
|
22
|
+
* const stateStore = createRedisOAuthStateStore(redis)
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function createRedisOAuthStateStore(redis: RedisClient, keyPrefix?: string): OAuthStateStore;
|
package/dist/core/index.d.ts
CHANGED
package/dist/index/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var we=Object.defineProperty;var pe=(e,r,t)=>r in e?we(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var x=(e,r,t)=>pe(e,typeof r!="symbol"?r+"":r,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("../actions-CExpv_dD.js"),C=require("../oauth-state-CzIWQq3s.js"),m=require("next/server"),F=typeof globalThis=="object"&&"crypto"in globalThis?globalThis.crypto:void 0;/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function Ee(e=32){if(F&&typeof F.getRandomValues=="function")return F.getRandomValues(new Uint8Array(e));if(F&&typeof F.randomBytes=="function")return Uint8Array.from(F.randomBytes(e));throw new Error("crypto.getRandomValues must be defined")}class Y{constructor(r){x(this,"attempts",new Map);x(this,"config");this.config=r}check(r){const t=Date.now(),n=this.attempts.get(r);return!n||n.resetAt<t?(this.attempts.set(r,{count:1,resetAt:t+this.config.windowMs}),{allowed:!0,remaining:this.config.maxAttempts-1,resetAt:new Date(t+this.config.windowMs)}):n.count>=this.config.maxAttempts?{allowed:!1,remaining:0,resetAt:new Date(n.resetAt)}:(n.count++,{allowed:!0,remaining:this.config.maxAttempts-n.count,resetAt:new Date(n.resetAt)})}reset(r){this.attempts.delete(r)}clear(){this.attempts.clear()}}function me(e){return new Y(e)}const Q={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"1; mode=block","Strict-Transport-Security":"max-age=31536000; includeSubDomains","Content-Security-Policy":"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"geolocation=(), microphone=(), camera=()"};function j(e){return{...Q,...e}}function Se(e,r){const t=j(r);for(const[n,s]of Object.entries(t))s&&e.set(n,s)}const ye=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,Ae=254;function $(e){var t;if(typeof e!="string"||!e)return{valid:!1,error:"Email is required"};const r=e.trim().toLowerCase();return ye.test(r)?r.length>Ae?{valid:!1,error:"Email is too long"}:r.includes("..")||r.startsWith(".")||r.endsWith(".")?{valid:!1,error:"Invalid email format"}:(t=r.split("@")[1])!=null&&t.includes("..")?{valid:!1,error:"Invalid email format"}:{valid:!0,sanitized:r}:{valid:!1,error:"Invalid email format"}}function Z(e){return e.valid===!0&&e.sanitized!==void 0}const Re=new Set(["password","12345678","qwerty","abc123","password123","123456789","1234567890","letmein","welcome","monkey","dragon","master","sunshine","princess","football","admin","root","test","guest","user"]),ve=/012|123|234|345|456|567|678|789|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz/i,ke=8,Ce=128;function Te(e,r=ke){if(typeof e!="string"||!e)return{valid:!1,error:"Password is required"};if(e.length<r)return{valid:!1,error:`Password must be at least ${r} characters`};if(e.length>Ce)return{valid:!1,error:"Password is too long"};const t=e.toLowerCase();if(Re.has(t))return{valid:!1,error:"Password is too common"};if(/(.)\1{3,}/.test(e))return{valid:!1,error:"Password contains too many repeated characters"};if(ve.test(e))return{valid:!1,error:"Password contains sequential characters"};const n=Oe(e);return{valid:!0,sanitized:e,strength:n}}function Oe(e){let r=0;return e.length>=12?r+=2:e.length>=8&&(r+=1),/[a-z]/.test(e)&&(r+=1),/[A-Z]/.test(e)&&(r+=1),/[0-9]/.test(e)&&(r+=1),/[^a-zA-Z0-9]/.test(e)&&(r+=1),r>=5?"strong":r>=3?"medium":"weak"}function Ie(e){return e.valid===!0&&e.sanitized!==void 0}const Pe=100;function _e(e){if(typeof e!="string"||!e)return{valid:!1,error:"Name is required"};const r=e.trim();if(r.length<1)return{valid:!1,error:"Name cannot be empty"};if(r.length>Pe)return{valid:!1,error:"Name is too long"};const t=r.replace(/[<>"']/g,"");return t.length===0?{valid:!1,error:"Name contains only invalid characters"}:{valid:!0,sanitized:t}}function Ne(e){return e.valid===!0&&e.sanitized!==void 0}const Ue=new Set(["http:","https:"]);function be(e){if(typeof e!="string"||!e)return{valid:!1,error:"URL is required"};try{const r=new URL(e);return Ue.has(r.protocol)?{valid:!0,sanitized:e}:{valid:!1,error:"URL must use http or https protocol"}}catch{return{valid:!1,error:"Invalid URL format"}}}function xe(e){return e.valid===!0&&e.sanitized!==void 0}const Fe=16,Le=512,De=/^[A-Za-z0-9_-]+$/;function Me(e,r=Fe){return typeof e!="string"||!e?{valid:!1,error:"Token is required"}:e.length<r?{valid:!1,error:"Token is too short"}:e.length>Le?{valid:!1,error:"Token is too long"}:De.test(e)?/(.)\1{10,}/.test(e)?{valid:!1,error:"Token contains suspicious pattern"}:{valid:!0,sanitized:e}:{valid:!1,error:"Invalid token format"}}function Ve(e){return e.valid===!0&&e.sanitized!==void 0}const ze=1e3;function q(e,r){const{maxLength:t=ze,allowHtml:n=!1,required:s=!0}=r??{};if(s&&(typeof e!="string"||!e||e.trim().length===0))return{valid:!1,error:"Input is required"};if(typeof e!="string"||!e)return{valid:!0,sanitized:""};let o=e.trim();return o.length>t?{valid:!1,error:`Input must be less than ${t} characters`}:(n||(o=o.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")),o=o.replace(/[\x00-\x1F\x7F]/g,""),{valid:!0,sanitized:o})}function je(e){return e.valid===!0&&e.sanitized!==void 0}class ee{constructor(){x(this,"tokens",new Map)}get(r){const t=this.tokens.get(r);return t?t.expiresAt<Date.now()?(this.delete(r),null):t.value:null}set(r,t,n=36e5){this.tokens.set(r,{value:t,expiresAt:Date.now()+n})}delete(r){this.tokens.delete(r)}clear(){this.tokens.clear()}}class re{constructor(r,t=32){x(this,"store");x(this,"tokenLength");this.store=r||new ee,this.tokenLength=t}generateToken(r,t){const n=H(this.tokenLength);return this.store.set(r,n,t),n}validateToken(r,t){const n=this.store.get(r);if(!n)return!1;const s=W(t,n);return s&&this.store.delete(r),s}getToken(r){return this.store.get(r)}deleteToken(r){this.store.delete(r)}}function $e(e){return new re(e)}function te(e){if(typeof e!="string")return"";const r={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,t=>r[t]||t)}function qe(e){return typeof e!="string"?"":e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/on\w+\s*=\s*["'][^"']*["']/gi,"").replace(/javascript:/gi,"")}function He(e){return typeof e!="string"?"":te(e.trim())}function We(e){return typeof e!="string"?!1:[/<script/i,/javascript:/i,/on\w+\s*=/i,/<iframe/i,/<object/i,/<embed/i,/<link/i,/<meta/i,/expression\s*\(/i,/vbscript:/i].some(t=>t.test(e))}const ne=32;function H(e=ne){if(e<1||e>256)throw new Error("Token length must be between 1 and 256 bytes");const r=Ee(e);return Buffer.from(r).toString("base64url")}function se(){return H(ne)}function W(e,r){if(typeof e!="string"||typeof r!="string"||!e||!r||e.length!==r.length)return!1;let t=0;for(let n=0;n<e.length;n++)t|=e.charCodeAt(n)^r.charCodeAt(n);return t===0}function Be(e,r){return W(e,r)}function Ge(e){return typeof e!="string"?"":e.trim().replace(/[<>]/g,"")}const Ke=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;function Xe(e){return typeof e=="string"&&Ke.test(e)}function oe(e){return!e.success&&!!e.error}function Je(e){return e.requires2FA===!0||e.errorCode===h.AuthErrorCode.TWO_FA_REQUIRED}function Ye(e,r){return e.error?e.error:r||"Authentication failed"}function Qe(e){return e.errorCode}function Ze(e){return e.success===!0&&!!e.user}function er(e,r){return e.errorCode===r}function rr(e){if(!oe(e))return!1;const r=[h.AuthErrorCode.NETWORK_ERROR,h.AuthErrorCode.RATE_LIMITED,h.AuthErrorCode.UNKNOWN_ERROR];return e.errorCode?r.includes(e.errorCode):!1}function tr(e){if(e.error)return e.error;switch(e.errorCode){case h.AuthErrorCode.INVALID_CREDENTIALS:return"Invalid email or password. Please try again.";case h.AuthErrorCode.ACCOUNT_LOCKED:return"Your account has been temporarily locked. Please try again later.";case h.AuthErrorCode.ACCOUNT_INACTIVE:return"Your account is inactive. Please contact support.";case h.AuthErrorCode.TWO_FA_REQUIRED:return"Two-factor authentication is required. Please enter your code.";case h.AuthErrorCode.INVALID_TWO_FA_CODE:return"Invalid two-factor authentication code. Please try again.";case h.AuthErrorCode.SESSION_EXPIRED:return"Your session has expired. Please sign in again.";case h.AuthErrorCode.UNAUTHORIZED:return"You are not authorized to perform this action.";case h.AuthErrorCode.NETWORK_ERROR:return"Network error. Please check your connection and try again.";case h.AuthErrorCode.VALIDATION_ERROR:return"Please check your input and try again.";case h.AuthErrorCode.RATE_LIMITED:return"Too many attempts. Please try again later.";case h.AuthErrorCode.UNKNOWN_ERROR:default:return"An unexpected error occurred. Please try again."}}async function nr(e,r,t){return e.signIn(r,t)}const ie={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",userInfoUrl:"https://www.googleapis.com/oauth2/v2/userinfo",defaultScopes:["openid","profile","email"]},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",defaultScopes:["user:email"]},apple:{authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",userInfoUrl:"https://appleid.apple.com/auth/userinfo",defaultScopes:["name","email"],defaultParams:{response_mode:"form_post",response_type:"code id_token"}},facebook:{authorizationUrl:"https://www.facebook.com/v18.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v18.0/oauth/access_token",userInfoUrl:"https://graph.facebook.com/v18.0/me?fields=id,name,email,picture",defaultScopes:["email","public_profile"]}};function z(e){return ie[e]??null}function sr(e){return e in ie}function ae(e,r,t,n){const s=z(e);if(!s)throw new Error(`Unknown OAuth provider: ${e}`);if(!r.clientId)throw new Error(`OAuth provider "${e}" is missing clientId`);const o=r.redirectUri??`${t}/api/auth/callback/${e}`,i=r.scopes??s.defaultScopes,a=new URLSearchParams({client_id:r.clientId,redirect_uri:o,response_type:"code",scope:Array.isArray(i)?i.join(" "):String(i),state:n});if(s.defaultParams)for(const[f,l]of Object.entries(s.defaultParams))a.append(f,l);if(r.params)for(const[f,l]of Object.entries(r.params))a.set(f,l);return`${s.authorizationUrl}?${a.toString()}`}async function ce(e,r,t,n){const s=z(e);if(!s)throw new Error(`Unknown OAuth provider: ${e}`);if(!t||typeof t!="string")throw new Error("Authorization code is required");if(!r.clientId)throw new Error(`OAuth provider "${e}" is missing clientId`);const o=new URLSearchParams({client_id:r.clientId,code:t,redirect_uri:n,grant_type:"authorization_code"});r.clientSecret&&o.append("client_secret",r.clientSecret);try{const i=await fetch(s.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:o.toString()});if(!i.ok){const f=await i.text();let l=`Failed to exchange code for tokens: ${f}`;try{const p=JSON.parse(f);l=p.error_description??p.error??l}catch{}throw new Error(l)}const a=await i.json();if(!or(a))throw new Error("Invalid token exchange response format");return a}catch(i){throw i instanceof Error?i:new Error(`OAuth token exchange failed: ${String(i)}`)}}function or(e){return typeof e=="object"&&e!==null&&"access_token"in e&&typeof e.access_token=="string"}async function ue(e,r){const t=z(e);if(!t)throw new Error(`Unknown OAuth provider: ${e}`);if(!r||typeof r!="string")throw new Error("Access token is required");try{const n=await fetch(t.userInfoUrl,{headers:{Authorization:`Bearer ${r}`,Accept:"application/json"}});if(!n.ok){const o=await n.text();let i=`Failed to fetch user info: ${o}`;try{const a=JSON.parse(o);i=a.error_description??a.error??i}catch{}throw new Error(i)}const s=await n.json();return ir(e,s,r)}catch(n){throw n instanceof Error?n:new Error(`OAuth user info retrieval failed: ${String(n)}`)}}async function ir(e,r,t){switch(e){case"google":return ar(r);case"github":return await cr(r,t);case"apple":return ur(r);case"facebook":return lr(r);default:return fr(r)}}function ar(e){return{id:String(e.sub??e.id??""),email:String(e.email??""),name:String(e.name??""),avatar:typeof e.picture=="string"?e.picture:void 0,emailVerified:!!e.email_verified,rawProfile:e}}async function cr(e,r){let t=typeof e.email=="string"?e.email:void 0,n={...e};if(!t)try{const s=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${r}`}});if(s.ok){const o=await s.json(),i=o.find(a=>a.primary)??o[0];t=(i==null?void 0:i.email)??`${String(e.login??"user")}@users.noreply.github.com`,n={...e,emails:o}}else t=`${String(e.login??"user")}@users.noreply.github.com`}catch{t=`${String(e.login??"user")}@users.noreply.github.com`}return{id:String(e.id??""),email:t??"",name:String(e.name??e.login??""),avatar:typeof e.avatar_url=="string"?e.avatar_url:void 0,emailVerified:!!t,rawProfile:n}}function ur(e){const r=e.name,t=r?`${r.firstName??""} ${r.lastName??""}`.trim():"";return{id:String(e.sub??""),email:String(e.email??""),name:t,emailVerified:!!e.email_verified,rawProfile:e}}function lr(e){var t;const r=e.picture;return{id:String(e.id??""),email:String(e.email??""),name:String(e.name??""),avatar:(t=r==null?void 0:r.data)==null?void 0:t.url,emailVerified:!0,rawProfile:e}}function fr(e){return{id:String(e.id??e.sub??""),email:String(e.email??""),name:String(e.name??e.display_name??e.username??""),avatar:typeof e.avatar=="string"?e.avatar:typeof e.picture=="string"?e.picture:typeof e.avatar_url=="string"?e.avatar_url:void 0,emailVerified:!!(e.email_verified??e.emailVerified??!1),rawProfile:e}}function dr(e){return typeof e=="object"&&e!==null&&"clientId"in e&&typeof e.clientId=="string"}class le{constructor(){x(this,"states",new Map)}set(r,t,n){this.states.set(r,t),this.cleanup()}get(r){const t=this.states.get(r);return t?t.expiresAt<Date.now()?(this.delete(r),null):t:null}delete(r){this.states.delete(r)}cleanup(){const r=Date.now();for(const[t,n]of this.states.entries())n.expiresAt<r&&this.states.delete(t)}}function fe(){return new le}function L(e){return e.success===!0&&e.user!==void 0&&e.session!==void 0}var de=(e=>(e[e.DEBUG=0]="DEBUG",e[e.INFO=1]="INFO",e[e.WARN=2]="WARN",e[e.ERROR=3]="ERROR",e))(de||{});const hr=process.env.NODE_ENV==="development"?0:1;function gr(e={}){const{enabled:r=process.env.NODE_ENV==="development",level:t=hr,context:n,formatter:s=wr}=e,o=a=>r&&a>=t,i=(a,f,l,p)=>({level:a,message:f,timestamp:new Date,context:n,data:l?pr(l):void 0,error:p});return{debug:(a,f)=>{if(o(0)){const l=i(0,a,f);console.debug(s(l))}},info:(a,f)=>{if(o(1)){const l=i(1,a,f);console.info(s(l))}},warn:(a,f)=>{if(o(2)){const l=i(2,a,f);console.warn(s(l))}},error:(a,f)=>{if(o(3)){const l=f instanceof Error?f:void 0,p=f instanceof Error?void 0:f,w=i(3,a,p,l);console.error(s(w)),l&&console.error(l)}}}}function wr(e){const r=e.timestamp.toISOString(),t=de[e.level],n=e.context?`[${e.context}]`:"",s=e.data?` ${JSON.stringify(e.data)}`:"";return`${r} [${t}]${n} ${e.message}${s}`}function pr(e){const r=new Set(["password","token","secret","key","accessToken","refreshToken"]),t={};for(const[n,s]of Object.entries(e))if(r.has(n.toLowerCase()))t[n]="***REDACTED***";else if(typeof s=="string"&&n.toLowerCase().includes("email")){const o=s.split("@");if(o.length===2&&o[0]){const i=o[0].substring(0,3)+"***@"+o[1];t[n]=i}else t[n]=s}else t[n]=s;return t}const I=gr();function Er(e,r,t,n={}){const{enabled:s=!0,maxRetries:o=1,retryDelay:i=1e3,rateLimit:a=3,autoSignOutOnFailure:f=!0,redirectToLogin:l="/login",autoRedirectOnFailure:p=!0}=n;let w=null,k=!1;const R=[],A=[],S=60*1e3;let g=0,O=!1,P=null;const D=2,M=60*1e3;function c(){const y=Date.now();if(O&&P){if(y<P)return!1;O=!1,P=null,g=0}for(;A.length>0;){const E=A[0];if(E!==void 0&&E<y-S)A.shift();else break}return A.length>=a?!1:(A.push(y),!0)}function u(){g++,g>=D&&(O=!0,P=Date.now()+M,process.env.NODE_ENV==="development"&&console.warn("[TokenRefreshManager] Circuit breaker opened - too many consecutive failures"))}function d(){g=0,O=!1,P=null}async function v(y=1){if(!s)return null;if(!c())throw new Error("Rate limit exceeded for token refresh");try{const E=await e();if(E)return d(),_(E),n.onTokenRefreshed&&await Promise.resolve(n.onTokenRefreshed(E)),E;if(u(),y<o)return await G(i*y),v(y+1);throw new Error("Token refresh failed: refresh function returned null")}catch(E){if(u(),y<o&&N(E))return await G(i*y),v(y+1);throw E}}function N(y){if(y instanceof Error){const E=y.message.toLowerCase();if(E.includes("rate limit")||E.includes("too many requests")||E.includes("429")||E.includes("limit:")||E.includes("requests per minute")||E.includes("token_blacklisted")||E.includes("blacklisted")||E.includes("invalid")||E.includes("401")||E.includes("unauthorized")||E.includes("session has been revoked")||E.includes("session expired"))return!1;if(E.includes("network")||E.includes("fetch")||E.includes("timeout"))return!0}return!1}function _(y){const E=[...R];R.length=0;for(const{resolve:b}of E)b(y)}function B(y){const E=[...R];R.length=0;for(const{reject:b}of E)b(y)}function G(y){return new Promise(E=>setTimeout(E,y))}async function K(y){try{if(n.onTokenRefreshFailed&&await Promise.resolve(n.onTokenRefreshFailed(y)),f&&(await t(),await r(),p&&typeof window<"u")){let E=!0;if(n.onBeforeRedirect&&(E=await Promise.resolve(n.onBeforeRedirect(y))),E){const b=new URL(l,window.location.origin);b.searchParams.set("reason","session_expired"),b.searchParams.set("redirect",window.location.pathname+window.location.search),window.location.href=b.toString()}}}catch(E){process.env.NODE_ENV==="development"&&console.error("[TokenRefreshManager] Error in handleRefreshFailure:",E)}}return{async refreshToken(){return s?w||(k=!0,w=v().then(y=>(k=!1,w=null,y)).catch(y=>{throw k=!1,w=null,B(y),K(y).catch(()=>{}),y}),w):null},isRefreshing(){return k},async waitForRefresh(){return w?new Promise((y,E)=>{R.push({resolve:y,reject:E})}):null},clear(){w=null,k=!1,A.length=0,d(),B(new Error("Token refresh manager cleared"))},async handleRefreshFailure(y){return K(y)}}}function mr(){const e=process.env.NODE_ENV==="production";return{cookieName:"__mulguard_session",expiresIn:60*60*24*7,httpOnly:!0,secure:e,sameSite:"lax",path:"/"}}function Sr(){return{enabled:!0,refreshThreshold:300,maxRetries:0,retryDelay:1e3,rateLimit:1,autoSignOutOnFailure:!0,redirectToLogin:"/login",autoRedirectOnFailure:!0}}function yr(){return process.env.NEXT_PUBLIC_URL??(process.env.VERCEL_URL?`https://${process.env.VERCEL_URL}`:"http://localhost:3000")}function Ar(e){const{sessionConfig:r,cacheTtl:t,getSessionAction:n,onSessionExpired:s,onError:o}=e,i=r.cookieName??"__mulguard_session";let a=null;const f=async()=>{const S=Date.now();if(a&&S-a.timestamp<t)return a.session;if(n)try{const g=await n();if(g&&C.validateSessionStructure(g))return a={session:g,timestamp:S},g;g&&!C.validateSessionStructure(g)&&(await p(),a=null)}catch(g){I.debug("getSession error",{error:g}),o&&await o(g instanceof Error?g:new Error(String(g)),"getSession"),a=null}try{const g=await h.getCookie(i);if(g)try{const O=JSON.parse(g);if(C.validateSessionStructure(O))return O.expiresAt&&new Date(O.expiresAt)<new Date?(s&&await s(O),await p(),a=null,null):(a={session:O,timestamp:S},O);await p(),a=null}catch{await p(),a=null}}catch(g){const O=g instanceof Error?g.message:String(g);!O.includes("request scope")&&!O.includes("cookies")&&(I.warn("getSession cookie error",{error:g}),o&&await o(g instanceof Error?g:new Error(String(g)),"getSession.cookie"))}return null},l=async S=>{if(!C.validateSessionStructure(S))return{success:!1,error:"Invalid session structure"};try{const g=typeof S=="object"&&"token"in S?String(S.token):JSON.stringify(S),O=h.buildCookieOptions(i,g,r),P=await h.setCookie(O);return P.success&&(a={session:S,timestamp:Date.now()}),P}catch(g){const O=g instanceof Error?g.message:"Failed to set session";return I.error("setSession error",{error:g}),o&&await o(g instanceof Error?g:new Error(String(g)),"setSession"),{success:!1,error:O}}},p=async()=>{try{await h.deleteCookie(i,{path:r.path,domain:r.domain}),a=null}catch(S){I.warn("clearSessionCookie error",{error:S})}},w=async()=>{const S=await f();return S!=null&&S.accessToken&&typeof S.accessToken=="string"?S.accessToken:null};return{getSession:f,setSession:l,clearSessionCookie:p,getAccessToken:w,getRefreshToken:async()=>{const S=await f();return S!=null&&S.refreshToken&&typeof S.refreshToken=="string"?S.refreshToken:null},hasValidTokens:async()=>!!await w(),clearCache:()=>{a=null},getSessionConfig:()=>({cookieName:i,config:r})}}function Rr(e){return async r=>{try{if(!r||typeof r!="object")return{success:!1,error:"Invalid credentials",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(!r.email||typeof r.email!="string")return{success:!1,error:"Email is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const t=$(r.email);if(!Z(t))return{success:!1,error:t.error??"Invalid email format",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(!r.password||typeof r.password!="string")return{success:!1,error:"Password is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(r.password.length>128)return{success:!1,error:"Invalid credentials",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const n={email:t.sanitized,password:r.password},s=await e.actions.signIn.email(n);if(L(s)){const o=await e.saveSessionAfterAuth(s);!o.success&&o.warning&&I.warn("Session save warning",{warning:o.warning})}return s.success?I.info("Sign in successful",{email:n.email.substring(0,3)+"***"}):I.warn("Sign in failed",{email:n.email.substring(0,3)+"***",errorCode:s.errorCode}),s}catch(t){const n=t instanceof Error?t.message:"Sign in failed";return I.error("Sign in error",{error:n,context:"signIn.email"}),e.onError&&await e.onError(t instanceof Error?t:new Error(String(t)),"signIn.email"),{success:!1,error:"Sign in failed. Please try again.",errorCode:h.AuthErrorCode.UNKNOWN_ERROR}}}}function vr(e,r){return async t=>{if(!t||typeof t!="string")throw new Error("Provider is required");const n=q(t,{maxLength:50,allowHtml:!1,required:!0});if(!n.valid||!n.sanitized)throw new Error("Invalid provider");const s=n.sanitized.toLowerCase();if(!e.actions.signIn.oauth)throw new Error("OAuth sign in is not configured. Either provide oauth action in signIn, or configure providers.oauth in config.");const o=await e.actions.signIn.oauth(s);return await r(o.state,s),I.info("OAuth sign in initiated",{provider:s}),o}}function kr(e){return async(r,t)=>{if(!r||typeof r!="string")return{success:!1,error:"Email is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const n=$(r);if(!Z(n))return{success:!1,error:n.error??"Invalid email format",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(t!==void 0&&(typeof t!="string"||t.length<4||t.length>10))return{success:!1,error:"Invalid OTP code format",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(!e.actions.signIn.otp)return{success:!1,error:"OTP sign in is not configured",errorCode:h.AuthErrorCode.VALIDATION_ERROR};try{const s=await e.actions.signIn.otp(n.sanitized,t);if(L(s)){const o=await e.saveSessionAfterAuth(s);!o.success&&o.warning&&I.warn("Session save warning",{warning:o.warning})}return s.success?I.info("OTP sign in successful",{email:n.sanitized.substring(0,3)+"***"}):I.warn("OTP sign in failed",{email:n.sanitized.substring(0,3)+"***"}),s}catch(s){return I.error("OTP sign in error",{error:s instanceof Error?s.message:"Unknown error",context:"signIn.otp"}),e.onError&&await e.onError(s instanceof Error?s:new Error(String(s)),"signIn.otp"),{success:!1,error:"OTP sign in failed. Please try again.",errorCode:h.AuthErrorCode.UNKNOWN_ERROR}}}}function Cr(e){return async r=>{if(!e.actions.signIn.passkey)throw new Error("PassKey sign in is not configured. Provide passkey action in signIn.");try{const t=await e.actions.signIn.passkey(r);if(L(t)){const n=await e.saveSessionAfterAuth(t);!n.success&&n.warning&&I.warn("Session save warning",{warning:n.warning})}return t}catch(t){return e.onError&&await e.onError(t instanceof Error?t:new Error(String(t)),"signIn.passkey"),{success:!1,error:t instanceof Error?t.message:"PassKey sign in failed"}}}}function Tr(e,r){const t=Rr(e),n=vr(e,r),s=kr(e),o=Cr(e);return Object.assign(async(f,l)=>{if(!f||typeof f!="string")throw new Error("Provider is required");const p=q(f,{maxLength:50,allowHtml:!1,required:!0});if(!p.valid||!p.sanitized)throw new Error("Invalid provider");const w=p.sanitized.toLowerCase();if(w==="google"||w==="github"||w==="apple"||w==="facebook"||typeof w=="string"&&!["credentials","otp","passkey"].includes(w))return n(w);if(w==="credentials")return!l||!("email"in l)||!("password"in l)?{success:!1,error:"Credentials are required",errorCode:h.AuthErrorCode.VALIDATION_ERROR}:t(l);if(w==="otp"){if(!l||!("email"in l))return{success:!1,error:"Email is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const k=l;return s(k.email,k.code)}return w==="passkey"?o(l):{success:!1,error:"Invalid provider",errorCode:h.AuthErrorCode.VALIDATION_ERROR}},{email:t,oauth:e.actions.signIn.oauth?n:void 0,passkey:e.actions.signIn.passkey?o:void 0,otp:e.actions.signIn.otp?s:void 0})}function Or(e){return async r=>{if(!e.actions.signUp)throw new Error("Sign up is not configured. Provide signUp action in config.");try{const t=await e.actions.signUp(r);if(L(t)){const n=await e.saveSessionAfterAuth(t);!n.success&&n.warning&&I.warn("Session save warning",{warning:n.warning})}return t}catch(t){return e.onError&&await e.onError(t instanceof Error?t:new Error(String(t)),"signUp"),{success:!1,error:t instanceof Error?t.message:"Sign up failed"}}}}function Ir(e,r){return async(t,n,s)=>{const o=e.oauthProviders[t];if(!o)return{success:!1,error:`OAuth provider "${t}" is not configured`,errorCode:h.AuthErrorCode.VALIDATION_ERROR};try{const i=o.redirectUri??`${e.baseUrl}/api/auth/callback/${t}`,a=await ce(t,o,n,i),f=await ue(t,a.access_token),l={id:f.id,email:f.email,name:f.name,avatar:f.avatar,emailVerified:f.emailVerified,provider:t,accessToken:a.access_token,refreshToken:a.refresh_token,tokens:{access_token:a.access_token,refresh_token:a.refresh_token,expires_in:a.expires_in,token_type:a.token_type,id_token:a.id_token},rawProfile:f.rawProfile};if(e.callbacks.onOAuthUser){const p=await X(e.callbacks.onOAuthUser,[l,t],e.onError);if(!p)return{success:!1,error:"Failed to create or retrieve user",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const w=e.createSession(p,l,a);return await e.saveSession(w),e.callbacks.onSignIn&&await X(e.callbacks.onSignIn,[w.user,w],e.onError),{success:!0,user:w.user,session:w}}return{success:!1,error:"OAuth user callback not implemented. Provide onOAuthUser callback or implement oauthCallback action.",errorCode:h.AuthErrorCode.VALIDATION_ERROR}}catch(i){return I.error("OAuth callback failed",{provider:t,error:i}),{success:!1,error:i instanceof Error?i.message:"OAuth callback failed",errorCode:h.AuthErrorCode.NETWORK_ERROR}}}}async function X(e,r,t){if(e)try{return await e(...r)}catch(n){throw t&&await t(n instanceof Error?n:new Error(String(n)),"callback"),n}}function Pr(e,r,t,n){if(Object.keys(e).length!==0)return async s=>{const o=e[s];if(!o)throw new Error(`OAuth provider "${s}" is not configured. Add it to providers.oauth in config.`);if(!o.clientId)throw new Error(`OAuth provider "${s}" is missing clientId`);const i=t();return{url:n(s,o,r,i),state:i}}}function _r(e){var D,M;const r={...mr(),...e.session},t=e.actions,n=e.callbacks||{},s=((D=e.providers)==null?void 0:D.oauth)||{},o=yr(),i={...Sr(),...e.tokenRefresh},a=((M=e.session)==null?void 0:M.cacheTtl)??e.sessionCacheTtl??5e3,f=e.oauthStateStore||fe(),l={...t},p=async(c,u)=>{const d={provider:u,expiresAt:Date.now()+6e5};await Promise.resolve(f.set(c,d,10*60*1e3)),f.cleanup&&await Promise.resolve(f.cleanup())},w=async(c,u)=>{const d=await Promise.resolve(f.get(c));return d?d.expiresAt<Date.now()?(await Promise.resolve(f.delete(c)),!1):d.provider!==u?!1:(await Promise.resolve(f.delete(c)),!0):!1},k=Pr(s,o,se,ae);if(k&&!l.signIn.oauth){const c=l.signIn;l.signIn={...c,oauth:async u=>{const d=await k(u);return await p(d.state,u),d}}}if(!l.signIn||!l.signIn.email)throw new Error("mulguard: signIn.email action is required");const R=async(c,...u)=>{if(c)try{return await c(...u)}catch(d){throw n.onError&&await n.onError(d instanceof Error?d:new Error(String(d)),"callback"),d}},A=Ar({sessionConfig:r,cacheTtl:a,getSessionAction:t.getSession,onSessionExpired:n.onSessionExpired,onError:n.onError}),S=async c=>{if(!L(c)||!c.session)return{success:!0};const u=await A.setSession(c.session);return c.user&&n.onSignIn&&await R(n.onSignIn,c.user,c.session),u};if(Object.keys(s).length>0&&!l.oauthCallback){const c=Ir({oauthProviders:s,baseUrl:o,callbacks:n,createSession:(u,d,v)=>({user:{...u,avatar:d.avatar,emailVerified:d.emailVerified},expiresAt:new Date(Date.now()+(r.expiresIn||604800)*1e3),accessToken:v.access_token,refreshToken:v.refresh_token,tokenType:"Bearer",expiresIn:v.expires_in}),saveSession:async u=>{await A.setSession(u)},onError:n.onError});l.oauthCallback=c}const g=Tr({actions:l,callbacks:n,saveSessionAfterAuth:S,onError:n.onError},p),O=Or({actions:l,callbacks:n,saveSessionAfterAuth:S,onError:n.onError}),P={async getSession(){return await A.getSession()},async getAccessToken(){return await A.getAccessToken()},async getRefreshToken(){return await A.getRefreshToken()},async hasValidTokens(){return await A.hasValidTokens()},signIn:g,async signUp(c){if(!O)throw new Error("Sign up is not configured. Provide signUp action in config.");return await O(c)},async signOut(){try{const c=await this.getSession(),u=c==null?void 0:c.user;return t.signOut&&await t.signOut(),await A.clearSessionCookie(),A.clearCache(),u&&n.onSignOut&&await R(n.onSignOut,u),{success:!0}}catch(c){return await A.clearSessionCookie(),A.clearCache(),n.onError&&await R(n.onError,c instanceof Error?c:new Error(String(c)),"signOut"),{success:!1,error:c instanceof Error?c.message:"Sign out failed"}}},async resetPassword(c){if(!t.resetPassword)throw new Error("Password reset is not configured. Provide resetPassword action in config.");try{return await t.resetPassword(c)}catch(u){return n.onError&&await R(n.onError,u instanceof Error?u:new Error(String(u)),"resetPassword"),{success:!1,error:u instanceof Error?u.message:"Password reset failed"}}},async verifyEmail(c){if(!t.verifyEmail)throw new Error("Email verification is not configured. Provide verifyEmail action in config.");try{return await t.verifyEmail(c)}catch(u){return n.onError&&await R(n.onError,u instanceof Error?u:new Error(String(u)),"verifyEmail"),{success:!1,error:u instanceof Error?u.message:"Email verification failed"}}},async refreshSession(){if(!t.refreshSession)return this.getSession();try{const c=await t.refreshSession();if(c&&C.validateSessionStructure(c)){if(await A.setSession(c),n.onSessionUpdate){const u=await R(n.onSessionUpdate,c);if(u&&C.validateSessionStructure(u)){if(await A.setSession(u),n.onTokenRefresh){const d=await this.getSession();d&&await R(n.onTokenRefresh,d,u)}return u}}if(n.onTokenRefresh){const u=await this.getSession();u&&await R(n.onTokenRefresh,u,c)}return c}else if(c&&!C.validateSessionStructure(c))return await A.clearSessionCookie(),A.clearCache(),null;return null}catch(c){return await A.clearSessionCookie(),A.clearCache(),n.onError&&await R(n.onError,c instanceof Error?c:new Error(String(c)),"refreshSession"),null}},async oauthCallback(c,u,d){if(!l.oauthCallback)throw new Error("OAuth callback is not configured. Either provide oauthCallback action, or configure providers.oauth in config.");if(!u||!d)return{success:!1,error:"Missing required OAuth parameters (code or state)",errorCode:h.AuthErrorCode.VALIDATION_ERROR};let v=c;if(!v){const _=await Promise.resolve(f.get(d));if(_&&_.provider)v=_.provider;else return{success:!1,error:"Provider is required and could not be extracted from state",errorCode:h.AuthErrorCode.VALIDATION_ERROR}}if(!await w(d,v))return{success:!1,error:"Invalid or expired state parameter",errorCode:h.AuthErrorCode.VALIDATION_ERROR};try{return await l.oauthCallback(v,u,d)}catch(_){return n.onError&&await R(n.onError,_ instanceof Error?_:new Error(String(_)),"oauthCallback"),{success:!1,error:_ instanceof Error?_.message:"OAuth callback failed",errorCode:h.AuthErrorCode.NETWORK_ERROR}}},async verify2FA(c,u){if(!t.verify2FA)throw new Error("2FA verification is not configured. Provide verify2FA action in config.");try{const d=await t.verify2FA(c);if(d.success&&d.session&&!(u!=null&&u.skipCookieSave)){const v=await S(d);v.success||(process.env.NODE_ENV==="development"&&I.debug("Failed to save session cookie after verify2FA",{error:v.error,warning:v.warning}),n.onError&&await R(n.onError,new Error(v.warning||v.error||"Failed to save session cookie"),"verify2FA.setSession"))}return d}catch(d){return n.onError&&await R(n.onError,d instanceof Error?d:new Error(String(d)),"verify2FA"),{success:!1,error:d instanceof Error?d.message:"2FA verification failed",errorCode:h.AuthErrorCode.TWO_FA_REQUIRED}}},async setSession(c){return await A.setSession(c)},_getSessionConfig(){return A.getSessionConfig()},_getCallbacks(){return n},passkey:t.passkey?{register:t.passkey.register,authenticate:async c=>{var u;if(!((u=t.passkey)!=null&&u.authenticate))throw new Error("PassKey authenticate is not configured.");try{const d=await t.passkey.authenticate(c);return d.success&&d.session&&await S(d),d}catch(d){return n.onError&&await R(n.onError,d instanceof Error?d:new Error(String(d)),"passkey.authenticate"),{success:!1,error:d instanceof Error?d.message:"PassKey authentication failed"}}},list:t.passkey.list?async()=>{var u;if(!((u=t.passkey)!=null&&u.list))throw new Error("PassKey list is not configured.");return[...await t.passkey.list()]}:void 0,remove:t.passkey.remove}:void 0,twoFactor:t.twoFactor?{enable:t.twoFactor.enable,verify:t.twoFactor.verify,disable:t.twoFactor.disable,generateBackupCodes:t.twoFactor.generateBackupCodes,isEnabled:t.twoFactor.isEnabled,verify2FA:async c=>{var d;const u=((d=t.twoFactor)==null?void 0:d.verify2FA)||t.verify2FA;if(!u)throw new Error("2FA verification is not configured. Provide verify2FA action in config.");try{const v=await u(c);if(v.success&&v.session){const N=await S(v);N.success||(process.env.NODE_ENV==="development"&&I.debug("Failed to save session cookie after twoFactor.verify2FA",{error:N.error,warning:N.warning}),n.onError&&await R(n.onError,new Error(N.warning||N.error||"Failed to save session cookie"),"twoFactor.verify2FA.setSession"))}return v}catch(v){return n.onError&&await R(n.onError,v instanceof Error?v:new Error(String(v)),"twoFactor.verify2FA"),{success:!1,error:v instanceof Error?v.message:"2FA verification failed",errorCode:h.AuthErrorCode.UNKNOWN_ERROR}}}}:void 0,signInMethods:{email:c=>g.email(c),oauth:c=>{var u;return((u=g.oauth)==null?void 0:u.call(g,c))||Promise.reject(new Error("OAuth not configured"))},passkey:c=>{var u;return((u=g.passkey)==null?void 0:u.call(g,c))||Promise.reject(new Error("Passkey not configured"))},otp:(c,u)=>{var d;return((d=g.otp)==null?void 0:d.call(g,c,u))||Promise.reject(new Error("OTP not configured"))}}};if(t.refreshSession){const c=Er(async()=>await P.refreshSession(),async()=>await P.signOut(),async()=>{await A.clearSessionCookie(),A.clearCache()},{...i,onTokenRefreshed:i.onTokenRefreshed,onTokenRefreshFailed:i.onTokenRefreshFailed,onBeforeRedirect:i.onBeforeRedirect});P._tokenRefreshManager=c,P._getTokenRefreshManager=()=>c}return P}function Nr(e){return{GET:async r=>J(r,e,"GET"),POST:async r=>J(r,e,"POST")}}async function J(e,r,t){const n=new URL(e.url),s=Ur(n.pathname),o=s.split("/").filter(Boolean);try{return t==="GET"?await br(e,r,s,o,n):t==="POST"?await xr(e,r,s,o,n):T("Method not allowed",405)}catch(i){return T(i instanceof Error?i.message:"Request failed",500)}}function Ur(e){return e.replace(/^\/api\/auth/,"")||"/session"}async function br(e,r,t,n,s){if(t==="/session"||t==="/"){const o=await r.getSession();return m.NextResponse.json({session:o})}return t==="/providers"?m.NextResponse.json({providers:{email:!!r.signIn.email,oauth:!!r.signIn.oauth,passkey:!!r.signIn.passkey}}):he(t,n)?await ge(e,r,t,n,s,"GET"):T("Not found",404)}async function xr(e,r,t,n,s){const o=await Fr(e);return t==="/sign-in"||n[0]==="sign-in"?await Dr(r,o):t==="/sign-up"||n[0]==="sign-up"?await Mr(r,o):t==="/sign-out"||n[0]==="sign-out"?await Vr(r):t==="/reset-password"||n[0]==="reset-password"?await zr(r,o):t==="/verify-email"||n[0]==="verify-email"?await jr(r,o):t==="/refresh"||n[0]==="refresh"?await $r(r):he(t,n)?await ge(e,r,t,n,s,"POST",o):t.startsWith("/passkey")?await Hr(r,t,n,o):t==="/verify-2fa"||n[0]==="verify-2fa"?await qr(r,o):t.startsWith("/two-factor")?await Wr(r,n,o):T("Not found",404)}async function Fr(e){try{return await e.json()}catch{return{}}}function he(e,r){return e==="/callback"||e.startsWith("/oauth/callback")||r[0]==="oauth"&&r[1]==="callback"||r[0]==="callback"}async function ge(e,r,t,n,s,o,i){if(!r.oauthCallback)return o==="GET"?V(e.url,"oauth_not_configured"):T("OAuth callback is not configured",400);const a=Lr(n,s,i),f=(i==null?void 0:i.code)??s.searchParams.get("code"),l=(i==null?void 0:i.state)??s.searchParams.get("state");if(!f||!l)return o==="GET"?V(e.url,"oauth_missing_params"):T("Missing required OAuth parameters. Code and state are required.",400);try{const p=await r.oauthCallback(a??"",f,l);return o==="GET"?p.success?Br(e.url,s.searchParams.get("callbackUrl")):V(e.url,p.error??"oauth_failed"):m.NextResponse.json(p)}catch(p){return o==="GET"?V(e.url,p instanceof Error?p.message:"oauth_error"):T(p instanceof Error?p.message:"OAuth callback failed",500)}}function Lr(e,r,t){return t!=null&&t.provider?t.provider:e[0]==="callback"&&e[1]?e[1]:e[0]==="oauth"&&e[1]==="callback"&&e[2]?e[2]:r.searchParams.get("provider")}async function Dr(e,r){if(r.provider==="email"&&r.email&&r.password){const t={email:r.email,password:r.password},n=await e.signIn.email(t);return m.NextResponse.json(n)}if(r.provider==="oauth"&&r.providerName){if(!e.signIn.oauth)return T("OAuth is not configured",400);const t=await e.signIn.oauth(r.providerName);return m.NextResponse.json(t)}if(r.provider==="passkey"){if(!e.signIn.passkey)return T("PassKey is not configured",400);const t=await e.signIn.passkey(r.options);return m.NextResponse.json(t)}return T("Invalid sign in request",400)}async function Mr(e,r){if(!e.signUp)return T("Sign up is not configured",400);const t=await e.signUp(r);return m.NextResponse.json(t)}async function Vr(e){const r=await e.signOut();return m.NextResponse.json(r)}async function zr(e,r){if(!e.resetPassword)return T("Password reset is not configured",400);if(!r.email||typeof r.email!="string")return T("Email is required",400);const t=await e.resetPassword(r.email);return m.NextResponse.json(t)}async function jr(e,r){if(!e.verifyEmail)return T("Email verification is not configured",400);if(!r.token||typeof r.token!="string")return T("Token is required",400);const t=await e.verifyEmail(r.token);return m.NextResponse.json(t)}async function $r(e){if(!e.refreshSession){const t=await e.getSession();return m.NextResponse.json({session:t})}const r=await e.refreshSession();return m.NextResponse.json({session:r})}async function qr(e,r){if(!e.verify2FA)return T("2FA verification is not configured",400);if(!r.email||!r.userId||!r.code)return T("Missing required parameters. Email, userId, and code are required.",400);const t={email:r.email,userId:r.userId,code:r.code},n=await e.verify2FA(t);return m.NextResponse.json(n)}async function Hr(e,r,t,n){if(!e.passkey)return T("PassKey is not configured",400);const s=t[1];if(s==="register"&&e.passkey.register){const o=await e.passkey.register(n.options);return m.NextResponse.json(o)}if(s==="list"&&e.passkey.list){const o=await e.passkey.list();return m.NextResponse.json(o)}if(s==="remove"&&e.passkey.remove){if(!n.passkeyId||typeof n.passkeyId!="string")return T("Passkey ID is required",400);const o=await e.passkey.remove(n.passkeyId);return m.NextResponse.json(o)}return T("Invalid Passkey request",400)}async function Wr(e,r,t){if(!e.twoFactor)return T("Two-Factor Authentication is not configured",400);const n=r[1];if(n==="enable"&&e.twoFactor.enable){const s=await e.twoFactor.enable();return m.NextResponse.json(s)}if(n==="verify"&&e.twoFactor.verify){if(!t.code||typeof t.code!="string")return T("Code is required",400);const s=await e.twoFactor.verify(t.code);return m.NextResponse.json(s)}if(n==="disable"&&e.twoFactor.disable){const s=await e.twoFactor.disable();return m.NextResponse.json(s)}if(n==="backup-codes"&&e.twoFactor.generateBackupCodes){const s=await e.twoFactor.generateBackupCodes();return m.NextResponse.json(s)}if(n==="is-enabled"&&e.twoFactor.isEnabled){const s=await e.twoFactor.isEnabled();return m.NextResponse.json({enabled:s})}return T("Invalid two-factor request",400)}function T(e,r){return m.NextResponse.json({success:!1,error:e},{status:r})}function V(e,r){return m.NextResponse.redirect(new URL(`/login?error=${encodeURIComponent(r)}`,e))}function Br(e,r){const t=r??"/";return m.NextResponse.redirect(new URL(t,e))}function Gr(e){return async r=>{const{method:t,nextUrl:n}=r,o=n.pathname.replace(/^\/api\/auth/,"")||"/";try{let i;if(t!=="GET"&&t!=="HEAD")try{i=await r.json()}catch{}const a=Object.fromEntries(n.searchParams.entries()),f=await fetch(`${process.env.NEXT_PUBLIC_API_URL||""}/api/auth${o}${Object.keys(a).length>0?`?${new URLSearchParams(a).toString()}`:""}`,{method:t,headers:{"Content-Type":"application/json",...Object.fromEntries(r.headers.entries())},body:i?JSON.stringify(i):void 0}),l=await f.json();return m.NextResponse.json(l,{status:f.status,headers:{...Object.fromEntries(f.headers.entries())}})}catch(i){return console.error("API handler error:",i),m.NextResponse.json({success:!1,error:i instanceof Error?i.message:"Internal server error"},{status:500})}}}function Kr(e){return async r=>{const{searchParams:t}=r.nextUrl,n=t.get("provider"),s=t.get("code"),o=t.get("state");if(!n||!s||!o)return m.NextResponse.redirect(new URL("/login?error=oauth_missing_params",r.url));try{if(!e.oauthCallback)return m.NextResponse.redirect(new URL("/login?error=oauth_not_configured",r.url));const i=await e.oauthCallback(n,s,o);if(i.success){const a=t.get("callbackUrl")||"/";return m.NextResponse.redirect(new URL(a,r.url))}else{const a=i.errorCode?`${encodeURIComponent(i.error||"oauth_failed")}&code=${i.errorCode}`:encodeURIComponent(i.error||"oauth_failed");return m.NextResponse.redirect(new URL(`/login?error=${a}`,r.url))}}catch(i){return process.env.NODE_ENV==="development"&&console.error("[Mulguard] OAuth callback error:",i),m.NextResponse.redirect(new URL(`/login?error=${encodeURIComponent(i instanceof Error?i.message:"oauth_error")}`,r.url))}}}function U(e,r){const t=j({"X-Frame-Options":"SAMEORIGIN"});for(const[n,s]of Object.entries(t))s&&typeof s=="string"&&r.headers.set(n,s);return r}function Xr(){return async e=>{const r=m.NextResponse.next();return U(e,r)}}function Jr(e,r={}){const{protectedRoutes:t=[],publicRoutes:n=[],redirectTo:s="/login",redirectIfAuthenticated:o}=r;return async i=>{const{pathname:a}=i.nextUrl,f=t.some(w=>a.startsWith(w));let l=null;try{l=await e.getSession()}catch(w){console.error("Middleware: Failed to get session:",w)}if(f&&!l){const w=i.nextUrl.clone();return w.pathname=s,w.searchParams.set("callbackUrl",a),m.NextResponse.redirect(w)}if(o&&l&&(a.startsWith("/login")||a.startsWith("/register"))){const k=i.nextUrl.clone();k.pathname=o;const R=m.NextResponse.redirect(k);return U(i,R)}const p=m.NextResponse.next();return U(i,p)}}async function Yr(e,r){var t;try{const n=await e.getSession();return n?((t=n.user.roles)==null?void 0:t.includes(r))??!1:!1}catch{return!1}}function Qr(e){const{auth:r,protectedRoutes:t=[],publicRoutes:n=[],redirectTo:s="/login",redirectIfAuthenticated:o,apiPrefix:i="/api/auth"}=e;return async a=>{const{pathname:f}=a.nextUrl;if(f.startsWith(i)){const k=m.NextResponse.next();return U(a,k)}const l=t.some(k=>f.startsWith(k));let p=null;if(l||o)try{p=await r.getSession()}catch(k){console.error("Middleware: Failed to get session:",k)}if(l&&!p){const k=a.nextUrl.clone();k.pathname=s,k.searchParams.set("callbackUrl",f);const R=m.NextResponse.redirect(k);return U(a,R)}if(o&&p&&(f.startsWith("/login")||f.startsWith("/register"))){const R=a.nextUrl.clone();R.pathname=o;const A=m.NextResponse.redirect(R);return U(a,A)}const w=m.NextResponse.next();return U(a,w)}}async function Zr(e,r){var t;try{const n=await e.getSession();return n?((t=n.user.roles)==null?void 0:t.includes(r))??!1:!1}catch{return!1}}exports.buildCookieOptions=h.buildCookieOptions;exports.deleteCookie=h.deleteCookie;exports.getCookie=h.getCookie;exports.setCookie=h.setCookie;exports.signInEmailAction=h.signInEmailAction;exports.signOutAction=h.signOutAction;exports.signUpAction=h.signUpAction;exports.verify2FAAction=h.verify2FAAction;exports.createServerAuthMiddleware=C.createAuthMiddleware;exports.createServerHelpers=C.createServerHelpers;exports.createServerUtils=C.createServerUtils;exports.createSessionManager=C.createSessionManager;exports.deleteOAuthStateCookie=C.deleteOAuthStateCookie;exports.getCurrentUser=C.getCurrentUser;exports.getOAuthStateCookie=C.getOAuthStateCookie;exports.getServerSession=C.getServerSession;exports.getSessionTimeUntilExpiry=C.getSessionTimeUntilExpiry;exports.isSessionExpiredNullable=C.isSessionExpiredNullable;exports.isSessionExpiringSoon=C.isSessionExpiringSoon;exports.isSessionValid=C.isSessionValid;exports.refreshSession=C.refreshSession;exports.requireAuth=C.requireAuth;exports.requireRole=C.requireRole;exports.requireServerAuthMiddleware=C.requireAuthMiddleware;exports.requireServerRoleMiddleware=C.requireRoleMiddleware;exports.storeOAuthStateCookie=C.storeOAuthStateCookie;exports.validateSessionStructure=C.validateSessionStructure;exports.CSRFProtection=re;exports.DEFAULT_SECURITY_HEADERS=Q;exports.MemoryCSRFStore=ee;exports.MemoryOAuthStateStore=le;exports.RateLimiter=Y;exports.applySecurityHeaders=Se;exports.buildOAuthAuthorizationUrl=ae;exports.checkRole=Yr;exports.checkRoleProxy=Zr;exports.containsXSSPattern=We;exports.createApiHandler=Gr;exports.createAuthMiddleware=Jr;exports.createCSRFProtection=$e;exports.createMemoryOAuthStateStore=fe;exports.createOAuthCallbackHandler=Kr;exports.createProxyMiddleware=Qr;exports.createRateLimiter=me;exports.createSecurityMiddleware=Xr;exports.escapeHTML=te;exports.exchangeOAuthCode=ce;exports.generateCSRFToken=se;exports.generateToken=H;exports.getErrorCode=Qe;exports.getErrorMessage=Ye;exports.getOAuthUserInfo=ue;exports.getProviderMetadata=z;exports.getSecurityHeaders=j;exports.getUserFriendlyError=tr;exports.hasErrorCode=er;exports.isAuthError=oe;exports.isAuthSuccess=Ze;exports.isOAuthProviderConfig=dr;exports.isRetryableError=rr;exports.isSupportedProvider=sr;exports.isTwoFactorRequired=Je;exports.isValidCSRFToken=Be;exports.isValidEmail=Xe;exports.isValidInput=je;exports.isValidName=Ne;exports.isValidPassword=Ie;exports.isValidToken=Ve;exports.isValidURL=xe;exports.mulguard=_r;exports.sanitizeHTML=qe;exports.sanitizeInput=Ge;exports.sanitizeUserInput=He;exports.signIn=nr;exports.toNextJsHandler=Nr;exports.validateAndSanitizeEmail=$;exports.validateAndSanitizeInput=q;exports.validateAndSanitizeName=_e;exports.validateAndSanitizePassword=Te;exports.validateCSRFToken=W;exports.validateToken=Me;exports.validateURL=be;exports.withSecurityHeaders=U;
|
|
1
|
+
"use strict";var we=Object.defineProperty;var pe=(e,r,t)=>r in e?we(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var x=(e,r,t)=>pe(e,typeof r!="symbol"?r+"":r,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("../actions-CExpv_dD.js"),C=require("../oauth-state-CzIWQq3s.js"),m=require("next/server"),F=typeof globalThis=="object"&&"crypto"in globalThis?globalThis.crypto:void 0;/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function Ee(e=32){if(F&&typeof F.getRandomValues=="function")return F.getRandomValues(new Uint8Array(e));if(F&&typeof F.randomBytes=="function")return Uint8Array.from(F.randomBytes(e));throw new Error("crypto.getRandomValues must be defined")}class Y{constructor(r){x(this,"attempts",new Map);x(this,"config");this.config=r}check(r){const t=Date.now(),n=this.attempts.get(r);return!n||n.resetAt<t?(this.attempts.set(r,{count:1,resetAt:t+this.config.windowMs}),{allowed:!0,remaining:this.config.maxAttempts-1,resetAt:new Date(t+this.config.windowMs)}):n.count>=this.config.maxAttempts?{allowed:!1,remaining:0,resetAt:new Date(n.resetAt)}:(n.count++,{allowed:!0,remaining:this.config.maxAttempts-n.count,resetAt:new Date(n.resetAt)})}reset(r){this.attempts.delete(r)}clear(){this.attempts.clear()}}function me(e){return new Y(e)}const Q={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"1; mode=block","Strict-Transport-Security":"max-age=31536000; includeSubDomains","Content-Security-Policy":"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"geolocation=(), microphone=(), camera=()"};function j(e){return{...Q,...e}}function ye(e,r){const t=j(r);for(const[n,s]of Object.entries(t))s&&e.set(n,s)}const Se=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,Ae=254;function $(e){var t;if(typeof e!="string"||!e)return{valid:!1,error:"Email is required"};const r=e.trim().toLowerCase();return Se.test(r)?r.length>Ae?{valid:!1,error:"Email is too long"}:r.includes("..")||r.startsWith(".")||r.endsWith(".")?{valid:!1,error:"Invalid email format"}:(t=r.split("@")[1])!=null&&t.includes("..")?{valid:!1,error:"Invalid email format"}:{valid:!0,sanitized:r}:{valid:!1,error:"Invalid email format"}}function Z(e){return e.valid===!0&&e.sanitized!==void 0}const Re=new Set(["password","12345678","qwerty","abc123","password123","123456789","1234567890","letmein","welcome","monkey","dragon","master","sunshine","princess","football","admin","root","test","guest","user"]),ke=/012|123|234|345|456|567|678|789|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz/i,ve=8,Ce=128;function Oe(e,r=ve){if(typeof e!="string"||!e)return{valid:!1,error:"Password is required"};if(e.length<r)return{valid:!1,error:`Password must be at least ${r} characters`};if(e.length>Ce)return{valid:!1,error:"Password is too long"};const t=e.toLowerCase();if(Re.has(t))return{valid:!1,error:"Password is too common"};if(/(.)\1{3,}/.test(e))return{valid:!1,error:"Password contains too many repeated characters"};if(ke.test(e))return{valid:!1,error:"Password contains sequential characters"};const n=Te(e);return{valid:!0,sanitized:e,strength:n}}function Te(e){let r=0;return e.length>=12?r+=2:e.length>=8&&(r+=1),/[a-z]/.test(e)&&(r+=1),/[A-Z]/.test(e)&&(r+=1),/[0-9]/.test(e)&&(r+=1),/[^a-zA-Z0-9]/.test(e)&&(r+=1),r>=5?"strong":r>=3?"medium":"weak"}function Ie(e){return e.valid===!0&&e.sanitized!==void 0}const _e=100;function Pe(e){if(typeof e!="string"||!e)return{valid:!1,error:"Name is required"};const r=e.trim();if(r.length<1)return{valid:!1,error:"Name cannot be empty"};if(r.length>_e)return{valid:!1,error:"Name is too long"};const t=r.replace(/[<>"']/g,"");return t.length===0?{valid:!1,error:"Name contains only invalid characters"}:{valid:!0,sanitized:t}}function Ne(e){return e.valid===!0&&e.sanitized!==void 0}const Ue=new Set(["http:","https:"]);function be(e){if(typeof e!="string"||!e)return{valid:!1,error:"URL is required"};try{const r=new URL(e);return Ue.has(r.protocol)?{valid:!0,sanitized:e}:{valid:!1,error:"URL must use http or https protocol"}}catch{return{valid:!1,error:"Invalid URL format"}}}function xe(e){return e.valid===!0&&e.sanitized!==void 0}const Fe=16,Le=512,De=/^[A-Za-z0-9_-]+$/;function Me(e,r=Fe){return typeof e!="string"||!e?{valid:!1,error:"Token is required"}:e.length<r?{valid:!1,error:"Token is too short"}:e.length>Le?{valid:!1,error:"Token is too long"}:De.test(e)?/(.)\1{10,}/.test(e)?{valid:!1,error:"Token contains suspicious pattern"}:{valid:!0,sanitized:e}:{valid:!1,error:"Invalid token format"}}function Ve(e){return e.valid===!0&&e.sanitized!==void 0}const ze=1e3;function q(e,r){const{maxLength:t=ze,allowHtml:n=!1,required:s=!0}=r??{};if(s&&(typeof e!="string"||!e||e.trim().length===0))return{valid:!1,error:"Input is required"};if(typeof e!="string"||!e)return{valid:!0,sanitized:""};let o=e.trim();return o.length>t?{valid:!1,error:`Input must be less than ${t} characters`}:(n||(o=o.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")),o=o.replace(/[\x00-\x1F\x7F]/g,""),{valid:!0,sanitized:o})}function je(e){return e.valid===!0&&e.sanitized!==void 0}class ee{constructor(){x(this,"tokens",new Map)}get(r){const t=this.tokens.get(r);return t?t.expiresAt<Date.now()?(this.delete(r),null):t.value:null}set(r,t,n=36e5){this.tokens.set(r,{value:t,expiresAt:Date.now()+n})}delete(r){this.tokens.delete(r)}clear(){this.tokens.clear()}}class re{constructor(r,t=32){x(this,"store");x(this,"tokenLength");this.store=r||new ee,this.tokenLength=t}generateToken(r,t){const n=H(this.tokenLength);return this.store.set(r,n,t),n}validateToken(r,t){const n=this.store.get(r);if(!n)return!1;const s=W(t,n);return s&&this.store.delete(r),s}getToken(r){return this.store.get(r)}deleteToken(r){this.store.delete(r)}}function $e(e){return new re(e)}function te(e){if(typeof e!="string")return"";const r={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,t=>r[t]||t)}function qe(e){return typeof e!="string"?"":e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/on\w+\s*=\s*["'][^"']*["']/gi,"").replace(/javascript:/gi,"")}function He(e){return typeof e!="string"?"":te(e.trim())}function We(e){return typeof e!="string"?!1:[/<script/i,/javascript:/i,/on\w+\s*=/i,/<iframe/i,/<object/i,/<embed/i,/<link/i,/<meta/i,/expression\s*\(/i,/vbscript:/i].some(t=>t.test(e))}const ne=32;function H(e=ne){if(e<1||e>256)throw new Error("Token length must be between 1 and 256 bytes");const r=Ee(e);return Buffer.from(r).toString("base64url")}function se(){return H(ne)}function W(e,r){if(typeof e!="string"||typeof r!="string"||!e||!r||e.length!==r.length)return!1;let t=0;for(let n=0;n<e.length;n++)t|=e.charCodeAt(n)^r.charCodeAt(n);return t===0}function Be(e,r){return W(e,r)}function Ge(e){return typeof e!="string"?"":e.trim().replace(/[<>]/g,"")}const Ke=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;function Xe(e){return typeof e=="string"&&Ke.test(e)}function oe(e){return!e.success&&!!e.error}function Je(e){return e.requires2FA===!0||e.errorCode===h.AuthErrorCode.TWO_FA_REQUIRED}function Ye(e,r){return e.error?e.error:r||"Authentication failed"}function Qe(e){return e.errorCode}function Ze(e){return e.success===!0&&!!e.user}function er(e,r){return e.errorCode===r}function rr(e){if(!oe(e))return!1;const r=[h.AuthErrorCode.NETWORK_ERROR,h.AuthErrorCode.RATE_LIMITED,h.AuthErrorCode.UNKNOWN_ERROR];return e.errorCode?r.includes(e.errorCode):!1}function tr(e){if(e.error)return e.error;switch(e.errorCode){case h.AuthErrorCode.INVALID_CREDENTIALS:return"Invalid email or password. Please try again.";case h.AuthErrorCode.ACCOUNT_LOCKED:return"Your account has been temporarily locked. Please try again later.";case h.AuthErrorCode.ACCOUNT_INACTIVE:return"Your account is inactive. Please contact support.";case h.AuthErrorCode.TWO_FA_REQUIRED:return"Two-factor authentication is required. Please enter your code.";case h.AuthErrorCode.INVALID_TWO_FA_CODE:return"Invalid two-factor authentication code. Please try again.";case h.AuthErrorCode.SESSION_EXPIRED:return"Your session has expired. Please sign in again.";case h.AuthErrorCode.UNAUTHORIZED:return"You are not authorized to perform this action.";case h.AuthErrorCode.NETWORK_ERROR:return"Network error. Please check your connection and try again.";case h.AuthErrorCode.VALIDATION_ERROR:return"Please check your input and try again.";case h.AuthErrorCode.RATE_LIMITED:return"Too many attempts. Please try again later.";case h.AuthErrorCode.UNKNOWN_ERROR:default:return"An unexpected error occurred. Please try again."}}async function nr(e,r,t){return e.signIn(r,t)}const ie={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",userInfoUrl:"https://www.googleapis.com/oauth2/v2/userinfo",defaultScopes:["openid","profile","email"]},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",defaultScopes:["user:email"]},apple:{authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",userInfoUrl:"https://appleid.apple.com/auth/userinfo",defaultScopes:["name","email"],defaultParams:{response_mode:"form_post",response_type:"code id_token"}},facebook:{authorizationUrl:"https://www.facebook.com/v18.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v18.0/oauth/access_token",userInfoUrl:"https://graph.facebook.com/v18.0/me?fields=id,name,email,picture",defaultScopes:["email","public_profile"]}};function z(e){return ie[e]??null}function sr(e){return e in ie}function ae(e,r,t,n){const s=z(e);if(!s)throw new Error(`Unknown OAuth provider: ${e}`);if(!r.clientId)throw new Error(`OAuth provider "${e}" is missing clientId`);const o=r.redirectUri??`${t}/api/auth/callback/${e}`,i=r.scopes??s.defaultScopes,a=new URLSearchParams({client_id:r.clientId,redirect_uri:o,response_type:"code",scope:Array.isArray(i)?i.join(" "):String(i),state:n});if(s.defaultParams)for(const[l,f]of Object.entries(s.defaultParams))a.append(l,f);if(r.params)for(const[l,f]of Object.entries(r.params))a.set(l,f);return`${s.authorizationUrl}?${a.toString()}`}async function ce(e,r,t,n){const s=z(e);if(!s)throw new Error(`Unknown OAuth provider: ${e}`);if(!t||typeof t!="string")throw new Error("Authorization code is required");if(!r.clientId)throw new Error(`OAuth provider "${e}" is missing clientId`);const o=new URLSearchParams({client_id:r.clientId,code:t,redirect_uri:n,grant_type:"authorization_code"});r.clientSecret&&o.append("client_secret",r.clientSecret);try{const i=await fetch(s.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:o.toString()});if(!i.ok){const l=await i.text();let f=`Failed to exchange code for tokens: ${l}`;try{const p=JSON.parse(l);f=p.error_description??p.error??f}catch{}throw new Error(f)}const a=await i.json();if(!or(a))throw new Error("Invalid token exchange response format");return a}catch(i){throw i instanceof Error?i:new Error(`OAuth token exchange failed: ${String(i)}`)}}function or(e){return typeof e=="object"&&e!==null&&"access_token"in e&&typeof e.access_token=="string"}async function ue(e,r){const t=z(e);if(!t)throw new Error(`Unknown OAuth provider: ${e}`);if(!r||typeof r!="string")throw new Error("Access token is required");try{const n=await fetch(t.userInfoUrl,{headers:{Authorization:`Bearer ${r}`,Accept:"application/json"}});if(!n.ok){const o=await n.text();let i=`Failed to fetch user info: ${o}`;try{const a=JSON.parse(o);i=a.error_description??a.error??i}catch{}throw new Error(i)}const s=await n.json();return ir(e,s,r)}catch(n){throw n instanceof Error?n:new Error(`OAuth user info retrieval failed: ${String(n)}`)}}async function ir(e,r,t){switch(e){case"google":return ar(r);case"github":return await cr(r,t);case"apple":return ur(r);case"facebook":return lr(r);default:return fr(r)}}function ar(e){return{id:String(e.sub??e.id??""),email:String(e.email??""),name:String(e.name??""),avatar:typeof e.picture=="string"?e.picture:void 0,emailVerified:!!e.email_verified,rawProfile:e}}async function cr(e,r){let t=typeof e.email=="string"?e.email:void 0,n={...e};if(!t)try{const s=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${r}`}});if(s.ok){const o=await s.json(),i=o.find(a=>a.primary)??o[0];t=(i==null?void 0:i.email)??`${String(e.login??"user")}@users.noreply.github.com`,n={...e,emails:o}}else t=`${String(e.login??"user")}@users.noreply.github.com`}catch{t=`${String(e.login??"user")}@users.noreply.github.com`}return{id:String(e.id??""),email:t??"",name:String(e.name??e.login??""),avatar:typeof e.avatar_url=="string"?e.avatar_url:void 0,emailVerified:!!t,rawProfile:n}}function ur(e){const r=e.name,t=r?`${r.firstName??""} ${r.lastName??""}`.trim():"";return{id:String(e.sub??""),email:String(e.email??""),name:t,emailVerified:!!e.email_verified,rawProfile:e}}function lr(e){var t;const r=e.picture;return{id:String(e.id??""),email:String(e.email??""),name:String(e.name??""),avatar:(t=r==null?void 0:r.data)==null?void 0:t.url,emailVerified:!0,rawProfile:e}}function fr(e){return{id:String(e.id??e.sub??""),email:String(e.email??""),name:String(e.name??e.display_name??e.username??""),avatar:typeof e.avatar=="string"?e.avatar:typeof e.picture=="string"?e.picture:typeof e.avatar_url=="string"?e.avatar_url:void 0,emailVerified:!!(e.email_verified??e.emailVerified??!1),rawProfile:e}}function dr(e){return typeof e=="object"&&e!==null&&"clientId"in e&&typeof e.clientId=="string"}class le{constructor(){x(this,"states",new Map)}set(r,t,n){this.states.set(r,t),this.cleanup()}get(r){const t=this.states.get(r);return t?t.expiresAt<Date.now()?(this.delete(r),null):t:null}delete(r){this.states.delete(r)}cleanup(){const r=Date.now();for(const[t,n]of this.states.entries())n.expiresAt<r&&this.states.delete(t)}}function fe(){return new le}function hr(e,r="mulguard:oauth:state:"){const t=s=>`${r}${s}`,n=async s=>{const o=t(s);await e.del(o)};return{async set(s,o,i){const a=t(s),l=JSON.stringify(o);await e.set(a,l,"EX",Math.floor(i/1e3))},async get(s){const o=t(s),i=await e.get(o);if(!i)return null;try{const a=JSON.parse(i);return a.expiresAt<Date.now()?(await n(s),null):a}catch{return await n(s),null}},async delete(s){await n(s)},async cleanup(){try{const s=await e.keys(`${r}*`),o=Date.now();for(const i of s){const a=await e.get(i);if(a)try{JSON.parse(a).expiresAt<o&&await e.del(i)}catch{await e.del(i)}}}catch(s){console.warn("[Mulguard] OAuth state cleanup warning:",s)}}}}function L(e){return e.success===!0&&e.user!==void 0&&e.session!==void 0}var de=(e=>(e[e.DEBUG=0]="DEBUG",e[e.INFO=1]="INFO",e[e.WARN=2]="WARN",e[e.ERROR=3]="ERROR",e))(de||{});const gr=process.env.NODE_ENV==="development"?0:1;function wr(e={}){const{enabled:r=process.env.NODE_ENV==="development",level:t=gr,context:n,formatter:s=pr}=e,o=a=>r&&a>=t,i=(a,l,f,p)=>({level:a,message:l,timestamp:new Date,context:n,data:f?Er(f):void 0,error:p});return{debug:(a,l)=>{if(o(0)){const f=i(0,a,l);console.debug(s(f))}},info:(a,l)=>{if(o(1)){const f=i(1,a,l);console.info(s(f))}},warn:(a,l)=>{if(o(2)){const f=i(2,a,l);console.warn(s(f))}},error:(a,l)=>{if(o(3)){const f=l instanceof Error?l:void 0,p=l instanceof Error?void 0:l,w=i(3,a,p,f);console.error(s(w)),f&&console.error(f)}}}}function pr(e){const r=e.timestamp.toISOString(),t=de[e.level],n=e.context?`[${e.context}]`:"",s=e.data?` ${JSON.stringify(e.data)}`:"";return`${r} [${t}]${n} ${e.message}${s}`}function Er(e){const r=new Set(["password","token","secret","key","accessToken","refreshToken"]),t={};for(const[n,s]of Object.entries(e))if(r.has(n.toLowerCase()))t[n]="***REDACTED***";else if(typeof s=="string"&&n.toLowerCase().includes("email")){const o=s.split("@");if(o.length===2&&o[0]){const i=o[0].substring(0,3)+"***@"+o[1];t[n]=i}else t[n]=s}else t[n]=s;return t}const I=wr();function mr(e,r,t,n={}){const{enabled:s=!0,maxRetries:o=1,retryDelay:i=1e3,rateLimit:a=3,autoSignOutOnFailure:l=!0,redirectToLogin:f="/login",autoRedirectOnFailure:p=!0}=n;let w=null,v=!1;const R=[],A=[],y=60*1e3;let g=0,T=!1,_=null;const D=2,M=60*1e3;function c(){const S=Date.now();if(T&&_){if(S<_)return!1;T=!1,_=null,g=0}for(;A.length>0;){const E=A[0];if(E!==void 0&&E<S-y)A.shift();else break}return A.length>=a?!1:(A.push(S),!0)}function u(){g++,g>=D&&(T=!0,_=Date.now()+M,process.env.NODE_ENV==="development"&&console.warn("[TokenRefreshManager] Circuit breaker opened - too many consecutive failures"))}function d(){g=0,T=!1,_=null}async function k(S=1){if(!s)return null;if(!c())throw new Error("Rate limit exceeded for token refresh");try{const E=await e();if(E)return d(),P(E),n.onTokenRefreshed&&await Promise.resolve(n.onTokenRefreshed(E)),E;if(u(),S<o)return await G(i*S),k(S+1);throw new Error("Token refresh failed: refresh function returned null")}catch(E){if(u(),S<o&&N(E))return await G(i*S),k(S+1);throw E}}function N(S){if(S instanceof Error){const E=S.message.toLowerCase();if(E.includes("rate limit")||E.includes("too many requests")||E.includes("429")||E.includes("limit:")||E.includes("requests per minute")||E.includes("token_blacklisted")||E.includes("blacklisted")||E.includes("invalid")||E.includes("401")||E.includes("unauthorized")||E.includes("session has been revoked")||E.includes("session expired"))return!1;if(E.includes("network")||E.includes("fetch")||E.includes("timeout"))return!0}return!1}function P(S){const E=[...R];R.length=0;for(const{resolve:b}of E)b(S)}function B(S){const E=[...R];R.length=0;for(const{reject:b}of E)b(S)}function G(S){return new Promise(E=>setTimeout(E,S))}async function K(S){try{if(n.onTokenRefreshFailed&&await Promise.resolve(n.onTokenRefreshFailed(S)),l&&(await t(),await r(),p&&typeof window<"u")){let E=!0;if(n.onBeforeRedirect&&(E=await Promise.resolve(n.onBeforeRedirect(S))),E){const b=new URL(f,window.location.origin);b.searchParams.set("reason","session_expired"),b.searchParams.set("redirect",window.location.pathname+window.location.search),window.location.href=b.toString()}}}catch(E){process.env.NODE_ENV==="development"&&console.error("[TokenRefreshManager] Error in handleRefreshFailure:",E)}}return{async refreshToken(){return s?w||(v=!0,w=k().then(S=>(v=!1,w=null,S)).catch(S=>{throw v=!1,w=null,B(S),K(S).catch(()=>{}),S}),w):null},isRefreshing(){return v},async waitForRefresh(){return w?new Promise((S,E)=>{R.push({resolve:S,reject:E})}):null},clear(){w=null,v=!1,A.length=0,d(),B(new Error("Token refresh manager cleared"))},async handleRefreshFailure(S){return K(S)}}}function yr(){const e=process.env.NODE_ENV==="production";return{cookieName:"__mulguard_session",expiresIn:60*60*24*7,httpOnly:!0,secure:e,sameSite:"lax",path:"/"}}function Sr(){return{enabled:!0,refreshThreshold:300,maxRetries:0,retryDelay:1e3,rateLimit:1,autoSignOutOnFailure:!0,redirectToLogin:"/login",autoRedirectOnFailure:!0}}function Ar(){return process.env.NEXT_PUBLIC_URL??(process.env.VERCEL_URL?`https://${process.env.VERCEL_URL}`:"http://localhost:3000")}function Rr(e){const{sessionConfig:r,cacheTtl:t,getSessionAction:n,onSessionExpired:s,onError:o}=e,i=r.cookieName??"__mulguard_session";let a=null;const l=async()=>{const y=Date.now();if(a&&y-a.timestamp<t)return a.session;if(n)try{const g=await n();if(g&&C.validateSessionStructure(g))return a={session:g,timestamp:y},g;g&&!C.validateSessionStructure(g)&&(await p(),a=null)}catch(g){I.debug("getSession error",{error:g}),o&&await o(g instanceof Error?g:new Error(String(g)),"getSession"),a=null}try{const g=await h.getCookie(i);if(g)try{const T=JSON.parse(g);if(C.validateSessionStructure(T))return T.expiresAt&&new Date(T.expiresAt)<new Date?(s&&await s(T),await p(),a=null,null):(a={session:T,timestamp:y},T);await p(),a=null}catch{await p(),a=null}}catch(g){const T=g instanceof Error?g.message:String(g);!T.includes("request scope")&&!T.includes("cookies")&&(I.warn("getSession cookie error",{error:g}),o&&await o(g instanceof Error?g:new Error(String(g)),"getSession.cookie"))}return null},f=async y=>{if(!C.validateSessionStructure(y))return{success:!1,error:"Invalid session structure"};try{const g=typeof y=="object"&&"token"in y?String(y.token):JSON.stringify(y),T=h.buildCookieOptions(i,g,r),_=await h.setCookie(T);return _.success&&(a={session:y,timestamp:Date.now()}),_}catch(g){const T=g instanceof Error?g.message:"Failed to set session";return I.error("setSession error",{error:g}),o&&await o(g instanceof Error?g:new Error(String(g)),"setSession"),{success:!1,error:T}}},p=async()=>{try{await h.deleteCookie(i,{path:r.path,domain:r.domain}),a=null}catch(y){I.warn("clearSessionCookie error",{error:y})}},w=async()=>{const y=await l();return y!=null&&y.accessToken&&typeof y.accessToken=="string"?y.accessToken:null};return{getSession:l,setSession:f,clearSessionCookie:p,getAccessToken:w,getRefreshToken:async()=>{const y=await l();return y!=null&&y.refreshToken&&typeof y.refreshToken=="string"?y.refreshToken:null},hasValidTokens:async()=>!!await w(),clearCache:()=>{a=null},getSessionConfig:()=>({cookieName:i,config:r})}}function kr(e){return async r=>{try{if(!r||typeof r!="object")return{success:!1,error:"Invalid credentials",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(!r.email||typeof r.email!="string")return{success:!1,error:"Email is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const t=$(r.email);if(!Z(t))return{success:!1,error:t.error??"Invalid email format",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(!r.password||typeof r.password!="string")return{success:!1,error:"Password is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(r.password.length>128)return{success:!1,error:"Invalid credentials",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const n={email:t.sanitized,password:r.password},s=await e.actions.signIn.email(n);if(L(s)){const o=await e.saveSessionAfterAuth(s);!o.success&&o.warning&&I.warn("Session save warning",{warning:o.warning})}return s.success?I.info("Sign in successful",{email:n.email.substring(0,3)+"***"}):I.warn("Sign in failed",{email:n.email.substring(0,3)+"***",errorCode:s.errorCode}),s}catch(t){const n=t instanceof Error?t.message:"Sign in failed";return I.error("Sign in error",{error:n,context:"signIn.email"}),e.onError&&await e.onError(t instanceof Error?t:new Error(String(t)),"signIn.email"),{success:!1,error:"Sign in failed. Please try again.",errorCode:h.AuthErrorCode.UNKNOWN_ERROR}}}}function vr(e,r){return async t=>{if(!t||typeof t!="string")throw new Error("Provider is required");const n=q(t,{maxLength:50,allowHtml:!1,required:!0});if(!n.valid||!n.sanitized)throw new Error("Invalid provider");const s=n.sanitized.toLowerCase();if(!e.actions.signIn.oauth)throw new Error("OAuth sign in is not configured. Either provide oauth action in signIn, or configure providers.oauth in config.");const o=await e.actions.signIn.oauth(s);return await r(o.state,s),I.info("OAuth sign in initiated",{provider:s}),o}}function Cr(e){return async(r,t)=>{if(!r||typeof r!="string")return{success:!1,error:"Email is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const n=$(r);if(!Z(n))return{success:!1,error:n.error??"Invalid email format",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(t!==void 0&&(typeof t!="string"||t.length<4||t.length>10))return{success:!1,error:"Invalid OTP code format",errorCode:h.AuthErrorCode.VALIDATION_ERROR};if(!e.actions.signIn.otp)return{success:!1,error:"OTP sign in is not configured",errorCode:h.AuthErrorCode.VALIDATION_ERROR};try{const s=await e.actions.signIn.otp(n.sanitized,t);if(L(s)){const o=await e.saveSessionAfterAuth(s);!o.success&&o.warning&&I.warn("Session save warning",{warning:o.warning})}return s.success?I.info("OTP sign in successful",{email:n.sanitized.substring(0,3)+"***"}):I.warn("OTP sign in failed",{email:n.sanitized.substring(0,3)+"***"}),s}catch(s){return I.error("OTP sign in error",{error:s instanceof Error?s.message:"Unknown error",context:"signIn.otp"}),e.onError&&await e.onError(s instanceof Error?s:new Error(String(s)),"signIn.otp"),{success:!1,error:"OTP sign in failed. Please try again.",errorCode:h.AuthErrorCode.UNKNOWN_ERROR}}}}function Or(e){return async r=>{if(!e.actions.signIn.passkey)throw new Error("PassKey sign in is not configured. Provide passkey action in signIn.");try{const t=await e.actions.signIn.passkey(r);if(L(t)){const n=await e.saveSessionAfterAuth(t);!n.success&&n.warning&&I.warn("Session save warning",{warning:n.warning})}return t}catch(t){return e.onError&&await e.onError(t instanceof Error?t:new Error(String(t)),"signIn.passkey"),{success:!1,error:t instanceof Error?t.message:"PassKey sign in failed"}}}}function Tr(e,r){const t=kr(e),n=vr(e,r),s=Cr(e),o=Or(e);return Object.assign(async(l,f)=>{if(!l||typeof l!="string")throw new Error("Provider is required");const p=q(l,{maxLength:50,allowHtml:!1,required:!0});if(!p.valid||!p.sanitized)throw new Error("Invalid provider");const w=p.sanitized.toLowerCase();if(w==="google"||w==="github"||w==="apple"||w==="facebook"||typeof w=="string"&&!["credentials","otp","passkey"].includes(w))return n(w);if(w==="credentials")return!f||!("email"in f)||!("password"in f)?{success:!1,error:"Credentials are required",errorCode:h.AuthErrorCode.VALIDATION_ERROR}:t(f);if(w==="otp"){if(!f||!("email"in f))return{success:!1,error:"Email is required",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const v=f;return s(v.email,v.code)}return w==="passkey"?o(f):{success:!1,error:"Invalid provider",errorCode:h.AuthErrorCode.VALIDATION_ERROR}},{email:t,oauth:e.actions.signIn.oauth?n:void 0,passkey:e.actions.signIn.passkey?o:void 0,otp:e.actions.signIn.otp?s:void 0})}function Ir(e){return async r=>{if(!e.actions.signUp)throw new Error("Sign up is not configured. Provide signUp action in config.");try{const t=await e.actions.signUp(r);if(L(t)){const n=await e.saveSessionAfterAuth(t);!n.success&&n.warning&&I.warn("Session save warning",{warning:n.warning})}return t}catch(t){return e.onError&&await e.onError(t instanceof Error?t:new Error(String(t)),"signUp"),{success:!1,error:t instanceof Error?t.message:"Sign up failed"}}}}function _r(e,r){return async(t,n,s)=>{const o=e.oauthProviders[t];if(!o)return{success:!1,error:`OAuth provider "${t}" is not configured`,errorCode:h.AuthErrorCode.VALIDATION_ERROR};try{const i=o.redirectUri??`${e.baseUrl}/api/auth/callback/${t}`,a=await ce(t,o,n,i),l=await ue(t,a.access_token),f={id:l.id,email:l.email,name:l.name,avatar:l.avatar,emailVerified:l.emailVerified,provider:t,accessToken:a.access_token,refreshToken:a.refresh_token,tokens:{access_token:a.access_token,refresh_token:a.refresh_token,expires_in:a.expires_in,token_type:a.token_type,id_token:a.id_token},rawProfile:l.rawProfile};if(e.callbacks.onOAuthUser){const p=await X(e.callbacks.onOAuthUser,[f,t],e.onError);if(!p)return{success:!1,error:"Failed to create or retrieve user",errorCode:h.AuthErrorCode.VALIDATION_ERROR};const w=e.createSession(p,f,a);return await e.saveSession(w),e.callbacks.onSignIn&&await X(e.callbacks.onSignIn,[w.user,w],e.onError),{success:!0,user:w.user,session:w}}return{success:!1,error:"OAuth user callback not implemented. Provide onOAuthUser callback or implement oauthCallback action.",errorCode:h.AuthErrorCode.VALIDATION_ERROR}}catch(i){return I.error("OAuth callback failed",{provider:t,error:i}),{success:!1,error:i instanceof Error?i.message:"OAuth callback failed",errorCode:h.AuthErrorCode.NETWORK_ERROR}}}}async function X(e,r,t){if(e)try{return await e(...r)}catch(n){throw t&&await t(n instanceof Error?n:new Error(String(n)),"callback"),n}}function Pr(e,r,t,n){if(Object.keys(e).length!==0)return async s=>{const o=e[s];if(!o)throw new Error(`OAuth provider "${s}" is not configured. Add it to providers.oauth in config.`);if(!o.clientId)throw new Error(`OAuth provider "${s}" is missing clientId`);const i=t();return{url:n(s,o,r,i),state:i}}}function Nr(e){var D,M;const r={...yr(),...e.session},t=e.actions,n=e.callbacks||{},s=((D=e.providers)==null?void 0:D.oauth)||{},o=Ar(),i={...Sr(),...e.tokenRefresh},a=((M=e.session)==null?void 0:M.cacheTtl)??e.sessionCacheTtl??5e3,l=e.oauthStateStore||fe(),f={...t},p=async(c,u)=>{const d={provider:u,expiresAt:Date.now()+6e5};await Promise.resolve(l.set(c,d,10*60*1e3)),l.cleanup&&await Promise.resolve(l.cleanup())},w=async(c,u)=>{const d=await Promise.resolve(l.get(c));return d?d.expiresAt<Date.now()?(await Promise.resolve(l.delete(c)),!1):d.provider!==u?!1:(await Promise.resolve(l.delete(c)),!0):!1},v=Pr(s,o,se,ae);if(v&&!f.signIn.oauth){const c=f.signIn;f.signIn={...c,oauth:async u=>{const d=await v(u);return await p(d.state,u),d}}}if(!f.signIn||!f.signIn.email)throw new Error("mulguard: signIn.email action is required");const R=async(c,...u)=>{if(c)try{return await c(...u)}catch(d){throw n.onError&&await n.onError(d instanceof Error?d:new Error(String(d)),"callback"),d}},A=Rr({sessionConfig:r,cacheTtl:a,getSessionAction:t.getSession,onSessionExpired:n.onSessionExpired,onError:n.onError}),y=async c=>{if(!L(c)||!c.session)return{success:!0};const u=await A.setSession(c.session);return c.user&&n.onSignIn&&await R(n.onSignIn,c.user,c.session),u};if(Object.keys(s).length>0&&!f.oauthCallback){const c=_r({oauthProviders:s,baseUrl:o,callbacks:n,createSession:(u,d,k)=>({user:{...u,avatar:d.avatar,emailVerified:d.emailVerified},expiresAt:new Date(Date.now()+(r.expiresIn||604800)*1e3),accessToken:k.access_token,refreshToken:k.refresh_token,tokenType:"Bearer",expiresIn:k.expires_in}),saveSession:async u=>{await A.setSession(u)},onError:n.onError});f.oauthCallback=c}const g=Tr({actions:f,callbacks:n,saveSessionAfterAuth:y,onError:n.onError},p),T=Ir({actions:f,callbacks:n,saveSessionAfterAuth:y,onError:n.onError}),_={async getSession(){return await A.getSession()},async getAccessToken(){return await A.getAccessToken()},async getRefreshToken(){return await A.getRefreshToken()},async hasValidTokens(){return await A.hasValidTokens()},signIn:g,async signUp(c){if(!T)throw new Error("Sign up is not configured. Provide signUp action in config.");return await T(c)},async signOut(){try{const c=await this.getSession(),u=c==null?void 0:c.user;return t.signOut&&await t.signOut(),await A.clearSessionCookie(),A.clearCache(),u&&n.onSignOut&&await R(n.onSignOut,u),{success:!0}}catch(c){return await A.clearSessionCookie(),A.clearCache(),n.onError&&await R(n.onError,c instanceof Error?c:new Error(String(c)),"signOut"),{success:!1,error:c instanceof Error?c.message:"Sign out failed"}}},async resetPassword(c){if(!t.resetPassword)throw new Error("Password reset is not configured. Provide resetPassword action in config.");try{return await t.resetPassword(c)}catch(u){return n.onError&&await R(n.onError,u instanceof Error?u:new Error(String(u)),"resetPassword"),{success:!1,error:u instanceof Error?u.message:"Password reset failed"}}},async verifyEmail(c){if(!t.verifyEmail)throw new Error("Email verification is not configured. Provide verifyEmail action in config.");try{return await t.verifyEmail(c)}catch(u){return n.onError&&await R(n.onError,u instanceof Error?u:new Error(String(u)),"verifyEmail"),{success:!1,error:u instanceof Error?u.message:"Email verification failed"}}},async refreshSession(){if(!t.refreshSession)return this.getSession();try{const c=await t.refreshSession();if(c&&C.validateSessionStructure(c)){if(await A.setSession(c),n.onSessionUpdate){const u=await R(n.onSessionUpdate,c);if(u&&C.validateSessionStructure(u)){if(await A.setSession(u),n.onTokenRefresh){const d=await this.getSession();d&&await R(n.onTokenRefresh,d,u)}return u}}if(n.onTokenRefresh){const u=await this.getSession();u&&await R(n.onTokenRefresh,u,c)}return c}else if(c&&!C.validateSessionStructure(c))return await A.clearSessionCookie(),A.clearCache(),null;return null}catch(c){return await A.clearSessionCookie(),A.clearCache(),n.onError&&await R(n.onError,c instanceof Error?c:new Error(String(c)),"refreshSession"),null}},async oauthCallback(c,u,d){if(!f.oauthCallback)throw new Error("OAuth callback is not configured. Either provide oauthCallback action, or configure providers.oauth in config.");if(!u||!d)return{success:!1,error:"Missing required OAuth parameters (code or state)",errorCode:h.AuthErrorCode.VALIDATION_ERROR};let k=c;if(!k){const P=await Promise.resolve(l.get(d));if(P&&P.provider)k=P.provider;else return{success:!1,error:"Provider is required and could not be extracted from state",errorCode:h.AuthErrorCode.VALIDATION_ERROR}}if(!await w(d,k))return{success:!1,error:"Invalid or expired state parameter",errorCode:h.AuthErrorCode.VALIDATION_ERROR};try{return await f.oauthCallback(k,u,d)}catch(P){return n.onError&&await R(n.onError,P instanceof Error?P:new Error(String(P)),"oauthCallback"),{success:!1,error:P instanceof Error?P.message:"OAuth callback failed",errorCode:h.AuthErrorCode.NETWORK_ERROR}}},async verify2FA(c,u){if(!t.verify2FA)throw new Error("2FA verification is not configured. Provide verify2FA action in config.");try{const d=await t.verify2FA(c);if(d.success&&d.session&&!(u!=null&&u.skipCookieSave)){const k=await y(d);k.success||(process.env.NODE_ENV==="development"&&I.debug("Failed to save session cookie after verify2FA",{error:k.error,warning:k.warning}),n.onError&&await R(n.onError,new Error(k.warning||k.error||"Failed to save session cookie"),"verify2FA.setSession"))}return d}catch(d){return n.onError&&await R(n.onError,d instanceof Error?d:new Error(String(d)),"verify2FA"),{success:!1,error:d instanceof Error?d.message:"2FA verification failed",errorCode:h.AuthErrorCode.TWO_FA_REQUIRED}}},async setSession(c){return await A.setSession(c)},_getSessionConfig(){return A.getSessionConfig()},_getCallbacks(){return n},passkey:t.passkey?{register:t.passkey.register,authenticate:async c=>{var u;if(!((u=t.passkey)!=null&&u.authenticate))throw new Error("PassKey authenticate is not configured.");try{const d=await t.passkey.authenticate(c);return d.success&&d.session&&await y(d),d}catch(d){return n.onError&&await R(n.onError,d instanceof Error?d:new Error(String(d)),"passkey.authenticate"),{success:!1,error:d instanceof Error?d.message:"PassKey authentication failed"}}},list:t.passkey.list?async()=>{var u;if(!((u=t.passkey)!=null&&u.list))throw new Error("PassKey list is not configured.");return[...await t.passkey.list()]}:void 0,remove:t.passkey.remove}:void 0,twoFactor:t.twoFactor?{enable:t.twoFactor.enable,verify:t.twoFactor.verify,disable:t.twoFactor.disable,generateBackupCodes:t.twoFactor.generateBackupCodes,isEnabled:t.twoFactor.isEnabled,verify2FA:async c=>{var d;const u=((d=t.twoFactor)==null?void 0:d.verify2FA)||t.verify2FA;if(!u)throw new Error("2FA verification is not configured. Provide verify2FA action in config.");try{const k=await u(c);if(k.success&&k.session){const N=await y(k);N.success||(process.env.NODE_ENV==="development"&&I.debug("Failed to save session cookie after twoFactor.verify2FA",{error:N.error,warning:N.warning}),n.onError&&await R(n.onError,new Error(N.warning||N.error||"Failed to save session cookie"),"twoFactor.verify2FA.setSession"))}return k}catch(k){return n.onError&&await R(n.onError,k instanceof Error?k:new Error(String(k)),"twoFactor.verify2FA"),{success:!1,error:k instanceof Error?k.message:"2FA verification failed",errorCode:h.AuthErrorCode.UNKNOWN_ERROR}}}}:void 0,signInMethods:{email:c=>g.email(c),oauth:c=>{var u;return((u=g.oauth)==null?void 0:u.call(g,c))||Promise.reject(new Error("OAuth not configured"))},passkey:c=>{var u;return((u=g.passkey)==null?void 0:u.call(g,c))||Promise.reject(new Error("Passkey not configured"))},otp:(c,u)=>{var d;return((d=g.otp)==null?void 0:d.call(g,c,u))||Promise.reject(new Error("OTP not configured"))}}};if(t.refreshSession){const c=mr(async()=>await _.refreshSession(),async()=>await _.signOut(),async()=>{await A.clearSessionCookie(),A.clearCache()},{...i,onTokenRefreshed:i.onTokenRefreshed,onTokenRefreshFailed:i.onTokenRefreshFailed,onBeforeRedirect:i.onBeforeRedirect});_._tokenRefreshManager=c,_._getTokenRefreshManager=()=>c}return _}function Ur(e){return{GET:async r=>J(r,e,"GET"),POST:async r=>J(r,e,"POST")}}async function J(e,r,t){const n=new URL(e.url),s=br(n.pathname),o=s.split("/").filter(Boolean);try{return t==="GET"?await xr(e,r,s,o,n):t==="POST"?await Fr(e,r,s,o,n):O("Method not allowed",405)}catch(i){return O(i instanceof Error?i.message:"Request failed",500)}}function br(e){return e.replace(/^\/api\/auth/,"")||"/session"}async function xr(e,r,t,n,s){if(t==="/session"||t==="/"){const o=await r.getSession();return m.NextResponse.json({session:o})}return t==="/providers"?m.NextResponse.json({providers:{email:!!r.signIn.email,oauth:!!r.signIn.oauth,passkey:!!r.signIn.passkey}}):he(t,n)?await ge(e,r,t,n,s,"GET"):O("Not found",404)}async function Fr(e,r,t,n,s){const o=await Lr(e);return t==="/sign-in"||n[0]==="sign-in"?await Mr(r,o):t==="/sign-up"||n[0]==="sign-up"?await Vr(r,o):t==="/sign-out"||n[0]==="sign-out"?await zr(r):t==="/reset-password"||n[0]==="reset-password"?await jr(r,o):t==="/verify-email"||n[0]==="verify-email"?await $r(r,o):t==="/refresh"||n[0]==="refresh"?await qr(r):he(t,n)?await ge(e,r,t,n,s,"POST",o):t.startsWith("/passkey")?await Wr(r,t,n,o):t==="/verify-2fa"||n[0]==="verify-2fa"?await Hr(r,o):t.startsWith("/two-factor")?await Br(r,n,o):O("Not found",404)}async function Lr(e){try{return await e.json()}catch{return{}}}function he(e,r){return e==="/callback"||e.startsWith("/oauth/callback")||r[0]==="oauth"&&r[1]==="callback"||r[0]==="callback"}async function ge(e,r,t,n,s,o,i){if(!r.oauthCallback)return o==="GET"?V(e.url,"oauth_not_configured"):O("OAuth callback is not configured",400);const a=Dr(n,s,i),l=(i==null?void 0:i.code)??s.searchParams.get("code"),f=(i==null?void 0:i.state)??s.searchParams.get("state");if(!l||!f)return o==="GET"?V(e.url,"oauth_missing_params"):O("Missing required OAuth parameters. Code and state are required.",400);try{const p=await r.oauthCallback(a??"",l,f);return o==="GET"?p.success?Gr(e.url,s.searchParams.get("callbackUrl")):V(e.url,p.error??"oauth_failed"):m.NextResponse.json(p)}catch(p){return o==="GET"?V(e.url,p instanceof Error?p.message:"oauth_error"):O(p instanceof Error?p.message:"OAuth callback failed",500)}}function Dr(e,r,t){return t!=null&&t.provider?t.provider:e[0]==="callback"&&e[1]?e[1]:e[0]==="oauth"&&e[1]==="callback"&&e[2]?e[2]:r.searchParams.get("provider")}async function Mr(e,r){if(r.provider==="email"&&r.email&&r.password){const t={email:r.email,password:r.password},n=await e.signIn.email(t);return m.NextResponse.json(n)}if(r.provider==="oauth"&&r.providerName){if(!e.signIn.oauth)return O("OAuth is not configured",400);const t=await e.signIn.oauth(r.providerName);return m.NextResponse.json(t)}if(r.provider==="passkey"){if(!e.signIn.passkey)return O("PassKey is not configured",400);const t=await e.signIn.passkey(r.options);return m.NextResponse.json(t)}return O("Invalid sign in request",400)}async function Vr(e,r){if(!e.signUp)return O("Sign up is not configured",400);const t=await e.signUp(r);return m.NextResponse.json(t)}async function zr(e){const r=await e.signOut();return m.NextResponse.json(r)}async function jr(e,r){if(!e.resetPassword)return O("Password reset is not configured",400);if(!r.email||typeof r.email!="string")return O("Email is required",400);const t=await e.resetPassword(r.email);return m.NextResponse.json(t)}async function $r(e,r){if(!e.verifyEmail)return O("Email verification is not configured",400);if(!r.token||typeof r.token!="string")return O("Token is required",400);const t=await e.verifyEmail(r.token);return m.NextResponse.json(t)}async function qr(e){if(!e.refreshSession){const t=await e.getSession();return m.NextResponse.json({session:t})}const r=await e.refreshSession();return m.NextResponse.json({session:r})}async function Hr(e,r){if(!e.verify2FA)return O("2FA verification is not configured",400);if(!r.email||!r.userId||!r.code)return O("Missing required parameters. Email, userId, and code are required.",400);const t={email:r.email,userId:r.userId,code:r.code},n=await e.verify2FA(t);return m.NextResponse.json(n)}async function Wr(e,r,t,n){if(!e.passkey)return O("PassKey is not configured",400);const s=t[1];if(s==="register"&&e.passkey.register){const o=await e.passkey.register(n.options);return m.NextResponse.json(o)}if(s==="list"&&e.passkey.list){const o=await e.passkey.list();return m.NextResponse.json(o)}if(s==="remove"&&e.passkey.remove){if(!n.passkeyId||typeof n.passkeyId!="string")return O("Passkey ID is required",400);const o=await e.passkey.remove(n.passkeyId);return m.NextResponse.json(o)}return O("Invalid Passkey request",400)}async function Br(e,r,t){if(!e.twoFactor)return O("Two-Factor Authentication is not configured",400);const n=r[1];if(n==="enable"&&e.twoFactor.enable){const s=await e.twoFactor.enable();return m.NextResponse.json(s)}if(n==="verify"&&e.twoFactor.verify){if(!t.code||typeof t.code!="string")return O("Code is required",400);const s=await e.twoFactor.verify(t.code);return m.NextResponse.json(s)}if(n==="disable"&&e.twoFactor.disable){const s=await e.twoFactor.disable();return m.NextResponse.json(s)}if(n==="backup-codes"&&e.twoFactor.generateBackupCodes){const s=await e.twoFactor.generateBackupCodes();return m.NextResponse.json(s)}if(n==="is-enabled"&&e.twoFactor.isEnabled){const s=await e.twoFactor.isEnabled();return m.NextResponse.json({enabled:s})}return O("Invalid two-factor request",400)}function O(e,r){return m.NextResponse.json({success:!1,error:e},{status:r})}function V(e,r){return m.NextResponse.redirect(new URL(`/login?error=${encodeURIComponent(r)}`,e))}function Gr(e,r){const t=r??"/";return m.NextResponse.redirect(new URL(t,e))}function Kr(e){return async r=>{const{method:t,nextUrl:n}=r,o=n.pathname.replace(/^\/api\/auth/,"")||"/";try{let i;if(t!=="GET"&&t!=="HEAD")try{i=await r.json()}catch{}const a=Object.fromEntries(n.searchParams.entries()),l=await fetch(`${process.env.NEXT_PUBLIC_API_URL||""}/api/auth${o}${Object.keys(a).length>0?`?${new URLSearchParams(a).toString()}`:""}`,{method:t,headers:{"Content-Type":"application/json",...Object.fromEntries(r.headers.entries())},body:i?JSON.stringify(i):void 0}),f=await l.json();return m.NextResponse.json(f,{status:l.status,headers:{...Object.fromEntries(l.headers.entries())}})}catch(i){return console.error("API handler error:",i),m.NextResponse.json({success:!1,error:i instanceof Error?i.message:"Internal server error"},{status:500})}}}function Xr(e){return async r=>{const{searchParams:t}=r.nextUrl,n=t.get("provider"),s=t.get("code"),o=t.get("state");if(!n||!s||!o)return m.NextResponse.redirect(new URL("/login?error=oauth_missing_params",r.url));try{if(!e.oauthCallback)return m.NextResponse.redirect(new URL("/login?error=oauth_not_configured",r.url));const i=await e.oauthCallback(n,s,o);if(i.success){const a=t.get("callbackUrl")||"/";return m.NextResponse.redirect(new URL(a,r.url))}else{const a=i.errorCode?`${encodeURIComponent(i.error||"oauth_failed")}&code=${i.errorCode}`:encodeURIComponent(i.error||"oauth_failed");return m.NextResponse.redirect(new URL(`/login?error=${a}`,r.url))}}catch(i){return process.env.NODE_ENV==="development"&&console.error("[Mulguard] OAuth callback error:",i),m.NextResponse.redirect(new URL(`/login?error=${encodeURIComponent(i instanceof Error?i.message:"oauth_error")}`,r.url))}}}function U(e,r){const t=j({"X-Frame-Options":"SAMEORIGIN"});for(const[n,s]of Object.entries(t))s&&typeof s=="string"&&r.headers.set(n,s);return r}function Jr(){return async e=>{const r=m.NextResponse.next();return U(e,r)}}function Yr(e,r={}){const{protectedRoutes:t=[],publicRoutes:n=[],redirectTo:s="/login",redirectIfAuthenticated:o}=r;return async i=>{const{pathname:a}=i.nextUrl,l=t.some(w=>a.startsWith(w));let f=null;try{f=await e.getSession()}catch(w){console.error("Middleware: Failed to get session:",w)}if(l&&!f){const w=i.nextUrl.clone();return w.pathname=s,w.searchParams.set("callbackUrl",a),m.NextResponse.redirect(w)}if(o&&f&&(a.startsWith("/login")||a.startsWith("/register"))){const v=i.nextUrl.clone();v.pathname=o;const R=m.NextResponse.redirect(v);return U(i,R)}const p=m.NextResponse.next();return U(i,p)}}async function Qr(e,r){var t;try{const n=await e.getSession();return n?((t=n.user.roles)==null?void 0:t.includes(r))??!1:!1}catch{return!1}}function Zr(e){const{auth:r,protectedRoutes:t=[],publicRoutes:n=[],redirectTo:s="/login",redirectIfAuthenticated:o,apiPrefix:i="/api/auth"}=e;return async a=>{const{pathname:l}=a.nextUrl;if(l.startsWith(i)){const v=m.NextResponse.next();return U(a,v)}const f=t.some(v=>l.startsWith(v));let p=null;if(f||o)try{p=await r.getSession()}catch(v){console.error("Middleware: Failed to get session:",v)}if(f&&!p){const v=a.nextUrl.clone();v.pathname=s,v.searchParams.set("callbackUrl",l);const R=m.NextResponse.redirect(v);return U(a,R)}if(o&&p&&(l.startsWith("/login")||l.startsWith("/register"))){const R=a.nextUrl.clone();R.pathname=o;const A=m.NextResponse.redirect(R);return U(a,A)}const w=m.NextResponse.next();return U(a,w)}}async function et(e,r){var t;try{const n=await e.getSession();return n?((t=n.user.roles)==null?void 0:t.includes(r))??!1:!1}catch{return!1}}exports.buildCookieOptions=h.buildCookieOptions;exports.deleteCookie=h.deleteCookie;exports.getCookie=h.getCookie;exports.setCookie=h.setCookie;exports.signInEmailAction=h.signInEmailAction;exports.signOutAction=h.signOutAction;exports.signUpAction=h.signUpAction;exports.verify2FAAction=h.verify2FAAction;exports.createServerAuthMiddleware=C.createAuthMiddleware;exports.createServerHelpers=C.createServerHelpers;exports.createServerUtils=C.createServerUtils;exports.createSessionManager=C.createSessionManager;exports.deleteOAuthStateCookie=C.deleteOAuthStateCookie;exports.getCurrentUser=C.getCurrentUser;exports.getOAuthStateCookie=C.getOAuthStateCookie;exports.getServerSession=C.getServerSession;exports.getSessionTimeUntilExpiry=C.getSessionTimeUntilExpiry;exports.isSessionExpiredNullable=C.isSessionExpiredNullable;exports.isSessionExpiringSoon=C.isSessionExpiringSoon;exports.isSessionValid=C.isSessionValid;exports.refreshSession=C.refreshSession;exports.requireAuth=C.requireAuth;exports.requireRole=C.requireRole;exports.requireServerAuthMiddleware=C.requireAuthMiddleware;exports.requireServerRoleMiddleware=C.requireRoleMiddleware;exports.storeOAuthStateCookie=C.storeOAuthStateCookie;exports.validateSessionStructure=C.validateSessionStructure;exports.CSRFProtection=re;exports.DEFAULT_SECURITY_HEADERS=Q;exports.MemoryCSRFStore=ee;exports.MemoryOAuthStateStore=le;exports.RateLimiter=Y;exports.applySecurityHeaders=ye;exports.buildOAuthAuthorizationUrl=ae;exports.checkRole=Qr;exports.checkRoleProxy=et;exports.containsXSSPattern=We;exports.createApiHandler=Kr;exports.createAuthMiddleware=Yr;exports.createCSRFProtection=$e;exports.createMemoryOAuthStateStore=fe;exports.createOAuthCallbackHandler=Xr;exports.createProxyMiddleware=Zr;exports.createRateLimiter=me;exports.createRedisOAuthStateStore=hr;exports.createSecurityMiddleware=Jr;exports.escapeHTML=te;exports.exchangeOAuthCode=ce;exports.generateCSRFToken=se;exports.generateToken=H;exports.getErrorCode=Qe;exports.getErrorMessage=Ye;exports.getOAuthUserInfo=ue;exports.getProviderMetadata=z;exports.getSecurityHeaders=j;exports.getUserFriendlyError=tr;exports.hasErrorCode=er;exports.isAuthError=oe;exports.isAuthSuccess=Ze;exports.isOAuthProviderConfig=dr;exports.isRetryableError=rr;exports.isSupportedProvider=sr;exports.isTwoFactorRequired=Je;exports.isValidCSRFToken=Be;exports.isValidEmail=Xe;exports.isValidInput=je;exports.isValidName=Ne;exports.isValidPassword=Ie;exports.isValidToken=Ve;exports.isValidURL=xe;exports.mulguard=Nr;exports.sanitizeHTML=qe;exports.sanitizeInput=Ge;exports.sanitizeUserInput=He;exports.signIn=nr;exports.toNextJsHandler=Ur;exports.validateAndSanitizeEmail=$;exports.validateAndSanitizeInput=q;exports.validateAndSanitizeName=Pe;exports.validateAndSanitizePassword=Oe;exports.validateCSRFToken=W;exports.validateToken=Me;exports.validateURL=be;exports.withSecurityHeaders=U;
|