UNPKG

authrix

Version:

Lightweight, flexible authentication library for Node.js and TypeScript.

1 lines 10 kB
'use strict';var chunkVB7D5NGL_cjs=require('./chunk-VB7D5NGL.cjs'),chunkXJ6V5AZ4_cjs=require('./chunk-XJ6V5AZ4.cjs'),chunkZXXCTYVU_cjs=require('./chunk-ZXXCTYVU.cjs'),chunkCUSEWHH4_cjs=require('./chunk-CUSEWHH4.cjs'),chunkE7UESKJB_cjs=require('./chunk-E7UESKJB.cjs'),chunk5ZKHY3X3_cjs=require('./chunk-5ZKHY3X3.cjs');var C=new Map,W=3,B=60*60*1e3;function z(i){let e=Date.now(),r=C.get(i);return r?e-r.lastAttempt>B?(C.set(i,{count:1,lastAttempt:e}),true):r.count<W?(r.count++,r.lastAttempt=e,true):false:(C.set(i,{count:1,lastAttempt:e}),true)}async function F(i,e){let r=i.split("@")[0].toLowerCase().replace(/[^a-z0-9]/g,""),n=r,a=1;for(;e.findUserByUsername;)try{if(!await e.findUserByUsername(n))break;n=`${r}${a}`,a++;}catch{break}return n}async function Y(i,e,r={}){let{requireEmailVerification:n=false,autoSignin:a=true,includeUserProfile:m=true,customUserData:p={},skipPasswordValidation:l=false,generateUsername:w=false,username:u,firstName:D,lastName:N,fullName:y,profilePicture:S,requesterIp:t}=r;if(!i?.trim())throw new chunkCUSEWHH4_cjs.b("Email is required");if(!e?.trim())throw new chunkCUSEWHH4_cjs.b("Password is required");let d=i.toLowerCase().trim();if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(d))throw new chunkCUSEWHH4_cjs.b("Invalid email format");if(l){if(e.length<6)throw new chunkCUSEWHH4_cjs.b("Password must be at least 6 characters long")}else {let b=[d.split("@")[0]],V=chunkE7UESKJB_cjs.d(e,{},b);if(!V.isValid)throw new chunkCUSEWHH4_cjs.b(`Password validation failed: ${V.errors.join(", ")}`)}let v=t?`${d}|${t}`:d;if(!z(v))throw new chunkCUSEWHH4_cjs.b("Too many signup attempts. Please try again later.");let c=chunk5ZKHY3X3_cjs.b.db;if(!c)throw new Error("Database not configured. Make sure initAuth() is called before using authentication functions.");try{if(await c.findUserByEmail(d))throw new chunkCUSEWHH4_cjs.f("An account with this email already exists");let V=await chunkE7UESKJB_cjs.a(e,{skipValidation:l,identifier:d}),U={email:d,password:V,emailVerified:!n,createdAt:new Date,authMethod:"password",authProvider:"password",...p};typeof u=="string"&&u.trim()&&(U.username=u.trim()),typeof D=="string"&&D.trim()&&(U.firstName=D.trim()),typeof N=="string"&&N.trim()&&(U.lastName=N.trim()),typeof y=="string"&&y.trim()&&(U.fullName=y.trim()),typeof S=="string"&&S.trim()&&(U.profilePicture=S.trim()),w&&!U.username&&(U.username=await F(d,c)),n||(U.emailVerifiedAt=new Date);let s=await c.createUser(U),k={id:s.id,email:s.email};s.username&&(k.username=s.username),s.emailVerified&&(k.emailVerified=s.emailVerified);let o=chunkZXXCTYVU_cjs.a(k),x={id:s.id,email:s.email,createdAt:s.createdAt};return m&&(s.username&&(x.username=s.username),s.firstName&&(x.firstName=s.firstName),s.lastName&&(x.lastName=s.lastName),s.fullName&&(x.fullName=s.fullName),s.profilePicture&&(x.profilePicture=s.profilePicture),typeof s.emailVerified=="boolean"&&(x.emailVerified=s.emailVerified,s.emailVerified&&s.emailVerifiedAt instanceof Date&&(x.emailVerifiedAt=s.emailVerifiedAt))),{user:x,token:o,cookieOptions:{httpOnly:!0,secure:chunk5ZKHY3X3_cjs.b.forceSecureCookies||process.env.NODE_ENV==="production",maxAge:1e3*60*60*24*7,sameSite:"lax",path:"/"},isNewUser:!0,requiresEmailVerification:n}}catch(b){throw chunkXJ6V5AZ4_cjs.a.debug("Signup failed",{email:d,error:b instanceof Error?b.message:"Unknown error"}),b}}var E=new Map;function H(i,e=5,r=15){let n=Date.now(),a=E.get(i);return a?a.lockedUntil&&n>a.lockedUntil?(E.set(i,{count:1,lastAttempt:n}),{allowed:true,attemptsRemaining:e-1}):a.lockedUntil&&n<=a.lockedUntil?{allowed:false,attemptsRemaining:0,lockedUntil:new Date(a.lockedUntil)}:n-a.lastAttempt>60*60*1e3?(E.set(i,{count:1,lastAttempt:n}),{allowed:true,attemptsRemaining:e-1}):(a.count++,a.lastAttempt=n,a.count>=e?(a.lockedUntil=n+r*60*1e3,{allowed:false,attemptsRemaining:0,lockedUntil:new Date(a.lockedUntil)}):{allowed:true,attemptsRemaining:e-a.count}):(E.set(i,{count:1,lastAttempt:n}),{allowed:true,attemptsRemaining:e-1})}function X(i){E.delete(i);}async function ne(i,e,r={}){let{rememberMe:n=false,requireEmailVerification:a=false,updateLastLogin:m=true,includeUserProfile:p=true,maxLoginAttempts:l=5,lockoutDuration:w=15}=r;if(!i?.trim())throw new chunkCUSEWHH4_cjs.b("Email is required");if(!e?.trim())throw new chunkCUSEWHH4_cjs.b("Password is required");let u=i.toLowerCase().trim();if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(u))throw new chunkCUSEWHH4_cjs.b("Invalid email format");let N=r.requesterIp?`${u}|${r.requesterIp}`:u,y=H(N,l,w);if(!y.allowed){let t=y.lockedUntil?`Account temporarily locked. Try again after ${y.lockedUntil.toLocaleTimeString()}`:"Too many login attempts. Please try again later.";throw chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"auth",action:"signin",outcome:"locked",message:t,email:u,attemptsRemaining:0}),new chunkCUSEWHH4_cjs.d(t)}let S=chunk5ZKHY3X3_cjs.b.db;if(!S)throw new Error("Database not configured. Make sure initAuth() is called before using authentication functions.");try{let t=await S.findUserByEmail(u);if(!t)throw new chunkCUSEWHH4_cjs.c("Invalid email or password");let d=!1,P;try{let o=await chunkE7UESKJB_cjs.c(e,t.password,{identifier:u,updateHash:!!(chunk5ZKHY3X3_cjs.b.db&&chunk5ZKHY3X3_cjs.b.db.updateUser)});d=o.valid,o.valid&&o.needsRehash&&o.newHash&&(P=o.newHash);}catch(o){o instanceof Error?chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"auth",action:"password-verify-fallback",message:"Password verify fallback",error:o instanceof Error?o.message:String(o)}):chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"auth",action:"password-verify-fallback",message:"Password verify fallback (unknown error type)"}),d=await chunkE7UESKJB_cjs.b(e,t.password,{identifier:u});}if(!d)throw chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"auth",action:"signin",outcome:"invalid-credentials",message:"Invalid email or password",email:u,attemptsRemaining:y.attemptsRemaining}),new chunkCUSEWHH4_cjs.c("Invalid email or password");if(a&&!t.emailVerified)throw new chunkCUSEWHH4_cjs.d("Please verify your email address before signing in");if(t.isDisabled)throw new chunkCUSEWHH4_cjs.d("Account has been disabled. Please contact support.");X(u);let v=t.mustChangePassword||!1,c=t;if((m||P)&&S.updateUser)try{let o={};m&&(o.lastLoginAt=new Date,o.loginCount=(t.loginCount||0)+1),P&&(o.password=P,o.passwordChangedAt=new Date),Object.keys(o).length>0&&(c=await S.updateUser(t.id,o)||t);}catch(o){chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"auth",action:"post-auth-update",outcome:"failed",message:"Failed post-auth update",error:o instanceof Error?o.message:String(o)});}let b={id:t.id,email:t.email};t.username&&(b.username=t.username),t.emailVerified&&(b.emailVerified=t.emailVerified);let V=chunkZXXCTYVU_cjs.a(b),s=n?1e3*60*60*24*30:chunk5ZKHY3X3_cjs.b.sessionMaxAgeMs,k={id:c.id,email:c.email};return p&&(c.username&&(k.username=c.username),c.firstName&&(k.firstName=c.firstName),c.lastName&&(k.lastName=c.lastName),typeof c.emailVerified=="boolean"&&(k.emailVerified=c.emailVerified),c.lastLoginAt&&(k.lastLoginAt=c.lastLoginAt)),{user:k,token:V,cookieOptions:{httpOnly:!0,secure:chunk5ZKHY3X3_cjs.b.forceSecureCookies||process.env.NODE_ENV==="production",maxAge:s,sameSite:"lax",path:"/"},isFirstLogin:!t.lastLoginAt,mustChangePassword:v}}catch(t){let d=t instanceof Error?t.message:"Unknown error";throw t instanceof chunkCUSEWHH4_cjs.d?chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"auth",action:"signin",outcome:"forbidden",message:d,email:u,attemptsRemaining:y.attemptsRemaining}):t instanceof chunkCUSEWHH4_cjs.c?chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"auth",action:"signin",outcome:"unauthorized",message:d,email:u,attemptsRemaining:y.attemptsRemaining}):chunkXJ6V5AZ4_cjs.a.error("Signin failed",{email:u,error:d}),t}}function le(i={}){let{invalidateAllSessions:e=false,clearRememberMe:r=true,redirectUrl:n,extraClear:a=[]}=i,m=[{name:chunk5ZKHY3X3_cjs.b.cookieName,options:{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/",expires:new Date(0)}}];return r&&m.push({name:`${chunk5ZKHY3X3_cjs.b.cookieName}_remember`,options:{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/",expires:new Date(0)}}),a.forEach(p=>{typeof p=="string"&&p.trim()&&m.push({name:p.trim(),options:{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/",expires:new Date(0)}});}),{success:true,message:"Logged out successfully",cookiesToClear:m,redirectUrl:n}}async function $(i,e={}){let{requireEmailVerification:r=false,updateLastSeen:n=false,includeUserProfile:a=true}=e;try{if(!i?.trim())return null;let m=chunkVB7D5NGL_cjs.a(i);if(!m?.id)return null;let p=chunk5ZKHY3X3_cjs.b.db;if(!p)return chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"session",action:"validation",outcome:"skipped",message:"Database not configured for session validation"}),null;let l=await p.findUserById(m.id);if(!l||r&&!l.emailVerified)return null;if(n&&p.updateUser)try{await p.updateUser(l.id,{lastLoginAt:new Date});}catch(u){chunkXJ6V5AZ4_cjs.a.structuredWarn({category:"session",action:"update-last-login",outcome:"failed",message:"Failed to update last login timestamp",error:u instanceof Error?u.message:String(u)});}let w={id:l.id,email:l.email,createdAt:l.createdAt};return a&&(l.username&&(w.username=l.username),l.firstName&&(w.firstName=l.firstName),l.lastName&&(w.lastName=l.lastName),typeof l.emailVerified=="boolean"&&(w.emailVerified=l.emailVerified),l.lastLoginAt&&(w.lastLoginAt=l.lastLoginAt)),w}catch(m){return chunkXJ6V5AZ4_cjs.a.debug("Session validation error",m),null}}async function ge(i,e){return await $(i,e)!==null}async function pe(i,e={}){let r=await $(i,e);if(!r)return {user:null};try{if(chunk5ZKHY3X3_cjs.b.rollingSessionEnabled){let n=chunkVB7D5NGL_cjs.a(i);if(n.exp){let a=Math.floor(Date.now()/1e3),m=n.exp-a;if(m>0&&m<=chunk5ZKHY3X3_cjs.b.rollingSessionThresholdSeconds){let p=chunkZXXCTYVU_cjs.a({id:r.id,email:r.email});return {user:r,refreshedToken:p}}}}}catch{}return {user:r}}exports.a=Y;exports.b=ne;exports.c=le;exports.d=$;exports.e=ge;exports.f=pe;