better-auth 0.7.3 → 0.7.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/adapters/drizzle.d.cts +1 -1
- package/dist/adapters/drizzle.d.ts +1 -1
- package/dist/adapters/kysely.d.cts +1 -1
- package/dist/adapters/kysely.d.ts +1 -1
- package/dist/adapters/mongodb.d.cts +1 -1
- package/dist/adapters/mongodb.d.ts +1 -1
- package/dist/adapters/prisma.d.cts +1 -1
- package/dist/adapters/prisma.d.ts +1 -1
- package/dist/api.cjs +5 -5
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +5 -5
- package/dist/{auth-BkJnc76F.d.cts → auth-B5ozNy5X.d.cts} +1 -1
- package/dist/{auth-G61_RA8H.d.ts → auth-BBUjEh9D.d.ts} +1 -1
- package/dist/client/plugins.d.cts +4 -4
- package/dist/client/plugins.d.ts +4 -4
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/cookies.d.cts +1 -1
- package/dist/cookies.d.ts +1 -1
- package/dist/db.d.cts +2 -2
- package/dist/db.d.ts +2 -2
- package/dist/{index-cKD4sHma.d.ts → index-CQluFeIi.d.ts} +2 -2
- package/dist/{index-KdWDL1fo.d.cts → index-DK55nobk.d.cts} +2 -2
- package/dist/index.cjs +4 -4
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -5
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/oauth2.d.cts +2 -2
- package/dist/oauth2.d.ts +2 -2
- package/dist/plugins.cjs +6 -6
- package/dist/plugins.d.cts +73 -4
- package/dist/plugins.d.ts +73 -4
- package/dist/plugins.js +6 -6
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/solid-start.d.cts +1 -1
- package/dist/solid-start.d.ts +1 -1
- package/dist/solid.d.cts +1 -1
- package/dist/solid.d.ts +1 -1
- package/dist/{state-UgidHWa5.d.cts → state-8Gh7gmo8.d.cts} +1 -1
- package/dist/{state-CTWPRYsC.d.ts → state-BU1iZb12.d.ts} +1 -1
- package/dist/svelte-kit.d.cts +1 -1
- package/dist/svelte-kit.d.ts +1 -1
- package/dist/svelte.d.cts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/package.json +1 -1
package/dist/plugins.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{APIError as
|
|
2
|
-
`)}}),y=Er();function De(e){try{return new URL(e).origin}catch{return null}}async function ge(e,t){let r=e.body?.callbackURL||(e.query?.currentURL?De(e.query?.currentURL):"")||e.context.options.baseURL;if(!r)throw new ft("BAD_REQUEST",{message:"callbackURL is required"});let o=Rr(),n=Ir(),i=JSON.stringify({callbackURL:r,codeVerifier:o,errorURL:e.query?.currentURL,link:t,expiresAt:Date.now()+10*60*1e3}),a=new Date;a.setMinutes(a.getMinutes()+10);let s=await e.context.internalAdapter.createVerificationValue({value:i,identifier:n,expiresAt:a});if(!s)throw y.error("Unable to create verification. Make sure the database adapter is properly working and there is a verification table in the database"),new ft("INTERNAL_SERVER_ERROR",{message:"Unable to create verification"});return{state:s.identifier,codeVerifier:o}}async function xe(e){let t=e.query.state,r=await e.context.internalAdapter.findVerificationValue(t);if(!r)throw y.error("State Mismatch. Verification not found",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let o=re.object({callbackURL:re.string(),codeVerifier:re.string(),errorURL:re.string().optional(),expiresAt:re.number(),link:re.object({email:re.string(),userId:re.string()}).optional()}).parse(JSON.parse(r.value));if(o.errorURL||(o.errorURL=`${e.context.baseURL}/error`),o.expiresAt<Date.now())throw await e.context.internalAdapter.deleteVerificationValue(r.id),y.error("State expired.",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);return await e.context.internalAdapter.deleteVerificationValue(r.id),o}var gt=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=o||["email","name","openid"];return e.scope&&i.push(...e.scope),new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${i.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>v({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Ur(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Tr}from"@better-fetch/fetch";var ht=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["identify","email"];return e.scope&&n.push(...e.scope),new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>v({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Tr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Sr}from"@better-fetch/fetch";var wt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["email","public_profile"];return e.scope&&n.push(...e.scope),await I({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>v({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Sr("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,image:r.picture.data.url,emailVerified:r.email_verified},data:r}}});import{betterFetch as yt}from"@better-fetch/fetch";var bt=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"GitHub",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let a=o||["user:email"];return e.scope&&a.push(...e.scope),I({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>v({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await yt("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await yt("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as Pr}from"oslo/jwt";var At=e=>({id:"google",name:"Google",async createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw y.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("codeVerifier is required for Google");let i=r||["email","profile","openid"];e.scope&&i.push(...e.scope);let a=await I({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n});return e.accessType&&a.searchParams.set("access_type",e.accessType),e.prompt&&a.searchParams.set("prompt",e.prompt),a},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>v({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=Pr(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as _r}from"@better-fetch/fetch";import{parseJWT as Cr}from"oslo/jwt";var kt=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=n.scopes||["openid","profile","email","User.Read"];return e.scope&&i.push(...e.scope),I({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return v({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=Cr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await _r(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){y.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as zr}from"@better-fetch/fetch";var Ot=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=r||["user-read-email"];return e.scope&&i.push(...e.scope),I({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>v({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await zr("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";import{parseJWT as Br}from"oslo/jwt";var vt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["user:read:email","openid"];return e.scope&&n.push(...e.scope),I({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>v({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return y.error("No idToken found in token"),null;let o=Br(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Dr}from"@better-fetch/fetch";var Et=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=t.scopes||["account_info.read"];return e.scope&&r.push(...e.scope),I({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>v({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Dr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});import{betterFetch as xr}from"@better-fetch/fetch";var Rt=e=>{let t="https://api.dropboxapi.com/oauth2/token";return{id:"dropbox",name:"Dropbox",createAuthorizationURL:async({state:r,scopes:o,codeVerifier:n,redirectURI:i})=>{let a=o||["account_info.read"];return e.scope&&a.push(...e.scope),await I({id:"dropbox",options:e,authorizationEndpoint:"https://www.dropbox.com/oauth2/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>await v({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await xr("https://api.dropboxapi.com/2/users/get_current_account",{method:"POST",headers:{Authorization:`Bearer ${r.accessToken}`}});return n?null:{user:{id:o.account_id,name:o.name?.display_name,email:o.email,emailVerified:o.email_verified||!1,image:o.profile_photo_url},data:o}}}};import{betterFetch as Lr}from"@better-fetch/fetch";var It=e=>{let t="https://www.linkedin.com/oauth/v2/authorization",r="https://www.linkedin.com/oauth/v2/accessToken";return{id:"linkedin",name:"Linkedin",createAuthorizationURL:async({state:o,scopes:n,redirectURI:i})=>{let a=n||["profile","email","openid"];return e.scope&&a.push(...e.scope),await I({id:"linkedin",options:e,authorizationEndpoint:t,scopes:a,state:o,redirectURI:i})},validateAuthorizationCode:async({code:o,redirectURI:n})=>await v({code:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:r}),async getUserInfo(o){let{data:n,error:i}=await Lr("https://api.linkedin.com/v2/userinfo",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken}`}});return i?null:{user:{id:n.sub,name:n.name,email:n.email,emailVerified:n.email_verified||!1,image:n.picture},data:n}}}};import{betterFetch as jr}from"@better-fetch/fetch";var et=(e="")=>e.split("://").map(t=>t.replace(/\/{2,}/g,"/")).join("://"),Nr=e=>{let t=e||"https://gitlab.com";return{authorizationEndpoint:et(`${t}/oauth/authorize`),tokenEndpoint:et(`${t}/oauth/token`),userinfoEndpoint:et(`${t}/api/v4/user`)}},Ut=e=>{let{authorizationEndpoint:t,tokenEndpoint:r,userinfoEndpoint:o}=Nr(e.issuer),n="gitlab";return{id:n,name:"Gitlab",createAuthorizationURL:async({state:a,scopes:s,codeVerifier:d,redirectURI:c})=>{let l=s||["read_user"];return e.scope&&l.push(...e.scope),await I({id:n,options:e,authorizationEndpoint:t,scopes:l,state:a,redirectURI:c,codeVerifier:d})},validateAuthorizationCode:async({code:a,redirectURI:s})=>v({code:a,redirectURI:e.redirectURI||s,options:e,tokenEndpoint:r}),async getUserInfo(a){let{data:s,error:d}=await jr(o,{headers:{authorization:`Bearer ${a.accessToken}`}});return d||s.state!=="active"||s.locked?null:{user:{id:s.id.toString(),name:s.name??s.username,email:s.email,image:s.avatar_url,emailVerified:!0},data:s}}}};var Fr={apple:gt,discord:ht,facebook:wt,github:bt,microsoft:kt,google:At,spotify:Ot,twitch:vt,twitter:Et,dropbox:Rt,linkedin:It,gitlab:Ut},Le=Object.keys(Fr);import{TimeSpan as Mr}from"oslo";import{createJWT as $r,validateJWT as Qr}from"oslo/jwt";import{z as Q}from"zod";import{APIError as he}from"better-call";import{APIError as ve}from"better-call";import{z as Ee}from"zod";var Tt=()=>u("/get-session",{method:"GET",query:Ee.optional(Ee.object({disableCookieCache:Ee.boolean().optional()})),requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.getSignedCookie(e.context.authCookies.sessionData.name,e.context.secret),o=await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret);if(r&&e.context.options.session?.cookieCache?.enabled&&!e.query?.disableCookieCache){let c=JSON.parse(r)?.session;if(c?.expiresAt>new Date)return e.json(c)}let n=await e.context.internalAdapter.findSession(t);if(!n||n.session.expiresAt<new Date)return J(e),n&&await e.context.internalAdapter.deleteSession(n.session.id),e.json(null,{status:401});if(o)return e.json(n);let i=e.context.sessionConfig.expiresIn,a=e.context.sessionConfig.updateAge;if(n.session.expiresAt.valueOf()-i*1e3+a*1e3<=Date.now()){let c=await e.context.internalAdapter.updateSession(n.session.id,{expiresAt:C(e.context.sessionConfig.expiresIn,"sec")});if(!c)return J(e),e.json(null,{status:401});let l=(c.expiresAt.valueOf()-Date.now())/1e3;return await w(e,{session:c,user:n.user},!1,{maxAge:l}),e.json({session:c,user:n.user})}return e.json(n)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),D=async e=>await Tt()({...e,_flag:"json",headers:e.headers}),b=_(async e=>{let t=await D(e);if(!t?.session)throw new ve("UNAUTHORIZED");return{session:t}});var Vr=u("/revoke-session",{method:"POST",body:Ee.object({id:Ee.string()}),use:[b],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new ve("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new ve("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),qr=u("/revoke-sessions",{method:"POST",use:[b],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function oe(e,t,r){return await $r("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new Mr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Hr=u("/send-verification-email",{method:"POST",query:Q.object({currentURL:Q.string().optional()}).optional(),body:Q.object({email:Q.string().email(),callbackURL:Q.string().optional()})},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new he("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new he("BAD_REQUEST",{message:"User not found"});let o=await oe(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),Wr=u("/verify-email",{method:"GET",query:Q.object({token:Q.string(),callbackURL:Q.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await Qr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new he("BAD_REQUEST",{message:"Invalid token"})}let n=Q.object({email:Q.string().email(),updateTo:Q.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new he("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await D(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new he("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new he("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Gr=u("/sign-in/social",{method:"POST",query:V.object({currentURL:V.string().optional()}).optional(),body:V.object({callbackURL:V.string().optional(),provider:V.enum(Le)})},async e=>{let t=e.context.socialProviders.find(i=>i.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new H("NOT_FOUND",{message:"Provider not found"});let{codeVerifier:r,state:o}=await ge(e),n=await t.createAuthorizationURL({state:o,codeVerifier:r,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:n.toString(),redirect:!0})}),Kr=u("/sign-in/email",{method:"POST",body:V.object({email:V.string(),password:V.string(),callbackURL:V.string().optional(),dontRememberMe:V.boolean().default(!1).optional()})},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.context.logger.error("Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!"),new H("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!V.string().email().safeParse(t).success)throw new H("BAD_REQUEST",{message:"Invalid email"});if(!V.string().email().safeParse(t).success)throw new H("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new H("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new H("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new H("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new H("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw y.error("Email verification is required but no email verification handler is provided"),new H("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await oe(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new H("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new H("UNAUTHORIZED",{message:"Failed to create session"});return await w(e,{session:c,user:i.user},e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as Ne}from"zod";import{z as O}from"zod";var Cs=O.object({id:O.string(),providerId:O.string(),accountId:O.string(),userId:O.string(),accessToken:O.string().nullable().optional(),refreshToken:O.string().nullable().optional(),idToken:O.string().nullable().optional(),expiresAt:O.date().nullable().optional(),password:O.string().optional().nullable()}),je=O.object({id:O.string(),email:O.string().transform(e=>e.toLowerCase()),emailVerified:O.boolean().default(!1),name:O.string(),image:O.string().optional(),createdAt:O.date().default(new Date),updatedAt:O.date().default(new Date)}),zs=O.object({id:O.string(),userId:O.string(),expiresAt:O.date(),ipAddress:O.string().optional(),userAgent:O.string().optional()}),Bs=O.object({id:O.string(),value:O.string(),expiresAt:O.date(),identifier:O.string()});var Jr=u("/callback/:id",{method:"GET",query:Ne.object({state:Ne.string(),code:Ne.string().optional(),error:Ne.string().optional()}),metadata:fe},async e=>{if(!e.query.code)throw e.redirect(`${e.context.baseURL}/error?error=${e.query.error||"no_code"}`);let t=e.context.socialProviders.find(A=>A.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let{codeVerifier:r,callbackURL:o,link:n,errorURL:i}=await xe(e),a;try{a=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:r,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(A){throw e.context.logger.error(A),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let s=await t.getUserInfo(a).then(A=>A?.user),d=z(),c=je.safeParse({...s,id:d});if(!s||c.success===!1)throw y.error("Unable to get user info",c.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw y.error("No callback URL found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(n){if(n.email!==s.email.toLowerCase())return l("email_doesn't_match");if(!await e.context.internalAdapter.createAccount({userId:n.userId,providerId:t.id,accountId:s.id}))return l("unable_to_link_account");let h;try{h=new URL(o).toString()}catch{h=o}throw e.redirect(h)}function l(A){throw e.redirect(`${i||o||`${e.context.baseURL}/error`}?error=${A}`)}let p=await e.context.internalAdapter.findUserByEmail(s.email,{includeAccounts:!0}).catch(A=>{throw y.error(`Better auth was unable to query your database.
|
|
3
|
-
Error: `,
|
|
1
|
+
import{APIError as Wt}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as hr,createMiddleware as ct,createMiddlewareCreator as wr}from"better-call";var ut=ct(async()=>({})),T=wr({use:[ut,ct(async()=>({}))]}),u=hr({use:[ut]});import{APIError as W}from"better-call";import{z as V}from"zod";import{TimeSpan as un}from"oslo";var $=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r}};var ze=Object.create(null),Re=e=>globalThis.process?.env||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?ze:globalThis),Q=new Proxy(ze,{get(e,t){return Re()[t]??ze[t]},has(e,t){let r=Re();return t in r||t in ze},set(e,t,r){let o=Re(!0);return o[t]=r,!0},deleteProperty(e,t){if(!t)return!1;let r=Re(!0);return delete r[t],!0},ownKeys(){let e=Re(!0);return Object.keys(e)}});function yr(e){return e?e!=="false":!1}var Xe=typeof process<"u"&&process.env&&process.env.NODE_ENV||"";var lt=Xe==="dev"||Xe==="development",br=Xe==="test"||yr(Q.TEST);async function w(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t.session.id,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options),e.context.options.session?.cookieCache?.enabled&&await e.setSignedCookie(e.context.authCookies.sessionData.name,JSON.stringify(t),e.context.secret,e.context.authCookies.sessionData.options),e.context.options.secondaryStorage&&await e.context.secondaryStorage?.set(t.session.id,JSON.stringify({user:t.user,session:t.session}),t.session.expiresAt.getTime()-Date.now())}function Z(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.sessionData.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function pt(e){let t=new Map;return e.split(", ").forEach(o=>{let[n,...i]=o.split("; "),[a,s]=n.split("="),d={value:s};i.forEach(c=>{let[l,p]=c.split("=");d[l.toLowerCase()]=p||!0}),t.set(a,d)}),t}function Be(e){let t=e.split("; "),r=new Map;return t.forEach(o=>{let[n,i]=o.split("=");r.set(n,i)}),r}import{parseJWT as Tr}from"oslo/jwt";import{sha256 as Ar}from"oslo/crypto";import{base64url as kr}from"oslo/encoding";var C=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));async function mt(e){let t=await Ar(new TextEncoder().encode(e));return kr.encode(new Uint8Array(t),{includePadding:!1})}function ft(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_in?C(e.expires_in,"sec"):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function U({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await mt(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,m)=>(p[m]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}import{betterFetch as Or}from"@better-fetch/fetch";async function R({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let i=new URLSearchParams;i.set("grant_type","authorization_code"),i.set("code",e),t&&i.set("code_verifier",t),i.set("redirect_uri",r),i.set("client_id",o.clientId),i.set("client_secret",o.clientSecret);let{data:a,error:s}=await Or(n,{method:"POST",body:i,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(s)throw s;return ft(a)}import{generateCodeVerifier as Ur,generateState as Ir}from"oslo/oauth2";import{z as oe}from"zod";import{APIError as gt}from"better-call";var we={isAction:!1};import{nanoid as Rr}from"nanoid";var z=e=>Rr(e);import{createConsola as vr}from"consola";var ce=vr({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),Er=e=>({log:(...t)=>{!e?.disabled&&ce.log("",...t)},error:(...t)=>{!e?.disabled&&ce.error("",...t)},warn:(...t)=>{!e?.disabled&&ce.warn("",...t)},info:(...t)=>{!e?.disabled&&ce.info("",...t)},debug:(...t)=>{!e?.disabled&&ce.debug("",...t)},box:(...t)=>{!e?.disabled&&ce.box("",...t)},success:(...t)=>{!e?.disabled&&ce.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
|
|
2
|
+
`)}}),y=Er();function Le(e){try{return new URL(e).origin}catch{return null}}async function ye(e,t){let r=e.body?.callbackURL||(e.query?.currentURL?Le(e.query?.currentURL):"")||e.context.options.baseURL;if(!r)throw new gt("BAD_REQUEST",{message:"callbackURL is required"});let o=Ur(),n=Ir(),i=JSON.stringify({callbackURL:r,codeVerifier:o,errorURL:e.query?.currentURL,link:t,expiresAt:Date.now()+10*60*1e3}),a=new Date;a.setMinutes(a.getMinutes()+10);let s=await e.context.internalAdapter.createVerificationValue({value:i,identifier:n,expiresAt:a});if(!s)throw y.error("Unable to create verification. Make sure the database adapter is properly working and there is a verification table in the database"),new gt("INTERNAL_SERVER_ERROR",{message:"Unable to create verification"});return{state:s.identifier,codeVerifier:o}}async function xe(e){let t=e.query.state,r=await e.context.internalAdapter.findVerificationValue(t);if(!r)throw y.error("State Mismatch. Verification not found",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let o=oe.object({callbackURL:oe.string(),codeVerifier:oe.string(),errorURL:oe.string().optional(),expiresAt:oe.number(),link:oe.object({email:oe.string(),userId:oe.string()}).optional()}).parse(JSON.parse(r.value));if(o.errorURL||(o.errorURL=`${e.context.baseURL}/error`),o.expiresAt<Date.now())throw await e.context.internalAdapter.deleteVerificationValue(r.id),y.error("State expired.",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);return await e.context.internalAdapter.deleteVerificationValue(r.id),o}var ht=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=o||["email","name","openid"];return e.scope&&i.push(...e.scope),new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${i.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>R({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Tr(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Sr}from"@better-fetch/fetch";var wt=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["identify","email"];return e.scope&&n.push(...e.scope),new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>R({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Sr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Pr}from"@better-fetch/fetch";var yt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["email","public_profile"];return e.scope&&n.push(...e.scope),await U({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>R({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Pr("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,image:r.picture.data.url,emailVerified:r.email_verified},data:r}}});import{betterFetch as bt}from"@better-fetch/fetch";var At=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"GitHub",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let a=o||["user:email"];return e.scope&&a.push(...e.scope),U({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>R({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await bt("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await bt("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as _r}from"oslo/jwt";var kt=e=>({id:"google",name:"Google",async createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw y.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("codeVerifier is required for Google");let i=r||["email","profile","openid"];e.scope&&i.push(...e.scope);let a=await U({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n});return e.accessType&&a.searchParams.set("access_type",e.accessType),e.prompt&&a.searchParams.set("prompt",e.prompt),a},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>R({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=_r(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as Cr}from"@better-fetch/fetch";import{parseJWT as zr}from"oslo/jwt";var Ot=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=n.scopes||["openid","profile","email","User.Read"];return e.scope&&i.push(...e.scope),U({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return R({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=zr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Cr(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){y.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as Br}from"@better-fetch/fetch";var Rt=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=r||["user-read-email"];return e.scope&&i.push(...e.scope),U({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>R({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await Br("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";import{parseJWT as Lr}from"oslo/jwt";var vt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["user:read:email","openid"];return e.scope&&n.push(...e.scope),U({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>R({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return y.error("No idToken found in token"),null;let o=Lr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as xr}from"@better-fetch/fetch";var Et=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=t.scopes||["account_info.read"];return e.scope&&r.push(...e.scope),U({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>R({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await xr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});import{betterFetch as Dr}from"@better-fetch/fetch";var Ut=e=>{let t="https://api.dropboxapi.com/oauth2/token";return{id:"dropbox",name:"Dropbox",createAuthorizationURL:async({state:r,scopes:o,codeVerifier:n,redirectURI:i})=>{let a=o||["account_info.read"];return e.scope&&a.push(...e.scope),await U({id:"dropbox",options:e,authorizationEndpoint:"https://www.dropbox.com/oauth2/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>await R({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await Dr("https://api.dropboxapi.com/2/users/get_current_account",{method:"POST",headers:{Authorization:`Bearer ${r.accessToken}`}});return n?null:{user:{id:o.account_id,name:o.name?.display_name,email:o.email,emailVerified:o.email_verified||!1,image:o.profile_photo_url},data:o}}}};import{betterFetch as jr}from"@better-fetch/fetch";var It=e=>{let t="https://www.linkedin.com/oauth/v2/authorization",r="https://www.linkedin.com/oauth/v2/accessToken";return{id:"linkedin",name:"Linkedin",createAuthorizationURL:async({state:o,scopes:n,redirectURI:i})=>{let a=n||["profile","email","openid"];return e.scope&&a.push(...e.scope),await U({id:"linkedin",options:e,authorizationEndpoint:t,scopes:a,state:o,redirectURI:i})},validateAuthorizationCode:async({code:o,redirectURI:n})=>await R({code:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:r}),async getUserInfo(o){let{data:n,error:i}=await jr("https://api.linkedin.com/v2/userinfo",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken}`}});return i?null:{user:{id:n.sub,name:n.name,email:n.email,emailVerified:n.email_verified||!1,image:n.picture},data:n}}}};import{betterFetch as Nr}from"@better-fetch/fetch";var et=(e="")=>e.split("://").map(t=>t.replace(/\/{2,}/g,"/")).join("://"),Fr=e=>{let t=e||"https://gitlab.com";return{authorizationEndpoint:et(`${t}/oauth/authorize`),tokenEndpoint:et(`${t}/oauth/token`),userinfoEndpoint:et(`${t}/api/v4/user`)}},Tt=e=>{let{authorizationEndpoint:t,tokenEndpoint:r,userinfoEndpoint:o}=Fr(e.issuer),n="gitlab";return{id:n,name:"Gitlab",createAuthorizationURL:async({state:a,scopes:s,codeVerifier:d,redirectURI:c})=>{let l=s||["read_user"];return e.scope&&l.push(...e.scope),await U({id:n,options:e,authorizationEndpoint:t,scopes:l,state:a,redirectURI:c,codeVerifier:d})},validateAuthorizationCode:async({code:a,redirectURI:s})=>R({code:a,redirectURI:e.redirectURI||s,options:e,tokenEndpoint:r}),async getUserInfo(a){let{data:s,error:d}=await Nr(o,{headers:{authorization:`Bearer ${a.accessToken}`}});return d||s.state!=="active"||s.locked?null:{user:{id:s.id.toString(),name:s.name??s.username,email:s.email,image:s.avatar_url,emailVerified:!0},data:s}}}};var Vr={apple:ht,discord:wt,facebook:yt,github:At,microsoft:Ot,google:kt,spotify:Rt,twitch:vt,twitter:Et,dropbox:Ut,linkedin:It,gitlab:Tt},De=Object.keys(Vr);import{TimeSpan as $r}from"oslo";import{createJWT as Qr,validateJWT as Hr}from"oslo/jwt";import{z as H}from"zod";import{APIError as be}from"better-call";import{APIError as ve}from"better-call";import{z as Ee}from"zod";var St=()=>u("/get-session",{method:"GET",query:Ee.optional(Ee.object({disableCookieCache:Ee.boolean().optional()})),requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.getSignedCookie(e.context.authCookies.sessionData.name,e.context.secret),o=await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret);if(r&&e.context.options.session?.cookieCache?.enabled&&!e.query?.disableCookieCache){let c=JSON.parse(r)?.session;if(c?.expiresAt>new Date)return e.json(c)}let n=await e.context.internalAdapter.findSession(t);if(!n||n.session.expiresAt<new Date)return Z(e),n&&await e.context.internalAdapter.deleteSession(n.session.id),e.json(null,{status:401});if(o)return e.json(n);let i=e.context.sessionConfig.expiresIn,a=e.context.sessionConfig.updateAge;if(n.session.expiresAt.valueOf()-i*1e3+a*1e3<=Date.now()){let c=await e.context.internalAdapter.updateSession(n.session.id,{expiresAt:C(e.context.sessionConfig.expiresIn,"sec")});if(!c)return Z(e),e.json(null,{status:401});let l=(c.expiresAt.valueOf()-Date.now())/1e3;return await w(e,{session:c,user:n.user},!1,{maxAge:l}),e.json({session:c,user:n.user})}return e.json(n)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),L=async e=>await St()({...e,_flag:"json",headers:e.headers}),A=T(async e=>{let t=await L(e);if(!t?.session)throw new ve("UNAUTHORIZED");return{session:t}});var qr=u("/revoke-session",{method:"POST",body:Ee.object({id:Ee.string()}),use:[A],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new ve("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new ve("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Mr=u("/revoke-sessions",{method:"POST",use:[A],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function ne(e,t,r){return await Qr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new $r(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Wr=u("/send-verification-email",{method:"POST",query:H.object({currentURL:H.string().optional()}).optional(),body:H.object({email:H.string().email(),callbackURL:H.string().optional()})},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be("BAD_REQUEST",{message:"User not found"});let o=await ne(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),Gr=u("/verify-email",{method:"GET",query:H.object({token:H.string(),callbackURL:H.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await Hr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be("BAD_REQUEST",{message:"Invalid token"})}let n=H.object({email:H.string().email(),updateTo:H.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await L(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Kr=u("/sign-in/social",{method:"POST",query:V.object({currentURL:V.string().optional()}).optional(),body:V.object({callbackURL:V.string().optional(),provider:V.enum(De)})},async e=>{let t=e.context.socialProviders.find(i=>i.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new W("NOT_FOUND",{message:"Provider not found"});let{codeVerifier:r,state:o}=await ye(e),n=await t.createAuthorizationURL({state:o,codeVerifier:r,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:n.toString(),redirect:!0})}),Jr=u("/sign-in/email",{method:"POST",body:V.object({email:V.string(),password:V.string(),callbackURL:V.string().optional(),dontRememberMe:V.boolean().default(!1).optional()})},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.context.logger.error("Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!"),new W("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!V.string().email().safeParse(t).success)throw new W("BAD_REQUEST",{message:"Invalid email"});if(!V.string().email().safeParse(t).success)throw new W("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new W("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new W("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new W("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new W("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw y.error("Email verification is required but no email verification handler is provided"),new W("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await ne(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new W("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new W("UNAUTHORIZED",{message:"Failed to create session"});return await w(e,{session:c,user:i.user},e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as Ne}from"zod";import{z as O}from"zod";var Bs=O.object({id:O.string(),providerId:O.string(),accountId:O.string(),userId:O.string(),accessToken:O.string().nullable().optional(),refreshToken:O.string().nullable().optional(),idToken:O.string().nullable().optional(),expiresAt:O.date().nullable().optional(),password:O.string().optional().nullable()}),je=O.object({id:O.string(),email:O.string().transform(e=>e.toLowerCase()),emailVerified:O.boolean().default(!1),name:O.string(),image:O.string().optional(),createdAt:O.date().default(new Date),updatedAt:O.date().default(new Date)}),Ls=O.object({id:O.string(),userId:O.string(),expiresAt:O.date(),ipAddress:O.string().optional(),userAgent:O.string().optional()}),xs=O.object({id:O.string(),value:O.string(),expiresAt:O.date(),identifier:O.string()});var Zr=u("/callback/:id",{method:"GET",query:Ne.object({state:Ne.string(),code:Ne.string().optional(),error:Ne.string().optional()}),metadata:we},async e=>{if(!e.query.code)throw e.redirect(`${e.context.baseURL}/error?error=${e.query.error||"no_code"}`);let t=e.context.socialProviders.find(b=>b.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let{codeVerifier:r,callbackURL:o,link:n,errorURL:i}=await xe(e),a;try{a=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:r,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(b){throw e.context.logger.error(b),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let s=await t.getUserInfo(a).then(b=>b?.user),d=z(),c=je.safeParse({...s,id:d});if(!s||c.success===!1)throw y.error("Unable to get user info",c.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw y.error("No callback URL found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(n){if(n.email!==s.email.toLowerCase())return l("email_doesn't_match");if(!await e.context.internalAdapter.createAccount({userId:n.userId,providerId:t.id,accountId:s.id}))return l("unable_to_link_account");let h;try{h=new URL(o).toString()}catch{h=o}throw e.redirect(h)}function l(b){throw e.redirect(`${i||o||`${e.context.baseURL}/error`}?error=${b}`)}let p=await e.context.internalAdapter.findUserByEmail(s.email,{includeAccounts:!0}).catch(b=>{throw y.error(`Better auth was unable to query your database.
|
|
3
|
+
Error: `,b),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=p?.user;if(p){let b=p.accounts.find(h=>h.providerId===t.id);if(b)await e.context.internalAdapter.updateAccount(b.id,{accessToken:a.accessToken,idToken:a.idToken,refreshToken:a.refreshToken,expiresAt:a.accessTokenExpiresAt});else{(!e.context.options.account?.accountLinking?.trustedProviders?.includes(t.id)&&!s.emailVerified||e.context.options.account?.accountLinking?.enabled===!1)&&(lt&&y.warn(`User already exist but account isn't linked to ${t.id}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`),l("account_not_linked"));try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:s.id.toString(),id:`${t.id}:${s.id}`,userId:p.user.id,accessToken:a.accessToken,idToken:a.idToken,refreshToken:a.refreshToken,expiresAt:a.accessTokenExpiresAt})}catch(ge){y.error("Unable to link account",ge),l("unable_to_link_account")}}}else try{let b=s.emailVerified||!1;if(m=await e.context.internalAdapter.createOAuthUser({...c.data,emailVerified:b},{accessToken:a.accessToken,idToken:a.idToken,refreshToken:a.refreshToken,expiresAt:a.accessTokenExpiresAt,providerId:t.id,accountId:s.id.toString()}).then(h=>h?.user),!b&&m&&e.context.options.emailVerification?.sendOnSignUp){let h=await ne(e.context.secret,m.email),_=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(m,_,h)}}catch(b){y.error("Unable to create user",b),l("unable_to_create_user")}if(!m)return l("unable_to_create_user");let f=await e.context.internalAdapter.createSession(m.id,e.request);f||l("unable_to_create_session"),await w(e,{session:f,user:m});let k;try{k=new URL(o).toString()}catch{k=o}throw e.redirect(k)});import"zod";import{APIError as Yr}from"better-call";var Xr=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Yr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),Z(e),e.json({success:!0})});import{z as G}from"zod";import{APIError as Fe}from"better-call";function Pt(e,t,r){let o=t?new URL(t,e.baseURL):new URL(`${e.baseURL}/error`);return r&&Object.entries(r).forEach(([n,i])=>o.searchParams.set(n,i)),o.href}function eo(e,t,r){let o=new URL(t,e.baseURL);return r&&Object.entries(r).forEach(([n,i])=>o.searchParams.set(n,i)),o.href}var to=u("/forget-password",{method:"POST",body:G.object({email:G.string().email(),redirectTo:G.string()})},async e=>{if(!e.context.options.emailAndPassword?.sendResetPassword)throw e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function in your auth config!"),new Fe("BAD_REQUEST",{message:"Reset password isn't enabled"});let{email:t,redirectTo:r}=e.body,o=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!o)return e.context.logger.error("Reset Password: User not found",{email:t}),e.json({status:!1},{body:{status:!0}});let n=60*60*1,i=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),a=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${a}`,expiresAt:i});let s=`${e.context.baseURL}/reset-password/${a}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(o.user,s),e.json({status:!0})}),ro=u("/reset-password/:token",{method:"GET",query:G.object({callbackURL:G.string()})},async e=>{let{token:t}=e.params,{callbackURL:r}=e.query;if(!t||!r)throw e.redirect(Pt(e.context,r,{error:"INVALID_TOKEN"}));let o=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!o||o.expiresAt<new Date?e.redirect(Pt(e.context,r,{error:"INVALID_TOKEN"})):e.redirect(eo(e.context,r,{token:t}))}),oo=u("/reset-password",{query:G.optional(G.object({token:G.string().optional(),currentURL:G.string().optional()})),method:"POST",body:G.object({newPassword:G.string()})},async e=>{let t=e.query?.token||(e.query?.currentURL?new URL(e.query.currentURL).searchParams.get("token"):"");if(!t)throw new Fe("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new Fe("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let i=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(i)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:i,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(i,a))throw new Fe("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{z as j}from"zod";import{APIError as D}from"better-call";var io=u("/change-password",{method:"POST",body:j.object({newPassword:j.string(),currentPassword:j.string(),revokeOtherSessions:j.boolean().optional()}),use:[A]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,i=e.context.password.config.minPasswordLength;if(t.length<i)throw e.context.logger.error("Password is too short"),new D("BAD_REQUEST",{message:"Password is too short"});let a=e.context.password.config.maxPasswordLength;if(t.length>a)throw e.context.logger.error("Password is too long"),new D("BAD_REQUEST",{message:"Password too long"});let d=(await e.context.internalAdapter.findAccounts(n.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!d||!d.password)throw new D("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new D("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:c}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new D("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await w(e,{session:p,user:n.user})}return e.json(n.user)}),so=u("/set-password",{method:"POST",body:j.object({newPassword:j.string()}),metadata:{SERVER_ONLY:!0},use:[A]},async e=>{let{newPassword:t}=e.body,r=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)throw e.context.logger.error("Password is too short"),new D("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new D("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(r.user.id)).find(d=>d.providerId==="credential"&&d.password),s=await e.context.password.hash(t);if(!a)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:s}),e.json(r.user);throw new D("BAD_REQUEST",{message:"user already has a password"})}),ao=u("/delete-user",{method:"POST",body:j.object({password:j.string()}),use:[A]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new D("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new D("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),Z(e),e.json(null)}),co=u("/change-email",{method:"POST",query:j.object({currentURL:j.string().optional()}).optional(),body:j.object({newEmail:j.string().email(),callbackURL:j.string().optional()}),use:[A]},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new D("BAD_REQUEST",{message:"Change email is disabled"});if(e.body.newEmail===e.context.session.user.email)throw e.context.logger.error("Email is the same"),new D("BAD_REQUEST",{message:"Email is the same"});if(await e.context.internalAdapter.findUserByEmail(e.body.newEmail))throw e.context.logger.error("Email already exists"),new D("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let n=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:n,status:!0})}if(!e.context.options.user.changeEmail.sendChangeEmailVerification)throw e.context.logger.error("Verification email isn't enabled."),new D("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await ne(e.context.secret,e.context.session.user.email,e.body.newEmail),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.user.changeEmail.sendChangeEmailVerification(e.context.session.user,e.body.newEmail,o,r),e.json({user:null,status:!0})});var uo=(e="Unknown")=>`<!DOCTYPE html>
|
|
4
4
|
<html lang="en">
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="UTF-8">
|
|
@@ -80,6 +80,6 @@ Error: `,A),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)
|
|
|
80
80
|
<div class="error-code">Error Code: <span id="errorCode">${e}</span></div>
|
|
81
81
|
</div>
|
|
82
82
|
</body>
|
|
83
|
-
</html>`,
|
|
84
|
-
`,`Current list of trustedOrigins: ${d}`),new bo("FORBIDDEN",{message:`Invalid ${m}`})};c&&!e.context.options.advanced?.disableCSRFCheck&&l(n,"origin"),i&&l(i,"callbackURL"),a&&l(a,"redirectURL"),s&&l(s,"currentURL")});import{APIError as E}from"better-call";var B=_(async e=>({})),x=_({use:[b]},async e=>({session:e.context.session}));import{z as q}from"zod";import{z as R}from"zod";var Me=R.enum(["admin","member","owner"]),ko=R.enum(["pending","accepted","rejected","canceled"]).default("pending"),Zd=R.object({id:R.string(),name:R.string(),slug:R.string(),logo:R.string().optional(),metadata:R.record(R.string()).or(R.string().transform(e=>JSON.parse(e))).optional(),createdAt:R.date()}),Yd=R.object({id:R.string(),email:R.string(),organizationId:R.string(),userId:R.string(),role:Me,createdAt:R.date()}),Xd=R.object({id:R.string(),organizationId:R.string(),email:R.string(),role:Me,status:ko,inviterId:R.string(),expiresAt:R.date()});import{APIError as U}from"better-call";var zt=u("/organization/invite-member",{method:"POST",use:[B,x],body:q.object({email:q.string(),role:Me,organizationId:q.string().optional(),resend:q.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw y.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new U("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new U("BAD_REQUEST",{message:"Organization not found"});let o=S(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new U("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new U("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new U("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new U("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new U("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new U("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),Bt=u("/organization/accept-invitation",{method:"POST",body:q.object({invitationId:q.string()}),use:[B,x]},async e=>{let t=e.context.session,r=S(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new U("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new U("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:z(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),Dt=u("/organization/reject-invitation",{method:"POST",body:q.object({invitationId:q.string()}),use:[B,x]},async e=>{let t=e.context.session,r=S(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new U("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new U("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),xt=u("/organization/cancel-invitation",{method:"POST",body:q.object({invitationId:q.string()}),use:[B,x]},async e=>{let t=e.context.session,r=S(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new U("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new U("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new U("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),Lt=u("/organization/get-invitation",{method:"GET",use:[B],requireHeaders:!0,query:q.object({id:q.string()})},async e=>{let t=await D(e);if(!t)throw new U("UNAUTHORIZED",{message:"Not authenticated"});let r=S(e.context,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new U("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new U("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new U("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new U("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as ae}from"zod";import{APIError as Ie}from"better-call";var jt=u("/organization/remove-member",{method:"POST",body:ae.object({memberIdOrEmail:ae.string(),organizationId:ae.string().optional()}),use:[B,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=S(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ie("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ie("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ie("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ie("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Ie("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Nt=u("/organization/update-member-role",{method:"POST",body:ae.object({role:ae.enum(["admin","member","owner"]),memberId:ae.string(),organizationId:ae.string().optional()}),use:[B,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=S(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as T}from"zod";import{APIError as de}from"better-call";var Ft=u("/organization/create",{method:"POST",body:T.object({name:T.string(),slug:T.string(),userId:T.string().optional(),logo:T.string().optional(),metadata:T.record(T.string()).optional()}),use:[B,x]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new de("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=S(e.context,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new de("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new de("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:z(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),Vt=u("/organization/update",{method:"POST",body:T.object({data:T.object({name:T.string().optional(),slug:T.string().optional()}).partial(),orgId:T.string().optional()}),requireHeaders:!0,use:[B]},async e=>{let t=await e.context.getSession(e);if(!t)throw new de("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=S(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["update"]}).error)return e.json(null,{body:{message:"You are not allowed to update this organization"},status:403});let s=await o.updateOrganization(r,e.body.data);return e.json(s)}),qt=u("/organization/delete",{method:"POST",body:T.object({orgId:T.string()}),requireHeaders:!0,use:[B]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=S(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["delete"]}).error)throw new de("FORBIDDEN",{message:"You are not allowed to delete this organization"});return r===t.session.activeOrganizationId&&await o.setActiveOrganization(t.session.id,null),await o.deleteOrganization(r),e.json(r)}),Mt=u("/organization/get-full",{method:"GET",query:T.optional(T.object({orgId:T.string().optional()})),requireHeaders:!0,use:[B,x]},async e=>{let t=e.context.session,r=e.query?.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:200});let n=await S(e.context,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new de("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),$t=u("/organization/activate",{method:"POST",body:T.object({orgId:T.string().nullable().optional()}),use:[x,B]},async e=>{let t=S(e.context,e.context.orgOptions),r=e.context.session,o=e.body.orgId;if(o===null)return r.session.activeOrganizationId&&await t.setActiveOrganization(r.session.id,null),e.json(null);if(!o){let a=r.session.activeOrganizationId;if(!a)return e.json(null);o=a}if(!await t.findMemberByOrgId({userId:r.user.id,organizationId:o}))throw await t.setActiveOrganization(r.session.id,null),new de("FORBIDDEN",{message:"You are not a member of this organization"});await t.setActiveOrganization(r.session.id,o);let i=await t.findFullOrganization(o,e.context.db||void 0);return e.json(i)}),Qt=u("/organization/list",{method:"GET",use:[B,x]},async e=>{let r=await S(e.context,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var Dc=e=>{let t={createOrganization:Ft,updateOrganization:Vt,deleteOrganization:qt,setActiveOrganization:$t,getFullOrganization:Mt,listOrganization:Qt,createInvitation:zt,cancelInvitation:xt,acceptInvitation:Bt,getInvitation:Lt,rejectInvitation:Dt,removeMember:jt,updateMemberRole:Nt},r={...Ct,...e?.roles};return{id:"organization",endpoints:{..._t(t,{orgOptions:e||{},roles:r,getSession:async n=>await D(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Ue.object({permission:Ue.record(Ue.string(),Ue.array(Ue.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new Ht("BAD_REQUEST",{message:"No active organization"});let a=await S(n.context).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Ht("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import Wt from"uncrypto";function Oo(e){return e.toString(2).padStart(8,"0")}function vo(e){return[...e].map(t=>Oo(t)).join("")}function Gt(e){return parseInt(vo(e),2)}function Eo(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));Wt.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=Gt(o);for(;n>=e;)Wt.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Gt(o);return n}function N(e,t){let r="";for(let o=0;o<e;o++)r+=t[Eo(t.length)];return r}function F(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}import{z as Ge}from"zod";import{xchacha20poly1305 as Jt}from"@noble/ciphers/chacha";import{bytesToHex as Ro,hexToBytes as Io,utf8ToBytes as Uo}from"@noble/ciphers/utils";import{managedNonce as Zt}from"@noble/ciphers/webcrypto";import{sha256 as Yt}from"oslo/crypto";import Kt from"uncrypto";import{decodeHex as $c,encodeHex as Qc}from"oslo/encoding";import{scryptAsync as Gc}from"@noble/hashes/scrypt";import{getRandomValues as Jc}from"uncrypto";async function ce(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await Kt.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),i=await Kt.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(i)))}var ye=async({key:e,data:t})=>{let r=await Yt(new TextEncoder().encode(e)),o=Uo(t),n=Zt(Jt)(new Uint8Array(r));return Ro(n.encrypt(o))},be=async({key:e,data:t})=>{let r=await Yt(new TextEncoder().encode(e)),o=Io(t),n=Zt(Jt)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};import{z as Z}from"zod";import{APIError as ne}from"better-call";var $e="two_factor";var Qe="trust_device";import{z as Xt}from"zod";var ue=_({body:Xt.object({trustDevice:Xt.boolean().optional()})},async e=>{let t=await D(e);if(!t){let r=e.context.createAuthCookie($e),o=await e.getSignedCookie(r.name,e.context.secret);if(!o)throw new ne("UNAUTHORIZED",{message:"invalid two factor cookie"});let[n,i]=o.split("!");if(!n||!i)throw new ne("UNAUTHORIZED",{message:"invalid two factor cookie"});let a=await e.context.adapter.findMany({model:e.context.tables.session.tableName,where:[{field:"userId",value:n}]});if(!a.length)throw new ne("UNAUTHORIZED",{message:"invalid session"});let s=a.filter(d=>d.expiresAt>new Date);if(!s)throw new ne("UNAUTHORIZED",{message:"invalid session"});for(let d of s){let c=await ce(e.context.secret,d.id),l=await e.context.adapter.findOne({model:e.context.tables.user.tableName,where:[{field:"id",value:d.userId}]});if(!l)throw new ne("UNAUTHORIZED",{message:"invalid session"});if(c===i)return{valid:async()=>{if(await w(e,{session:d,user:l},!1),e.body.trustDevice){let p=e.context.createAuthCookie(Qe,{maxAge:2592e3}),m=await ce(e.context.secret,`${l.id}!${d.id}`);await e.setSignedCookie(p.name,`${m}!${d.id}`,e.context.secret,p.attributes)}return e.json({session:d,user:l})},invalid:async()=>{throw new ne("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:d.id,userId:d.userId,expiresAt:d.expiresAt,user:l}}}throw new ne("UNAUTHORIZED",{message:"invalid two factor cookie"})}return{valid:async()=>e.json({session:t,user:t.user}),invalid:async()=>{throw new ne("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:t}});import{APIError as Te}from"better-call";function To(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>N(e?.length??10,F("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function rt(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():To(),n=await ye({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function So(e,t){let r=await er(e.backupCodes,t);return r?r.includes(e.code):!1}async function er(e,t){let r=Buffer.from(await be({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Z.array(Z.string()).safeParse(o);return n.success?n.data:null}var tr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:Z.object({code:Z.string(),disableSession:Z.boolean().optional()}),use:[ue]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Te("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!So({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Te("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await w(r,{session:r.context.session,user:o}),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",body:Z.object({password:Z.string()}),use:[b]},async r=>{let o=r.context.session.user;if(!o.twoFactorEnabled)throw new Te("BAD_REQUEST",{message:"Two factor isn't enabled"});await r.context.password.checkPassword(o.id,r);let n=await rt(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",body:Z.object({password:Z.string()}),use:[b]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Te("BAD_REQUEST",{message:"Backup codes aren't enabled"});await r.context.password.checkPassword(o.id,r);let i=er(n.backupCodes,r.context.secret);if(!i)throw new Te("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as He}from"better-call";import{TOTPController as Po}from"oslo/otp";import{z as rr}from"zod";import{TimeSpan as _o}from"oslo";var or=(e,t)=>{let r={...e,period:new _o(e?.period||3,"m")},o=new Po({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[ue]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new He("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"OTP isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:rr.object({code:rr.string()}),use:[ue]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new He("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"OTP isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as Ae}from"better-call";import{TimeSpan as Co}from"oslo";import{TOTPController as nr,createTOTPKeyURI as zo}from"oslo/otp";import{z as We}from"zod";var ir=(e,t)=>{let r={...e,digits:6,period:new Co(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[b]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new nr(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"POST",use:[b],body:We.object({password:We.string()})},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});return await a.context.password.checkPassword(s.id,a),{totpURI:zo(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:We.object({code:We.string()}),use:[ue]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});let c=new nr(r),l=await be({key:a.context.secret,data:d.secret}),p=Buffer.from(l);if(!await c.verify(a.body.code,p))return a.context.invalid();if(!s.twoFactorEnabled){let f=await a.context.internalAdapter.updateUser(s.id,{twoFactorEnabled:!0}),k=await a.context.internalAdapter.createSession(s.id,a.request);await w(a,{session:k,user:f})}return a.context.valid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};import{APIError as $u}from"better-call";async function ot(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as sr}from"better-call";import{createTOTPKeyURI as Bo}from"oslo/otp";import{TimeSpan as Do}from"oslo";var Hu=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t.startsWith("/two-factor/"),signal:"$sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var dl=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=ir({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=tr({...e?.backupCodeOptions},t.twoFactorTable),n=or({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ge.object({password:Ge.string().min(8)}),use:[b]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await ot(i,{password:s,userId:a.id}))throw new sr("BAD_REQUEST",{message:"Invalid password"});let c=N(16,F("a-z","0-9","-")),l=await ye({key:i.context.secret,data:c}),p=await rt(i.context.secret,e?.backupCodeOptions);if(e?.skipVerificationOnEnable){let f=await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),k=await i.context.internalAdapter.createSession(f.id,i.request);await w(i,{session:k,user:a})}await i.context.adapter.deleteMany({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}});let m=Bo(e?.issuer||"BetterAuth",a.email,Buffer.from(c),{digits:e?.totpOptions?.digits||6,period:new Do(e?.totpOptions?.period||30,"s")});return i.json({totpURI:m,backupCodes:p.backupCodes})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ge.object({password:Ge.string().min(8)}),use:[b]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await ot(i,{password:s,userId:a.id}))throw new sr("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:_(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[f,k]=c.split("!"),A=await ce(i.context.secret,`${s.user.id}!${k}`);if(f===A){let h=await ce(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.attributes);return}}J(i);let l=await ce(i.context.secret,s.session.id),p=i.context.createAuthCookie($e,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.attributes),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1,input:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as Mo,generateRegistrationOptions as $o,verifyAuthenticationResponse as Qo,verifyRegistrationResponse as Ho}from"@simplewebauthn/server";import{APIError as G}from"better-call";import{z as Y}from"zod";import{WebAuthnError as jo,startAuthentication as No,startRegistration as Fo}from"@simplewebauthn/browser";import{createFetch as Il}from"@better-fetch/fetch";import"nanostores";import"@better-fetch/fetch";import{atom as yl}from"nanostores";import"@better-fetch/fetch";import{atom as xo,onMount as Lo}from"nanostores";var nt=(e,t,r,o)=>{let n=xo({data:null,error:null,isPending:!0,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():Lo(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as Vo}from"nanostores";var qo=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await No(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch{return{data:null,error:{message:"auth cancelled",status:400,statusText:"BAD_REQUEST"}}}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Fo(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof jo?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),Wl=()=>{let e=Vo();return{id:"passkey",$InferServerPlugin:{},getActions:t=>qo(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:nt(e,"/passkey/list-user-passkeys",t,{method:"GET"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var sp=e=>{let t=ze.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[b],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(N(32,F("a-z","0-9")))),p;p=await $o({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let m=z();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,m,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:m,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:Y.object({email:Y.string().optional()}).optional()},async s=>{let d=await D(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await Mo({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},m=z();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,m,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:m,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:Y.object({response:Y.any(),name:Y.string().optional()}),use:[b]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:m,userData:f}=JSON.parse(p.value);if(f.id!==s.context.session.user.id)throw new G("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await Ho({response:c,expectedChallenge:m,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:A,registrationInfo:h}=k;if(!A||!h)return s.json(null,{status:400});let{credentialID:P,credentialPublicKey:pe,counter:M,credentialDeviceType:_e,credentialBackedUp:me}=h,ie=Buffer.from(pe).toString("base64"),Ye=z(),mr={name:s.body.name,userId:f.id,webauthnUserID:Ye,id:P,publicKey:ie,counter:M,deviceType:_e,transports:c.response.transports.join(","),backedUp:me,createdAt:new Date},fr=await s.context.adapter.create({model:"passkey",data:mr});return s.json(fr,{status:200})}catch(k){throw console.log(k),new G("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:Y.object({response:Y.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new G("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new G("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:m}=JSON.parse(p.value),f=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!f)throw new G("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await Qo({response:c,expectedChallenge:m,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:f.id,credentialPublicKey:new Uint8Array(Buffer.from(f.publicKey,"base64")),counter:f.counter,transports:f.transports?.split(",")}}),{verified:A}=k;if(!A)throw new G("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:f.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(f.userId,s.request);if(!h)throw new G("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});let P=await s.context.internalAdapter.findUserById(f.userId);if(!P)throw new G("INTERNAL_SERVER_ERROR",{message:"User not found"});return await w(s,{session:h,user:P}),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new G("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[b]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:Y.object({id:Y.string()}),use:[b]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as Ke}from"zod";import{APIError as Je}from"better-call";var ar=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:Ke.object({username:Ke.string(),password:Ke.string(),dontRememberMe:Ke.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:e.context.tables.user.tableName,where:[{field:"username",value:e.body.username}]});if(!t)throw await e.context.password.hash(e.body.password),e.context.logger.error("User not found",{username:ar}),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:e.context.tables.account.tableName,where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.providerId.fieldName||"providerId",value:"credential"}]});if(!r)throw new Je("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:ar}),new Je("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as Wo}from"better-call";var fp=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await Wo("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as ke}from"zod";import{APIError as dr}from"better-call";var kp=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:ke.object({email:ke.string().email(),callbackURL:ke.string().optional()})},async t=>{let{email:r}=t.body;if(e.disableSignUp&&!await t.context.internalAdapter.findUserByEmail(r))throw new dr("BAD_REQUEST",{message:"User not found"});let o=N(32,F("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new dr("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:ke.object({token:ke.string(),callbackURL:ke.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await w(t,{session:c,user:s?.user}),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as le}from"zod";import{APIError as X}from"better-call";function Go(e){return N(e,F("0-9"))}var _p=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:le.object({phoneNumber:le.string()})},async r=>{if(!e?.sendOTP)throw y.warn("sendOTP not implemented"),new X("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Go(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:C(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:le.object({phoneNumber:le.string(),code:le.string(),disableSession:le.boolean().optional(),updatePhoneNumber:le.boolean().optional()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new X("BAD_REQUEST",{message:"OTP expired"})):new X("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new X("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await D(r);if(!i)throw new X("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:e.signUpOnVerification.getTempEmail(r.body.phoneNumber),name:e.signUpOnVerification.getTempName?e.signUpOnVerification.getTempName(r.body.phoneNumber):r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new X("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new X("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new X("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new X("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await w(r,{session:i,user:n}),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as it}from"zod";var jp=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=De(t.context.baseURL)}=e||{},o=z(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await w(t,{session:a,user:i}),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAccount:u("/anonymous/link-account",{method:"POST",body:it.object({email:it.string().email().optional(),password:it.string().min(6)}),use:[b]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o,isAnonymous:!1})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await w(t,{session:d,user:i}),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",required:!1}}}}});import{z as g}from"zod";var K=_(async e=>{let t=await D(e);if(!t?.session)throw new E("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new E("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),$p=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/list-sessions"},handler:_(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:g.object({userId:g.string(),role:g.string()}),use:[K]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:g.object({email:g.string(),password:g.string(),name:g.string(),role:g.string(),data:g.optional(g.record(g.any()))}),use:[K]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new E("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new E("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[K],query:g.object({search:g.object({field:g.enum(["email","name"]),operator:g.enum(["contains","starts_with","ends_with"]).default("contains"),value:g.string()}).optional(),limit:g.string().or(g.number()).optional(),offset:g.string().or(g.number()).optional(),sortBy:g.string().optional(),sortDirection:g.enum(["asc","desc"]).optional(),filter:g.array(g.object({field:g.string(),value:g.string().or(g.number()).or(g.boolean()),operator:g.enum(["eq","ne","lt","lte","gt","gte"]),connector:g.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[K],body:g.object({userId:g.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:g.object({userId:g.string()}),use:[K]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:g.object({userId:g.string(),banReason:g.string().optional(),banExpiresIn:g.number().optional()}),use:[K]},async t=>{if(t.body.userId===t.context.session.user.id)throw new E("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?C(t.body.banExpiresIn,"sec"):e?.defaultBanExpiresIn?C(e.defaultBanExpiresIn,"sec"):void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:g.object({userId:g.string()}),use:[K]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new E("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?C(e.impersonationSessionDuration,"sec"):C(60*60,"sec")});if(!o)throw new E("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await w(t,{session:o,user:r},!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:g.object({sessionId:g.string()}),use:[K]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:g.object({userId:g.string()}),use:[K]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:g.object({userId:g.string()}),use:[K]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1,input:!1},banned:{type:"boolean",defaultValue:!1,required:!1,input:!1},banReason:{type:"string",required:!1,input:!1},banExpires:{type:"date",required:!1,input:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});import{z as ee}from"zod";import{APIError as Se}from"better-call";import{betterFetch as st}from"@better-fetch/fetch";import{parseJWT as Ko}from"oslo/jwt";async function Jo(e,t,r){if(t==="oidc"&&e.idToken){let n=Ko(e.idToken);if(n?.payload)return n.payload}return r?(await st(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var om=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:ee.object({currentURL:ee.string().optional()}).optional(),body:ee.object({providerId:ee.string(),callbackURL:ee.string().optional()})},async t=>{let{providerId:r}=t.body,o=e.config.find(ie=>ie.providerId===r);if(!o)throw new Se("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:m,prompt:f,accessType:k}=o,A=i,h=a;if(n){let ie=await st(n,{onError(Ye){y.error(Ye.error,{discoveryUrl:n})}});ie.data&&(A=ie.data.authorization_endpoint,h=ie.data.token_endpoint)}if(!A||!h)throw new Se("BAD_REQUEST",{message:"Invalid OAuth configuration."});let P=t.query?.currentURL?new URL(t.query?.currentURL):null,pe=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${P?.origin}${t.body.callbackURL||""}`,{state:M,codeVerifier:_e}=await ge(t),me=await I({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:A,state:M,codeVerifier:_e,scopes:c||[],disablePkce:!m,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&me.searchParams.set("response_type",p),f&&me.searchParams.set("prompt",f),k&&me.searchParams.set("access_type",k),t.json({url:me.toString(),redirect:!0})}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:ee.object({code:ee.string().optional(),error:ee.string().optional(),state:ee.string()})},async t=>{if(t.query.error||!t.query.code)throw t.redirect(`${t.context.baseURL}?error=${t.query.error||"oAuth_code_missing"}`);let r=e.config.find(h=>h.providerId===t.params.providerId);if(!r)throw new Se("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o,n=await xe(t),{callbackURL:i,codeVerifier:a,errorURL:s}=n,d=t.query.code,c=r.tokenUrl,l=r.userInfoUrl;if(r.discoveryUrl){let h=await st(r.discoveryUrl,{method:"GET"});h.data&&(c=h.data.token_endpoint,l=h.data.userinfo_endpoint)}try{if(!c)throw new Se("BAD_REQUEST",{message:"Invalid OAuth configuration."});o=await v({code:d,codeVerifier:a,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:c})}catch(h){throw t.context.logger.error(h),t.redirect(`${s}?error=oauth_code_verification_failed`)}if(!o)throw new Se("BAD_REQUEST",{message:"Invalid OAuth configuration."});let p=r.getUserInfo?await r.getUserInfo(o):await Jo(o,r.type||"oauth2",l),m=z(),f=p?je.safeParse({...p,id:m}):null;if(!f?.success)throw t.redirect(`${s}?error=oauth_user_info_invalid`);let k=await t.context.internalAdapter.findUserByEmail(f.data.email,{includeAccounts:!0}).catch(h=>{throw y.error(`Better auth was unable to query your database.
|
|
85
|
-
Error: `,h),t.redirect(`${s}?error=internal_server_error`)}),A=k?.user.id||m;if(k){let h=k.accounts.find(M=>M.providerId===r.providerId),P=t.context.options.account?.accountLinking?.trustedProviders,pe=P?P.includes(r.providerId):!0;if(!h&&(!f?.data.emailVerified||!pe)){let M;try{M=new URL(s),M.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${s}?error=account_not_linked`)}throw t.redirect(M.toString())}if(h)await t.context.internalAdapter.updateAccount(h.id,{accessToken:o.accessToken,idToken:o.idToken,refreshToken:o.refreshToken,expiresAt:o.accessTokenExpiresAt});else try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:f.data.id,id:`${r.providerId}:${f.data.id}`,userId:k.user.id,accessToken:o.accessToken,idToken:o.idToken,refreshToken:o.refreshToken,expiresAt:o.accessTokenExpiresAt})}catch(M){throw console.log(M),t.redirect(`${s}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(f.data,{id:`${r.providerId}:${f.data.id}`,providerId:r.providerId,accountId:f.data.id,accessToken:o.accessToken,idToken:o.idToken,refreshToken:o.refreshToken,expiresAt:o.accessTokenExpiresAt})}catch{let P=new URL(s);throw P.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",P.toString()),t.redirect(P.toString())}try{let h=await t.context.internalAdapter.createSession(A||m,t.request);if(!h)throw t.redirect(`${s}?error=unable_to_create_session`);await w(t,{session:h,user:f.data})}catch{throw t.redirect(`${s}?error=unable_to_create_session`)}throw t.redirect(i)})}});import{z as Pe}from"zod";var cr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},sm=Pe.object({id:Pe.string(),publicKey:Pe.string(),privateKey:Pe.string(),createdAt:Pe.date()});var at=e=>({getAllKeys:async()=>await e.findMany({model:"jwks"}),getLatestKey:async()=>(await e.findMany({model:"jwks",sortBy:{field:"createdAt",direction:"desc"},limit:1}))[0],createJwk:async t=>await e.create({model:"jwks",data:{...t,createdAt:new Date}})});import{exportJWK as ur,generateKeyPair as Zo,importJWK as Yo,SignJWT as Xo}from"jose";var fm=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await at(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[b]},async t=>{let r=at(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await Zo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await ur(c),m=await ur(l),f=JSON.stringify(m),k={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(await ye({key:t.context.options.secret,data:f})):f,createdAt:new Date};o=await r.createJwk(k)}let i=n?await be({key:t.context.options.secret,data:JSON.parse(o.privateKey)}):o.privateKey,a=await Yo(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new Xo({...s,...t.context.session.session.impersonatedBy?{impersonatedBy:t.context.session.session.impersonatedBy}:{}}).setProtectedHeader({alg:e?.jwks?.keyPairConfig?.alg??"EdDSA",kid:o.id}).setIssuedAt().setIssuer(e?.jwt?.issuer??t.context.options.baseURL).setAudience(e?.jwt?.audience??t.context.options.baseURL).setExpirationTime(e?.jwt?.expirationTime??"15m").setSubject(t.context.session.user.id).sign(a);return t.json({token:d})})},schema:cr});import{z as Ze}from"zod";var bm=e=>{let t={maximumSessions:5,...e},r=o=>o.includes("_multi-");return{id:"multi-session",endpoints:{listDeviceSessions:u("/multi-session/list-device-sessions",{method:"GET",requireHeaders:!0},async o=>{let n=o.headers?.get("cookie");if(!n)return o.json([]);let i=Object.fromEntries(Be(n)),a=(await Promise.all(Object.entries(i).filter(([c])=>r(c)).map(async([c])=>await o.getSignedCookie(c,o.context.secret)))).filter(c=>c!==void 0);if(!a.length)return o.json([]);let d=(await o.context.internalAdapter.findSessions(a)).filter(c=>c&&c.session.expiresAt>new Date).filter((c,l,p)=>l===p.findIndex(m=>m.user.id===c.user.id));return Object.entries(i).filter(([c])=>r(c)).forEach(([c,l])=>{d.some(p=>p.session.id===l)||o.setCookie(c,"",{...o.context.authCookies.sessionToken.options,maxAge:0})}),o.json(d)}),setActiveSession:u("/multi-session/set-active",{method:"POST",body:Ze.object({sessionId:Ze.string()}),requireHeaders:!0,use:[b]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new E("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);if(!s||s.session.expiresAt<new Date)throw o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),new E("UNAUTHORIZED",{message:"Invalid session id"});return await o.setSignedCookie(o.context.authCookies.sessionToken.name,n,o.context.secret,o.context.authCookies.sessionToken.options),o.json(s)}),revokeDeviceSession:u("/multi-session/revoke",{method:"POST",body:Ze.object({sessionId:Ze.string()}),requireHeaders:!0,use:[b]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new E("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);return o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),s?(await o.context.internalAdapter.deleteSession(n),o.json({success:!0})):o.json({success:!0})})},hooks:{after:[{matcher:()=>!0,handler:_(async o=>{if(!o.context.returned||!(o.context.returned instanceof Response))return;let n=o.context.returned.headers.get("set-cookie");if(!n)return;let i=lt(n),a=o.context.authCookies.sessionToken,s=i.get(a.name)?.value;if(!s)return;let d=Be(o.headers?.get("cookie")||""),c=s.split(".")[0],l=`${a.name}_multi-${c}`;if(i.get(l)||d.get(l)||Object.keys(Object.fromEntries(d)).filter(r).length+(n.includes("session_token")?1:0)>t.maximumSessions)return;await o.setSignedCookie(l,c,o.context.secret,a.options);let m=o.context.returned;return m.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:m}})},{matcher:o=>o.path==="/sign-out",handler:_(async o=>{let n=o.headers?.get("cookie");if(!n)return;let i=Object.fromEntries(Be(n));await Promise.all(Object.entries(i).map(async([s,d])=>{if(r(s)){o.setCookie(s,"",{maxAge:0});let c=s.split("_multi-")[1];await o.context.internalAdapter.deleteSession(c)}}));let a=o.context.returned;return a?.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:a}})}]}}};import{z as te}from"zod";var Tm=e=>{let t={expireIn:300,otpLength:6,...e};return{id:"email-otp",endpoints:{sendVerificationOTP:u("/email-otp/send-verification-otp",{method:"POST",body:te.object({email:te.string(),type:te.enum(["email-verification","sign-in"])})},async r=>{if(!e?.sendVerificationOTP)throw y.error("send email verification is not implemented"),new E("BAD_REQUEST",{message:"send email verification is not implemented"});let o=r.body.email,n=N(t.otpLength,F("0-9"));return await r.context.internalAdapter.createVerificationValue({value:n,identifier:`${r.body.type}-otp-${o}`,expiresAt:C(t.expireIn,"sec")}),await e.sendVerificationOTP({email:o,otp:n,type:r.body.type}),r.json({success:!0})}),verifyEmailOTP:u("/email-otp/verify-email",{method:"POST",body:te.object({email:te.string(),otp:te.string()})},async r=>{let o=r.body.email,n=await r.context.internalAdapter.findVerificationValue(`email-verification-otp-${o}`);if(!n||n.expiresAt<new Date)throw n&&await r.context.internalAdapter.deleteVerificationValue(n.id),new E("BAD_REQUEST",{message:"Invalid OTP"});let i=r.body.otp;if(n.value!==i)throw new E("BAD_REQUEST",{message:"Invalid OTP"});await r.context.internalAdapter.deleteVerificationValue(n.id);let a=await r.context.internalAdapter.findUserByEmail(o);if(!a)throw new E("BAD_REQUEST",{message:"User not found"});let s=await r.context.internalAdapter.updateUser(a.user.id,{email:o,emailVerified:!0});return r.json({user:s})}),signInEmailOTP:u("/sign-in/email-otp",{method:"POST",body:te.object({email:te.string(),otp:te.string()})},async r=>{let o=r.body.email,n=await r.context.internalAdapter.findVerificationValue(`sign-in-otp-${o}`);if(!n||n.expiresAt<new Date)throw n&&await r.context.internalAdapter.deleteVerificationValue(n.id),new E("BAD_REQUEST",{message:"Invalid OTP"});let i=r.body.otp;if(n.value!==i)throw new E("BAD_REQUEST",{message:"Invalid OTP"});await r.context.internalAdapter.deleteVerificationValue(n.id);let a=await r.context.internalAdapter.findUserByEmail(o);if(!a){if(t.disableSignUp)throw new E("BAD_REQUEST",{message:"User not found"});let d=await r.context.internalAdapter.createUser({email:o,emailVerified:!0,name:o}),c=await r.context.internalAdapter.createSession(d.id,r.request);return await w(r,{session:c,user:d}),r.json({user:d,session:c})}let s=await r.context.internalAdapter.createSession(a.user.id,r.request);return await w(r,{session:s,user:a.user}),r.json({session:s,user:a})})},hooks:{after:[{matcher(r){return!!(r.path?.startsWith("/sign-up")&&t.sendVerificationOnSignUp)},async handler(r){let o=r.context.returned;if(o?.status!==200)return;let n=await o.clone().json();if(n.user.email&&n.user.emailVerified===!1){let i=N(t.otpLength,F("0-9"));await r.context.internalAdapter.createVerificationValue({value:i,identifier:`email-verification-otp-${n.user.email}`,expiresAt:C(t.expireIn,"sec")}),await e.sendVerificationOTP({email:n.user.email,otp:i,type:"email-verification"})}}}]}}};import{z as pr}from"zod";import{betterFetch as en}from"@better-fetch/fetch";function lr(e){return e==="true"||e===!0}var xm=e=>({id:"one-tap",endpoints:{oneTapCallback:u("/one-tap/callback",{method:"POST",body:pr.object({idToken:pr.string()})},async t=>{let{idToken:r}=t.body,{data:o,error:n}=await en("https://oauth2.googleapis.com/tokeninfo?id_token="+r);if(n)return t.json({error:"Invalid token"});let i=await t.context.internalAdapter.findUserByEmail(o.email);if(!i){if(e?.disableSignup)throw new E("BAD_GATEWAY",{message:"User not found"});let s=await t.context.internalAdapter.createOAuthUser({email:o.email,emailVerified:lr(o.email_verified),name:o.name,image:o.picture},{providerId:"google",accountId:o.sub});if(!s)throw new E("INTERNAL_SERVER_ERROR",{message:"Could not create user"});let d=await t.context.internalAdapter.createSession(s?.user.id,t.request);return await w(t,{user:s.user,session:d}),t.json({session:d,user:s})}let a=await t.context.internalAdapter.createSession(i.user.id,t.request);return await w(t,{user:i.user,session:a}),t.json({session:a,user:i})})}});export{fe as HIDE_METADATA,$p as admin,K as adminMiddleware,jp as anonymous,fp as bearer,u as createAuthEndpoint,_ as createAuthMiddleware,Tm as emailOTP,om as genericOAuth,qo as getPasskeyActions,fm as jwt,kp as magicLink,bm as multiSession,xm as oneTap,ct as optionsMiddleware,Dc as organization,sp as passkey,Wl as passkeyClient,_p as phoneNumber,dl as twoFactor,Hu as twoFactorClient,ar as username};
|
|
83
|
+
</html>`,lo=u("/error",{method:"GET",metadata:we},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(uo(t),{headers:{"Content-Type":"text/html"}})});var po=u("/ok",{method:"GET",metadata:we},async e=>e.json({ok:!0}));import{z as Ra}from"zod";import{APIError as _a}from"better-call";import{z as Ue}from"zod";import{APIError as _t}from"better-call";var mo=u("/list-accounts",{method:"GET",use:[A]},async e=>{let t=e.context.session,r=await e.context.internalAdapter.findAccounts(t.user.id);return e.json(r)}),fo=u("/link-social",{method:"POST",requireHeaders:!0,query:Ue.object({currentURL:Ue.string().optional()}).optional(),body:Ue.object({callbackURL:Ue.string().optional(),provider:Ue.enum(De)}),use:[A]},async e=>{let t=e.context.session;if((await e.context.internalAdapter.findAccounts(t.user.id)).find(s=>s.providerId===e.body.provider))throw new _t("BAD_REQUEST",{message:"Social Account is already linked."});let n=e.context.socialProviders.find(s=>s.id===e.body.provider);if(!n)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new _t("NOT_FOUND",{message:"Provider not found"});let i=await ye(e,{userId:t.user.id,email:t.user.email}),a=await n.createAuthorizationURL({state:i.state,codeVerifier:i.codeVerifier,redirectURI:`${e.context.baseURL}/callback/${n.id}`});return e.json({url:a.toString(),redirect:!0})});var Ct=(e,t)=>{let r={};for(let[o,n]of Object.entries(e))r[o]=i=>n({...i,context:{...t,...i.context}}),r[o].path=n.path,r[o].method=n.method,r[o].options=n.options,r[o].headers=n.headers;return r};var Ae=class extends Error{path;constructor(t,r){super(t),this.path=r}},Ve=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new qe(t)}},qe=class e{statements;constructor(t){this.statements=t}authorize(t,r){for(let[o,n]of Object.entries(t)){let i=this.statements[o];if(!i)return{success:!1,error:`You are not allowed to access resource: ${o}`};let a=r==="OR"?n.some(s=>i.includes(s)):n.every(s=>i.includes(s));return a?{success:a}:{success:!1,error:`unauthorized to access resource "${o}"`}}return{success:!1,error:"Not authorized"}}static fromString(t){let r=JSON.parse(t);if(typeof r!="object")throw new Ae("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new Ae("invalid resource identifier",o);if(!Array.isArray(n))throw new Ae("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new Ae("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var go=e=>new Ve(e),ho={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},tt=go(ho),wo=tt.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),yo=tt.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),bo=tt.newRole({organization:[],member:[],invitation:[]}),zt={admin:wo,owner:yo,member:bo};var P=(e,t)=>{let r=e.adapter;return{findOrganizationBySlug:async o=>await r.findOne({model:"organization",where:[{field:"slug",value:o}]}),createOrganization:async o=>{let n=await r.create({model:"organization",data:{...o.organization,metadata:o.organization.metadata?JSON.stringify(o.organization.metadata):void 0}}),i=await r.create({model:"member",data:{id:z(),organizationId:n.id,userId:o.user.id,createdAt:new Date,email:o.user.email,role:t?.creatorRole||"owner"}});return{...n,metadata:n.metadata?JSON.parse(n.metadata):void 0,members:[{...i,user:{id:o.user.id,name:o.user.name,email:o.user.email,image:o.user.image}}]}},findMemberByEmail:async o=>{let n=await r.findOne({model:"member",where:[{field:"email",value:o.email},{field:"organizationId",value:o.organizationId}]});if(!n)return null;let i=await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:n.userId}]});return i?{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}:null},findMemberByOrgId:async o=>{let[n,i]=await Promise.all([await r.findOne({model:"member",where:[{field:"userId",value:o.userId},{field:"organizationId",value:o.organizationId}]}),await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:o.userId}]})]);return!i||!n?null:{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}},findMemberById:async o=>{let n=await r.findOne({model:"member",where:[{field:"id",value:o}]});if(!n)return null;let i=await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:n.userId}]});return i?{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}:null},createMember:async o=>await r.create({model:"member",data:o}),updateMember:async(o,n)=>await r.update({model:"member",where:[{field:"id",value:o}],update:{role:n}}),deleteMember:async o=>await r.delete({model:"member",where:[{field:"id",value:o}]}),updateOrganization:async(o,n)=>await r.update({model:"organization",where:[{field:"id",value:o}],update:n}),deleteOrganization:async o=>(await r.delete({model:"member",where:[{field:"organizationId",value:o}]}),await r.delete({model:"invitation",where:[{field:"organizationId",value:o}]}),await r.delete({model:"organization",where:[{field:"id",value:o}]}),o),setActiveOrganization:async(o,n)=>await r.update({model:e.tables.session.tableName,where:[{field:"id",value:o}],update:{activeOrganizationId:n}}),findOrganizationById:async o=>await r.findOne({model:"organization",where:[{field:"id",value:o}]}),findFullOrganization:async(o,n)=>{let[i,a,s]=await Promise.all([r.findOne({model:"organization",where:[{field:"id",value:o}]}),r.findMany({model:"invitation",where:[{field:"organizationId",value:o}]}),r.findMany({model:"member",where:[{field:"organizationId",value:o}]})]);if(!i)return null;let d=s.map(m=>m.userId),c=await r.findMany({model:e.tables.user.tableName,where:[{field:"id",value:d,operator:"in"}]}),l=new Map(c.map(m=>[m.id,m])),p=s.map(m=>{let f=l.get(m.userId);if(!f)throw new $("Unexpected error: User not found for member");return{...m,user:{id:f.id,name:f.name,email:f.email,image:f.image}}});return{...i,invitations:a,members:p}},listOrganizations:async o=>{let n=await r.findMany({model:"member",where:[{field:"userId",value:o}]});if(!n||n.length===0)return[];let i=n.map(s=>s.organizationId);return await r.findMany({model:"organization",where:[{field:"id",value:i,operator:"in"}]})},createInvitation:async({invitation:o,user:n})=>{let a=C(t?.invitationExpiresIn||1728e5);return await r.create({model:"invitation",data:{id:z(),email:o.email,role:o.role,organizationId:o.organizationId,status:"pending",expiresAt:a,inviterId:n.id}})},findInvitationById:async o=>await r.findOne({model:"invitation",where:[{field:"id",value:o}]}),findPendingInvitation:async o=>(await r.findMany({model:"invitation",where:[{field:"email",value:o.email},{field:"organizationId",value:o.organizationId},{field:"status",value:"pending"}]})).filter(i=>new Date(i.expiresAt)>new Date),updateInvitation:async o=>await r.update({model:"invitation",where:[{field:"id",value:o.invitationId}],update:{status:o.status}})}};import"better-call";import{APIError as zd,createRouter as Bd,statusCode as Ld}from"better-call";import{APIError as Ao}from"better-call";var ko=T(async e=>{if(e.request?.method!=="POST")return;let{body:t,query:r,context:o}=e,n=e.headers?.get("origin")||e.headers?.get("referer")||"",i=t?.callbackURL||r?.callbackURL,a=t?.redirectTo,s=r?.currentURL,d=o.trustedOrigins,c=e.headers?.has("cookie"),l=(m,f)=>f.includes("*")?new RegExp("^"+f.replace(/\*/g,"[^/]+").replace(/\./g,"\\.")+"$").test(m):m.startsWith(f),p=(m,f)=>{if(!m)return;if(!d.some(b=>l(m,b)||m?.startsWith("/")&&f!=="origin"&&!m.includes(":")))throw y.error(`Invalid ${f}: ${m}`),y.info(`If it's a valid URL, please add ${m} to trustedOrigins in your auth config
|
|
84
|
+
`,`Current list of trustedOrigins: ${d}`),new Ao("FORBIDDEN",{message:`Invalid ${f}`})};c&&!e.context.options.advanced?.disableCSRFCheck&&p(n,"origin"),i&&p(i,"callbackURL"),a&&p(a,"redirectURL"),s&&p(s,"currentURL")});import{APIError as v}from"better-call";var B=T(async e=>({})),x=T({use:[A]},async e=>({session:e.context.session}));import{z as q}from"zod";import{z as E}from"zod";var Me=E.enum(["admin","member","owner"]),Oo=E.enum(["pending","accepted","rejected","canceled"]).default("pending"),Xd=E.object({id:E.string(),name:E.string(),slug:E.string(),logo:E.string().optional(),metadata:E.record(E.string()).or(E.string().transform(e=>JSON.parse(e))).optional(),createdAt:E.date()}),ec=E.object({id:E.string(),email:E.string(),organizationId:E.string(),userId:E.string(),role:Me,createdAt:E.date()}),tc=E.object({id:E.string(),organizationId:E.string(),email:E.string(),role:Me,status:Oo,inviterId:E.string(),expiresAt:E.date()});import{APIError as I}from"better-call";var Bt=u("/organization/invite-member",{method:"POST",use:[B,x],body:q.object({email:q.string(),role:Me,organizationId:q.string().optional(),resend:q.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw y.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new I("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new I("BAD_REQUEST",{message:"Organization not found"});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new I("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new I("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new I("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new I("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new I("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new I("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),Lt=u("/organization/accept-invitation",{method:"POST",body:q.object({invitationId:q.string()}),use:[B,x]},async e=>{let t=e.context.session,r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new I("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:z(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),xt=u("/organization/reject-invitation",{method:"POST",body:q.object({invitationId:q.string()}),use:[B,x]},async e=>{let t=e.context.session,r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new I("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),Dt=u("/organization/cancel-invitation",{method:"POST",body:q.object({invitationId:q.string()}),use:[B,x]},async e=>{let t=e.context.session,r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new I("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new I("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new I("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),jt=u("/organization/get-invitation",{method:"GET",use:[B],requireHeaders:!0,query:q.object({id:q.string()})},async e=>{let t=await L(e);if(!t)throw new I("UNAUTHORIZED",{message:"Not authenticated"});let r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new I("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new I("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new I("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as ue}from"zod";import{APIError as Ie}from"better-call";var Nt=u("/organization/remove-member",{method:"POST",body:ue.object({memberIdOrEmail:ue.string(),organizationId:ue.string().optional()}),use:[B,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ie("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ie("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ie("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ie("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Ie("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Ft=u("/organization/update-member-role",{method:"POST",body:ue.object({role:ue.enum(["admin","member","owner"]),memberId:ue.string(),organizationId:ue.string().optional()}),use:[B,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as S}from"zod";import{APIError as le}from"better-call";var Vt=u("/organization/create",{method:"POST",body:S.object({name:S.string(),slug:S.string(),userId:S.string().optional(),logo:S.string().optional(),metadata:S.record(S.string()).optional()}),use:[B,x]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new le("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=P(e.context,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new le("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new le("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:z(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),qt=u("/organization/update",{method:"POST",body:S.object({data:S.object({name:S.string().optional(),slug:S.string().optional()}).partial(),orgId:S.string().optional()}),requireHeaders:!0,use:[B]},async e=>{let t=await e.context.getSession(e);if(!t)throw new le("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["update"]}).error)return e.json(null,{body:{message:"You are not allowed to update this organization"},status:403});let s=await o.updateOrganization(r,e.body.data);return e.json(s)}),Mt=u("/organization/delete",{method:"POST",body:S.object({orgId:S.string()}),requireHeaders:!0,use:[B]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["delete"]}).error)throw new le("FORBIDDEN",{message:"You are not allowed to delete this organization"});return r===t.session.activeOrganizationId&&await o.setActiveOrganization(t.session.id,null),await o.deleteOrganization(r),e.json(r)}),$t=u("/organization/get-full",{method:"GET",query:S.optional(S.object({orgId:S.string().optional()})),requireHeaders:!0,use:[B,x]},async e=>{let t=e.context.session,r=e.query?.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:200});let n=await P(e.context,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new le("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Qt=u("/organization/activate",{method:"POST",body:S.object({orgId:S.string().nullable().optional()}),use:[x,B]},async e=>{let t=P(e.context,e.context.orgOptions),r=e.context.session,o=e.body.orgId;if(o===null)return r.session.activeOrganizationId&&await t.setActiveOrganization(r.session.id,null),e.json(null);if(!o){let a=r.session.activeOrganizationId;if(!a)return e.json(null);o=a}if(!await t.findMemberByOrgId({userId:r.user.id,organizationId:o}))throw await t.setActiveOrganization(r.session.id,null),new le("FORBIDDEN",{message:"You are not a member of this organization"});await t.setActiveOrganization(r.session.id,o);let i=await t.findFullOrganization(o,e.context.db||void 0);return e.json(i)}),Ht=u("/organization/list",{method:"GET",use:[B,x]},async e=>{let r=await P(e.context,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var Dc=e=>{let t={createOrganization:Vt,updateOrganization:qt,deleteOrganization:Mt,setActiveOrganization:Qt,getFullOrganization:$t,listOrganization:Ht,createInvitation:Bt,cancelInvitation:Dt,acceptInvitation:Lt,getInvitation:jt,rejectInvitation:xt,removeMember:Nt,updateMemberRole:Ft},r={...zt,...e?.roles};return{id:"organization",endpoints:{...Ct(t,{orgOptions:e||{},roles:r,getSession:async n=>await L(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new Wt("BAD_REQUEST",{message:"No active organization"});let a=await P(n.context).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Wt("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import Gt from"uncrypto";function Ro(e){return e.toString(2).padStart(8,"0")}function vo(e){return[...e].map(t=>Ro(t)).join("")}function Kt(e){return parseInt(vo(e),2)}function Eo(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));Gt.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=Kt(o);for(;n>=e;)Gt.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Kt(o);return n}function N(e,t){let r="";for(let o=0;o<e;o++)r+=t[Eo(t.length)];return r}function F(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}import{z as Ge}from"zod";import{xchacha20poly1305 as Zt}from"@noble/ciphers/chacha";import{bytesToHex as Uo,hexToBytes as Io,utf8ToBytes as To}from"@noble/ciphers/utils";import{managedNonce as Yt}from"@noble/ciphers/webcrypto";import{sha256 as Xt}from"oslo/crypto";import Jt from"uncrypto";import{decodeHex as Hc,encodeHex as Wc}from"oslo/encoding";import{scryptAsync as Jc}from"@noble/hashes/scrypt";import{getRandomValues as Yc}from"uncrypto";async function pe(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await Jt.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),i=await Jt.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(i)))}var ie=async({key:e,data:t})=>{let r=await Xt(new TextEncoder().encode(e)),o=To(t),n=Yt(Zt)(new Uint8Array(r));return Uo(n.encrypt(o))},se=async({key:e,data:t})=>{let r=await Xt(new TextEncoder().encode(e)),o=Io(t),n=Yt(Zt)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};import{z as Y}from"zod";import{APIError as ae}from"better-call";var $e="two_factor";var Qe="trust_device";import{z as er}from"zod";var me=T({body:er.object({trustDevice:er.boolean().optional()})},async e=>{let t=await L(e);if(!t){let r=e.context.createAuthCookie($e),o=await e.getSignedCookie(r.name,e.context.secret);if(!o)throw new ae("UNAUTHORIZED",{message:"invalid two factor cookie"});let[n,i]=o.split("!");if(!n||!i)throw new ae("UNAUTHORIZED",{message:"invalid two factor cookie"});let a=await e.context.adapter.findMany({model:e.context.tables.session.tableName,where:[{field:"userId",value:n}]});if(!a.length)throw new ae("UNAUTHORIZED",{message:"invalid session"});let s=a.filter(d=>d.expiresAt>new Date);if(!s)throw new ae("UNAUTHORIZED",{message:"invalid session"});for(let d of s){let c=await pe(e.context.secret,d.id),l=await e.context.adapter.findOne({model:e.context.tables.user.tableName,where:[{field:"id",value:d.userId}]});if(!l)throw new ae("UNAUTHORIZED",{message:"invalid session"});if(c===i)return{valid:async()=>{if(await w(e,{session:d,user:l},!1),e.body.trustDevice){let p=e.context.createAuthCookie(Qe,{maxAge:2592e3}),m=await pe(e.context.secret,`${l.id}!${d.id}`);await e.setSignedCookie(p.name,`${m}!${d.id}`,e.context.secret,p.attributes)}return e.json({session:d,user:l})},invalid:async()=>{throw new ae("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:d.id,userId:d.userId,expiresAt:d.expiresAt,user:l}}}throw new ae("UNAUTHORIZED",{message:"invalid two factor cookie"})}return{valid:async()=>e.json({session:t,user:t.user}),invalid:async()=>{throw new ae("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:t}});import{APIError as Se}from"better-call";function So(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>N(e?.length??10,F("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function rt(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():So(),n=await ie({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Po(e,t){let r=await tr(e.backupCodes,t);return r?r.includes(e.code):!1}async function tr(e,t){let r=Buffer.from(await se({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Y.array(Y.string()).safeParse(o);return n.success?n.data:null}var rr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:Y.object({code:Y.string(),disableSession:Y.boolean().optional()}),use:[me]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Po({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Se("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await w(r,{session:r.context.session,user:o}),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",body:Y.object({password:Y.string()}),use:[A]},async r=>{let o=r.context.session.user;if(!o.twoFactorEnabled)throw new Se("BAD_REQUEST",{message:"Two factor isn't enabled"});await r.context.password.checkPassword(o.id,r);let n=await rt(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",body:Y.object({password:Y.string()}),use:[A]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});await r.context.password.checkPassword(o.id,r);let i=tr(n.backupCodes,r.context.secret);if(!i)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as He}from"better-call";import{TOTPController as _o}from"oslo/otp";import{z as or}from"zod";import{TimeSpan as Co}from"oslo";var nr=(e,t)=>{let r={...e,period:new Co(e?.period||3,"m")},o=new _o({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[me]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new He("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"OTP isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:or.object({code:or.string()}),use:[me]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new He("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"OTP isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as ke}from"better-call";import{TimeSpan as zo}from"oslo";import{TOTPController as ir,createTOTPKeyURI as Bo}from"oslo/otp";import{z as We}from"zod";var sr=(e,t)=>{let r={...e,digits:6,period:new zo(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[A]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new ke("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new ke("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new ir(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"POST",use:[A],body:We.object({password:We.string()})},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new ke("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new ke("BAD_REQUEST",{message:"totp isn't enabled"});return await a.context.password.checkPassword(s.id,a),{totpURI:Bo(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:We.object({code:We.string()}),use:[me]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new ke("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new ke("BAD_REQUEST",{message:"totp isn't enabled"});let c=new ir(r),l=await se({key:a.context.secret,data:d.secret}),p=Buffer.from(l);if(!await c.verify(a.body.code,p))return a.context.invalid();if(!s.twoFactorEnabled){let f=await a.context.internalAdapter.updateUser(s.id,{twoFactorEnabled:!0}),k=await a.context.internalAdapter.createSession(s.id,a.request);await w(a,{session:k,user:f})}return a.context.valid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};import{APIError as Hu}from"better-call";async function ot(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as ar}from"better-call";import{createTOTPKeyURI as Lo}from"oslo/otp";import{TimeSpan as xo}from"oslo";var Gu=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t.startsWith("/two-factor/"),signal:"$sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var ul=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=sr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=rr({...e?.backupCodeOptions},t.twoFactorTable),n=nr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ge.object({password:Ge.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await ot(i,{password:s,userId:a.id}))throw new ar("BAD_REQUEST",{message:"Invalid password"});let c=N(16,F("a-z","0-9","-")),l=await ie({key:i.context.secret,data:c}),p=await rt(i.context.secret,e?.backupCodeOptions);if(e?.skipVerificationOnEnable){let f=await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),k=await i.context.internalAdapter.createSession(f.id,i.request);await w(i,{session:k,user:a})}await i.context.adapter.deleteMany({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}});let m=Lo(e?.issuer||"BetterAuth",a.email,Buffer.from(c),{digits:e?.totpOptions?.digits||6,period:new xo(e?.totpOptions?.period||30,"s")});return i.json({totpURI:m,backupCodes:p.backupCodes})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ge.object({password:Ge.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await ot(i,{password:s,userId:a.id}))throw new ar("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:T(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[f,k]=c.split("!"),b=await pe(i.context.secret,`${s.user.id}!${k}`);if(f===b){let h=await pe(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.attributes);return}}Z(i);let l=await pe(i.context.secret,s.session.id),p=i.context.createAuthCookie($e,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.attributes),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1,input:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as $o,generateRegistrationOptions as Qo,verifyAuthenticationResponse as Ho,verifyRegistrationResponse as Wo}from"@simplewebauthn/server";import{APIError as K}from"better-call";import{z as X}from"zod";import{WebAuthnError as No,startAuthentication as Fo,startRegistration as Vo}from"@simplewebauthn/browser";import{createFetch as Tl}from"@better-fetch/fetch";import"nanostores";import"@better-fetch/fetch";import{atom as Al}from"nanostores";import"@better-fetch/fetch";import{atom as Do,onMount as jo}from"nanostores";var nt=(e,t,r,o)=>{let n=Do({data:null,error:null,isPending:!0,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():jo(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as qo}from"nanostores";var Mo=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await Fo(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch{return{data:null,error:{message:"auth cancelled",status:400,statusText:"BAD_REQUEST"}}}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Vo(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof No?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),Kl=()=>{let e=qo();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Mo(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:nt(e,"/passkey/list-user-passkeys",t,{method:"GET"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var dp=e=>{let t=Q.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[A],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(N(32,F("a-z","0-9")))),p;p=await Qo({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let m=z();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,m,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:m,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:X.object({email:X.string().optional()}).optional()},async s=>{let d=await L(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await $o({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},m=z();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,m,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:m,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:X.object({response:X.any(),name:X.string().optional()}),use:[A]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new K("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:m,userData:f}=JSON.parse(p.value);if(f.id!==s.context.session.user.id)throw new K("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await Wo({response:c,expectedChallenge:m,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:b,registrationInfo:h}=k;if(!b||!h)return s.json(null,{status:400});let{credentialID:_,credentialPublicKey:ge,counter:M,credentialDeviceType:Ce,credentialBackedUp:he}=h,de=Buffer.from(ge).toString("base64"),Ye=z(),fr={name:s.body.name,userId:f.id,webauthnUserID:Ye,id:_,publicKey:de,counter:M,deviceType:Ce,transports:c.response.transports.join(","),backedUp:he,createdAt:new Date},gr=await s.context.adapter.create({model:"passkey",data:fr});return s.json(gr,{status:200})}catch(k){throw console.log(k),new K("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:X.object({response:X.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new K("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new K("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new K("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:m}=JSON.parse(p.value),f=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!f)throw new K("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await Ho({response:c,expectedChallenge:m,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:f.id,credentialPublicKey:new Uint8Array(Buffer.from(f.publicKey,"base64")),counter:f.counter,transports:f.transports?.split(",")}}),{verified:b}=k;if(!b)throw new K("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:f.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(f.userId,s.request);if(!h)throw new K("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});let _=await s.context.internalAdapter.findUserById(f.userId);if(!_)throw new K("INTERNAL_SERVER_ERROR",{message:"User not found"});return await w(s,{session:h,user:_}),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new K("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[A]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:X.object({id:X.string()}),use:[A]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as Ke}from"zod";import{APIError as Je}from"better-call";var dr=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:Ke.object({username:Ke.string(),password:Ke.string(),dontRememberMe:Ke.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:e.context.tables.user.tableName,where:[{field:"username",value:e.body.username}]});if(!t)throw await e.context.password.hash(e.body.password),e.context.logger.error("User not found",{username:dr}),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:e.context.tables.account.tableName,where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.providerId.fieldName||"providerId",value:"credential"}]});if(!r)throw new Je("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:dr}),new Je("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as Go}from"better-call";var hp=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await Go("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as Oe}from"zod";import{APIError as cr}from"better-call";var Rp=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Oe.object({email:Oe.string().email(),callbackURL:Oe.string().optional()})},async t=>{let{email:r}=t.body;if(e.disableSignUp&&!await t.context.internalAdapter.findUserByEmail(r))throw new cr("BAD_REQUEST",{message:"User not found"});let o=N(32,F("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new cr("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:Oe.object({token:Oe.string(),callbackURL:Oe.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await w(t,{session:c,user:s?.user}),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as fe}from"zod";import{APIError as ee}from"better-call";function Ko(e){return N(e,F("0-9"))}var zp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:fe.object({phoneNumber:fe.string()})},async r=>{if(!e?.sendOTP)throw y.warn("sendOTP not implemented"),new ee("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Ko(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:C(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:fe.object({phoneNumber:fe.string(),code:fe.string(),disableSession:fe.boolean().optional(),updatePhoneNumber:fe.boolean().optional()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new ee("BAD_REQUEST",{message:"OTP expired"})):new ee("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ee("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await L(r);if(!i)throw new ee("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:e.signUpOnVerification.getTempEmail(r.body.phoneNumber),name:e.signUpOnVerification.getTempName?e.signUpOnVerification.getTempName(r.body.phoneNumber):r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ee("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ee("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new ee("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new ee("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await w(r,{session:i,user:n}),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as it}from"zod";var Fp=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=Le(t.context.baseURL)}=e||{},o=z(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await w(t,{session:a,user:i}),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAccount:u("/anonymous/link-account",{method:"POST",body:it.object({email:it.string().email().optional(),password:it.string().min(6)}),use:[A]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o,isAnonymous:!1})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await w(t,{session:d,user:i}),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",required:!1}}}}});import{z as g}from"zod";var J=T(async e=>{let t=await L(e);if(!t?.session)throw new v("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new v("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),Hp=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/list-sessions"},handler:T(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:g.object({userId:g.string(),role:g.string()}),use:[J]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:g.object({email:g.string(),password:g.string(),name:g.string(),role:g.string(),data:g.optional(g.record(g.any()))}),use:[J]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new v("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new v("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[J],query:g.object({search:g.object({field:g.enum(["email","name"]),operator:g.enum(["contains","starts_with","ends_with"]).default("contains"),value:g.string()}).optional(),limit:g.string().or(g.number()).optional(),offset:g.string().or(g.number()).optional(),sortBy:g.string().optional(),sortDirection:g.enum(["asc","desc"]).optional(),filter:g.array(g.object({field:g.string(),value:g.string().or(g.number()).or(g.boolean()),operator:g.enum(["eq","ne","lt","lte","gt","gte"]),connector:g.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[J],body:g.object({userId:g.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:g.object({userId:g.string()}),use:[J]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:g.object({userId:g.string(),banReason:g.string().optional(),banExpiresIn:g.number().optional()}),use:[J]},async t=>{if(t.body.userId===t.context.session.user.id)throw new v("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?C(t.body.banExpiresIn,"sec"):e?.defaultBanExpiresIn?C(e.defaultBanExpiresIn,"sec"):void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:g.object({userId:g.string()}),use:[J]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new v("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?C(e.impersonationSessionDuration,"sec"):C(60*60,"sec")});if(!o)throw new v("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await w(t,{session:o,user:r},!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:g.object({sessionId:g.string()}),use:[J]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:g.object({userId:g.string()}),use:[J]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:g.object({userId:g.string()}),use:[J]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1,input:!1},banned:{type:"boolean",defaultValue:!1,required:!1,input:!1},banReason:{type:"string",required:!1,input:!1},banExpires:{type:"date",required:!1,input:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});import{z as te}from"zod";import{APIError as Pe}from"better-call";import{betterFetch as st}from"@better-fetch/fetch";import{parseJWT as Jo}from"oslo/jwt";async function Zo(e,t,r){if(t==="oidc"&&e.idToken){let n=Jo(e.idToken);if(n?.payload)return n.payload}return r?(await st(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var im=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:te.object({currentURL:te.string().optional()}).optional(),body:te.object({providerId:te.string(),callbackURL:te.string().optional()})},async t=>{let{providerId:r}=t.body,o=e.config.find(de=>de.providerId===r);if(!o)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:m,prompt:f,accessType:k}=o,b=i,h=a;if(n){let de=await st(n,{onError(Ye){y.error(Ye.error,{discoveryUrl:n})}});de.data&&(b=de.data.authorization_endpoint,h=de.data.token_endpoint)}if(!b||!h)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let _=t.query?.currentURL?new URL(t.query?.currentURL):null,ge=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${_?.origin}${t.body.callbackURL||""}`,{state:M,codeVerifier:Ce}=await ye(t),he=await U({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:b,state:M,codeVerifier:Ce,scopes:c||[],disablePkce:!m,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&he.searchParams.set("response_type",p),f&&he.searchParams.set("prompt",f),k&&he.searchParams.set("access_type",k),t.json({url:he.toString(),redirect:!0})}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:te.object({code:te.string().optional(),error:te.string().optional(),state:te.string()})},async t=>{if(t.query.error||!t.query.code)throw t.redirect(`${t.context.baseURL}?error=${t.query.error||"oAuth_code_missing"}`);let r=e.config.find(h=>h.providerId===t.params.providerId);if(!r)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o,n=await xe(t),{callbackURL:i,codeVerifier:a,errorURL:s}=n,d=t.query.code,c=r.tokenUrl,l=r.userInfoUrl;if(r.discoveryUrl){let h=await st(r.discoveryUrl,{method:"GET"});h.data&&(c=h.data.token_endpoint,l=h.data.userinfo_endpoint)}try{if(!c)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});o=await R({code:d,codeVerifier:a,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:c})}catch(h){throw t.context.logger.error(h),t.redirect(`${s}?error=oauth_code_verification_failed`)}if(!o)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let p=r.getUserInfo?await r.getUserInfo(o):await Zo(o,r.type||"oauth2",l),m=z(),f=p?je.safeParse({...p,id:m}):null;if(!f?.success)throw t.redirect(`${s}?error=oauth_user_info_invalid`);let k=await t.context.internalAdapter.findUserByEmail(f.data.email,{includeAccounts:!0}).catch(h=>{throw y.error(`Better auth was unable to query your database.
|
|
85
|
+
Error: `,h),t.redirect(`${s}?error=internal_server_error`)}),b=k?.user.id||m;if(k){let h=k.accounts.find(M=>M.providerId===r.providerId),_=t.context.options.account?.accountLinking?.trustedProviders,ge=_?_.includes(r.providerId):!0;if(!h&&(!f?.data.emailVerified||!ge)){let M;try{M=new URL(s),M.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${s}?error=account_not_linked`)}throw t.redirect(M.toString())}if(h)await t.context.internalAdapter.updateAccount(h.id,{accessToken:o.accessToken,idToken:o.idToken,refreshToken:o.refreshToken,expiresAt:o.accessTokenExpiresAt});else try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:f.data.id,id:`${r.providerId}:${f.data.id}`,userId:k.user.id,accessToken:o.accessToken,idToken:o.idToken,refreshToken:o.refreshToken,expiresAt:o.accessTokenExpiresAt})}catch(M){throw console.log(M),t.redirect(`${s}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(f.data,{id:`${r.providerId}:${f.data.id}`,providerId:r.providerId,accountId:f.data.id,accessToken:o.accessToken,idToken:o.idToken,refreshToken:o.refreshToken,expiresAt:o.accessTokenExpiresAt})}catch{let _=new URL(s);throw _.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",_.toString()),t.redirect(_.toString())}try{let h=await t.context.internalAdapter.createSession(b||m,t.request);if(!h)throw t.redirect(`${s}?error=unable_to_create_session`);await w(t,{session:h,user:f.data})}catch{throw t.redirect(`${s}?error=unable_to_create_session`)}throw t.redirect(i)})}});import{z as _e}from"zod";var ur={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},dm=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var at=e=>({getAllKeys:async()=>await e.findMany({model:"jwks"}),getLatestKey:async()=>(await e.findMany({model:"jwks",sortBy:{field:"createdAt",direction:"desc"},limit:1}))[0],createJwk:async t=>await e.create({model:"jwks",data:{...t,createdAt:new Date}})});import{exportJWK as lr,generateKeyPair as Yo,importJWK as Xo,SignJWT as en}from"jose";var hm=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await at(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[A]},async t=>{let r=at(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await Yo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await lr(c),m=await lr(l),f=JSON.stringify(m),k={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(await ie({key:t.context.options.secret,data:f})):f,createdAt:new Date};o=await r.createJwk(k)}let i=n?await se({key:t.context.options.secret,data:JSON.parse(o.privateKey)}):o.privateKey,a=await Xo(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new en({...s,...t.context.session.session.impersonatedBy?{impersonatedBy:t.context.session.session.impersonatedBy}:{}}).setProtectedHeader({alg:e?.jwks?.keyPairConfig?.alg??"EdDSA",kid:o.id}).setIssuedAt().setIssuer(e?.jwt?.issuer??t.context.options.baseURL).setAudience(e?.jwt?.audience??t.context.options.baseURL).setExpirationTime(e?.jwt?.expirationTime??"15m").setSubject(t.context.session.user.id).sign(a);return t.json({token:d})})},schema:ur});import{z as Ze}from"zod";var km=e=>{let t={maximumSessions:5,...e},r=o=>o.includes("_multi-");return{id:"multi-session",endpoints:{listDeviceSessions:u("/multi-session/list-device-sessions",{method:"GET",requireHeaders:!0},async o=>{let n=o.headers?.get("cookie");if(!n)return o.json([]);let i=Object.fromEntries(Be(n)),a=(await Promise.all(Object.entries(i).filter(([c])=>r(c)).map(async([c])=>await o.getSignedCookie(c,o.context.secret)))).filter(c=>c!==void 0);if(!a.length)return o.json([]);let d=(await o.context.internalAdapter.findSessions(a)).filter(c=>c&&c.session.expiresAt>new Date).filter((c,l,p)=>l===p.findIndex(m=>m.user.id===c.user.id));return Object.entries(i).filter(([c])=>r(c)).forEach(([c,l])=>{d.some(p=>p.session.id===l)||o.setCookie(c,"",{...o.context.authCookies.sessionToken.options,maxAge:0})}),o.json(d)}),setActiveSession:u("/multi-session/set-active",{method:"POST",body:Ze.object({sessionId:Ze.string()}),requireHeaders:!0,use:[A]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new v("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);if(!s||s.session.expiresAt<new Date)throw o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),new v("UNAUTHORIZED",{message:"Invalid session id"});return await o.setSignedCookie(o.context.authCookies.sessionToken.name,n,o.context.secret,o.context.authCookies.sessionToken.options),o.json(s)}),revokeDeviceSession:u("/multi-session/revoke",{method:"POST",body:Ze.object({sessionId:Ze.string()}),requireHeaders:!0,use:[A]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new v("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);return o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),s?(await o.context.internalAdapter.deleteSession(n),o.json({success:!0})):o.json({success:!0})})},hooks:{after:[{matcher:()=>!0,handler:T(async o=>{if(!o.context.returned||!(o.context.returned instanceof Response))return;let n=o.context.returned.headers.get("set-cookie");if(!n)return;let i=pt(n),a=o.context.authCookies.sessionToken,s=i.get(a.name)?.value;if(!s)return;let d=Be(o.headers?.get("cookie")||""),c=s.split(".")[0],l=`${a.name}_multi-${c}`;if(i.get(l)||d.get(l)||Object.keys(Object.fromEntries(d)).filter(r).length+(n.includes("session_token")?1:0)>t.maximumSessions)return;await o.setSignedCookie(l,c,o.context.secret,a.options);let m=o.context.returned;return m.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:m}})},{matcher:o=>o.path==="/sign-out",handler:T(async o=>{let n=o.headers?.get("cookie");if(!n)return;let i=Object.fromEntries(Be(n));await Promise.all(Object.entries(i).map(async([s,d])=>{if(r(s)){o.setCookie(s,"",{maxAge:0});let c=s.split("_multi-")[1];await o.context.internalAdapter.deleteSession(c)}}));let a=o.context.returned;return a?.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:a}})}]}}};import{z as re}from"zod";var Pm=e=>{let t={expireIn:300,otpLength:6,...e};return{id:"email-otp",endpoints:{sendVerificationOTP:u("/email-otp/send-verification-otp",{method:"POST",body:re.object({email:re.string(),type:re.enum(["email-verification","sign-in"])})},async r=>{if(!e?.sendVerificationOTP)throw y.error("send email verification is not implemented"),new v("BAD_REQUEST",{message:"send email verification is not implemented"});let o=r.body.email,n=N(t.otpLength,F("0-9"));return await r.context.internalAdapter.createVerificationValue({value:n,identifier:`${r.body.type}-otp-${o}`,expiresAt:C(t.expireIn,"sec")}),await e.sendVerificationOTP({email:o,otp:n,type:r.body.type}),r.json({success:!0})}),verifyEmailOTP:u("/email-otp/verify-email",{method:"POST",body:re.object({email:re.string(),otp:re.string()})},async r=>{let o=r.body.email,n=await r.context.internalAdapter.findVerificationValue(`email-verification-otp-${o}`);if(!n||n.expiresAt<new Date)throw n&&await r.context.internalAdapter.deleteVerificationValue(n.id),new v("BAD_REQUEST",{message:"Invalid OTP"});let i=r.body.otp;if(n.value!==i)throw new v("BAD_REQUEST",{message:"Invalid OTP"});await r.context.internalAdapter.deleteVerificationValue(n.id);let a=await r.context.internalAdapter.findUserByEmail(o);if(!a)throw new v("BAD_REQUEST",{message:"User not found"});let s=await r.context.internalAdapter.updateUser(a.user.id,{email:o,emailVerified:!0});return r.json({user:s})}),signInEmailOTP:u("/sign-in/email-otp",{method:"POST",body:re.object({email:re.string(),otp:re.string()})},async r=>{let o=r.body.email,n=await r.context.internalAdapter.findVerificationValue(`sign-in-otp-${o}`);if(!n||n.expiresAt<new Date)throw n&&await r.context.internalAdapter.deleteVerificationValue(n.id),new v("BAD_REQUEST",{message:"Invalid OTP"});let i=r.body.otp;if(n.value!==i)throw new v("BAD_REQUEST",{message:"Invalid OTP"});await r.context.internalAdapter.deleteVerificationValue(n.id);let a=await r.context.internalAdapter.findUserByEmail(o);if(!a){if(t.disableSignUp)throw new v("BAD_REQUEST",{message:"User not found"});let d=await r.context.internalAdapter.createUser({email:o,emailVerified:!0,name:o}),c=await r.context.internalAdapter.createSession(d.id,r.request);return await w(r,{session:c,user:d}),r.json({user:d,session:c})}let s=await r.context.internalAdapter.createSession(a.user.id,r.request);return await w(r,{session:s,user:a.user}),r.json({session:s,user:a})})},hooks:{after:[{matcher(r){return!!(r.path?.startsWith("/sign-up")&&t.sendVerificationOnSignUp)},async handler(r){let o=r.context.returned;if(o?.status!==200)return;let n=await o.clone().json();if(n.user.email&&n.user.emailVerified===!1){let i=N(t.otpLength,F("0-9"));await r.context.internalAdapter.createVerificationValue({value:i,identifier:`email-verification-otp-${n.user.email}`,expiresAt:C(t.expireIn,"sec")}),await e.sendVerificationOTP({email:n.user.email,otp:i,type:"email-verification"})}}}]}}};import{z as mr}from"zod";import{betterFetch as tn}from"@better-fetch/fetch";function pr(e){return e==="true"||e===!0}var jm=e=>({id:"one-tap",endpoints:{oneTapCallback:u("/one-tap/callback",{method:"POST",body:mr.object({idToken:mr.string()})},async t=>{let{idToken:r}=t.body,{data:o,error:n}=await tn("https://oauth2.googleapis.com/tokeninfo?id_token="+r);if(n)return t.json({error:"Invalid token"});let i=await t.context.internalAdapter.findUserByEmail(o.email);if(!i){if(e?.disableSignup)throw new v("BAD_GATEWAY",{message:"User not found"});let s=await t.context.internalAdapter.createOAuthUser({email:o.email,emailVerified:pr(o.email_verified),name:o.name,image:o.picture},{providerId:"google",accountId:o.sub});if(!s)throw new v("INTERNAL_SERVER_ERROR",{message:"Could not create user"});let d=await t.context.internalAdapter.createSession(s?.user.id,t.request);return await w(t,{user:s.user,session:d}),t.json({session:d,user:s})}let a=await t.context.internalAdapter.createSession(i.user.id,t.request);return await w(t,{user:i.user,session:a}),t.json({session:a,user:i})})}});import{z as dt}from"zod";function rn(){let e=Q.VERCEL_URL,t=Q.NETLIFY_URL,r=Q.RENDER_URL,o=Q.AWS_LAMBDA_FUNCTION_NAME,n=Q.GOOGLE_CLOUD_FUNCTION_NAME,i=Q.AZURE_FUNCTION_NAME;return e||t||r||o||n||i}var $m=e=>({id:"oauth-proxy",endpoints:{oAuthProxy:u("/oauth-proxy-callback",{method:"GET",query:dt.object({callbackURL:dt.string(),cookies:dt.string()})},async t=>{let r=t.query.cookies,o=await se({key:t.context.secret,data:r});throw t.setHeader("set-cookie",o),t.redirect(t.query.callbackURL)})},hooks:{after:[{matcher(t){return t.path?.startsWith("/callback")},handler:T(async t=>{let r=t.context.returned;if(!r)return;let o=r.headers.get("location");if(o?.includes("/oauth-proxy-callback?callbackURL")){if(!o.startsWith("http")||new URL(o).origin===t.context.baseURL)return;let i=r.headers.get("set-cookie");if(!i)return;let a=await ie({key:t.context.secret,data:i}),s=`${o}&cookies=${encodeURIComponent(a)}`;return r.headers.set("location",s),{response:r}}})}],before:[{matcher(t){return t.path?.startsWith("/sign-in/social")},async handler(t){let r=new URL(e?.currentURL||t.request?.url||rn()||t.context.baseURL);return t.body.callbackURL=`${r.origin}${t.context.options.basePath||"/api/auth"}/oauth-proxy-callback?callbackURL=${encodeURIComponent(t.body.callbackURL||t.context.baseURL)}`,{context:t}}}]}});export{we as HIDE_METADATA,Hp as admin,J as adminMiddleware,Fp as anonymous,hp as bearer,u as createAuthEndpoint,T as createAuthMiddleware,Pm as emailOTP,im as genericOAuth,Mo as getPasskeyActions,hm as jwt,Rp as magicLink,km as multiSession,$m as oAuthProxy,jm as oneTap,ut as optionsMiddleware,Dc as organization,dp as passkey,Kl as passkeyClient,zp as phoneNumber,ul as twoFactor,Gu as twoFactorClient,dr as username};
|