authhero 0.68.0 → 0.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authhero.cjs +1 -1
- package/dist/authhero.mjs +1 -1
- package/package.json +1 -1
package/dist/authhero.cjs
CHANGED
|
@@ -146,7 +146,7 @@ PERFORMANCE OF THIS SOFTWARE.
|
|
|
146
146
|
}};
|
|
147
147
|
<\/script>
|
|
148
148
|
</body>
|
|
149
|
-
</html>`;return new Response(i,{headers:{"Content-Type":"text/html"}})}async function Jw(t,e,n,r,i){var m,y,f;if(!n.redirect_uri)throw new z(400,{message:"Missing redirect_uri in authParams"});const[s]=await t.env.data.keys.list();if(!s)throw new z(500,{message:"No signing key found"});if(!((m=e.addons)!=null&&m.samlp))throw new z(400,{message:`SAML Addon is not enabled for client ${e.id}`});const{recipient:o,audience:c}=e.addons.samlp,l=n.state||"";if(!o||!l||!r||!n.state)throw new z(400,{message:"Missing recipient or inResponseTo"});const u=JSON.parse(n.state),p=new URL(n.redirect_uri),h=await Zw(t,{issuer:t.env.ISSUER,audience:c||n.client_id,destination:p.toString(),inResponseTo:u.requestId,userId:((f=(y=r.app_metadata)==null?void 0:y.vimeo)==null?void 0:f.user_id)||r.user_id,email:r.email,sessionIndex:i,signature:{privateKeyPem:s.pkcs7,cert:s.cert,kid:s.kid}});return Gw(p.toString(),h,u.relayState)}async function Zw(t,e){const n=e.notBefore||new Date().toISOString(),r=e.notAfter||new Date(new Date(n).getTime()+10*60*1e3).toISOString(),i=e.issueInstant||n,s=e.sessionNotOnOrAfter||r,o=e.responseId||`_${qe()}`,c=e.assertionId||`_${qe()}`,l=[{"samlp:Response":[{"saml:Issuer":[{"#text":e.issuer}]},{"samlp:Status":[{"samlp:StatusCode":[],":@":{"@_Value":"urn:oasis:names:tc:SAML:2.0:status:Success"}}]},{"saml:Assertion":[{"saml:Issuer":[{"#text":e.issuer}]},{"saml:Subject":[{"saml:NameID":[{"#text":e.email}],":@":{"@_Format":"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"}},{"saml:SubjectConfirmation":[{"saml:SubjectConfirmationData":[],":@":{"@_InResponseTo":e.inResponseTo,"@_NotOnOrAfter":r,"@_Recipient":e.destination}}],":@":{"@_Method":"urn:oasis:names:tc:SAML:2.0:cm:bearer"}}]},{"saml:Conditions":[{"saml:AudienceRestriction":[{"saml:Audience":[{"#text":e.audience}]}]}],":@":{"@_NotBefore":n,"@_NotOnOrAfter":r}},{"saml:AuthnStatement":[{"saml:AuthnContext":[{"saml:AuthnContextClassRef":[{"#text":"urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"}]}]}],":@":{"@_AuthnInstant":i,"@_SessionIndex":e.sessionIndex,"@_SessionNotOnOrAfter":s}},{"saml:AttributeStatement":[{"saml:Attribute":[{"saml:AttributeValue":[{"#text":e.userId}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_FriendlyName":"persistent","@_Name":"id","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":e.email}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"email","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"manage-account"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"default-roles-master"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"offline_access"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"view-profile"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"uma_authorization"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"manage-account-links"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}}]}],":@":{"@_xmlns":"urn:oasis:names:tc:SAML:2.0:assertion","@_ID":c,"@_IssueInstant":i,"@_Version":"2.0"}}],":@":{"@_xmlns:samlp":"urn:oasis:names:tc:SAML:2.0:protocol","@_xmlns:saml":"urn:oasis:names:tc:SAML:2.0:assertion","@_Destination":e.destination,"@_ID":o,"@_InResponseTo":e.inResponseTo,"@_IssueInstant":i,"@_Version":"2.0"}}];let p=new Ww.XMLBuilder({ignoreAttributes:!1,suppressEmptyNode:!0,preserveOrder:!0}).build(l);if(e.signature){const m=await fetch(t.env.SAML_SIGN_URL,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({xmlContent:p,privateKey:e.signature.privateKeyPem,publicCert:e.signature.cert})});if(!m.ok)throw new Error(`Failed to sign SAML response: ${m.status}`);p=await m.text()}return e.encode===!1?p:btoa(p)}function Yw(){const t=new Uint8Array(32);return crypto.getRandomValues(t),gn.encode(t,{includePadding:!1})}const Ap=["sub","iss","aud","exp","nbf","iat","jti"];async function Yl(t,e){var _,w;const{authParams:n,user:r,client:i,session_id:s}=e,c=(await t.env.data.keys.list()).filter(S=>!S.revoked_at||new Date(S.revoked_at)>new Date),l=c[c.length-1];if(!(l!=null&&l.pkcs7))throw new z(500,{message:"No signing key available"});const u=Ev(l.pkcs7),p={aud:n.audience||"default",scope:n.scope||"",sub:(r==null?void 0:r.user_id)||n.client_id,iss:t.env.ISSUER,tenant_id:t.var.tenant_id,sid:s},h=r&&((_=n.scope)!=null&&_.split(" ").includes("openid"))?{aud:n.client_id,sub:r.user_id,iss:t.env.ISSUER,sid:s,nonce:n.nonce,given_name:r.given_name,family_name:r.family_name,nickname:r.nickname,picture:r.picture,locale:r.locale,name:r.name,email:r.email,email_verified:r.email_verified}:void 0;(w=t.env.hooks)!=null&&w.onExecuteCredentialsExchange&&await t.env.hooks.onExecuteCredentialsExchange({client:i,user:r,scope:n.scope||"",grant_type:""},{accessToken:{setCustomClaim:(S,N)=>{if(Ap.includes(S))throw new Error(`Cannot overwrite reserved claim '${S}'`);p[S]=N}},idToken:{setCustomClaim:(S,N)=>{if(Ap.includes(S))throw new Error(`Cannot overwrite reserved claim '${S}'`);h&&(h[S]=N)}},access:{deny:S=>{throw new z(400,{message:`Access denied: ${S}`})}}});const m={includeIssuedTimestamp:!0,expiresIn:new Fl(1,"d"),headers:{kid:l.kid}},y=await vp("RS256",u,p,m),f=h?await vp("RS256",u,h,m):void 0;return{access_token:y,refresh_token:e.refresh_token,id_token:f,token_type:"Bearer",expires_in:86400}}async function Xw(t,e){const{client:n,scope:r,audience:i=n.tenant.audience,session_id:s}=e;return await t.env.data.refreshTokens.create(n.tenant.id,{id:qe(),session_id:s,client_id:n.id,expires_at:new Date(Date.now()+Mo*1e3).toISOString(),user_id:e.user.user_id,device:{last_ip:t.req.header("x-real-ip")||"",initial_ip:t.req.header("x-real-ip")||"",last_user_agent:t.req.header("user-agent")||"",initial_user_agent:t.req.header("user-agent")||"",initial_asn:"",last_asn:""},resource_servers:[{audience:i,scopes:r}],rotating:!1})}async function Bg(t,e){const{user:n,client:r,scope:i,audience:s}=e,o=await t.env.data.sessions.create(r.tenant.id,{id:qe(),user_id:n.user_id,idle_expires_at:new Date(Date.now()+Mo*1e3).toISOString(),device:{last_ip:t.req.header("x-real-ip")||"",initial_ip:t.req.header("x-real-ip")||"",last_user_agent:t.req.header("user-agent")||"",initial_user_agent:t.req.header("user-agent")||"",initial_asn:"",last_asn:""},clients:[r.id]}),c=i!=null&&i.split(" ").includes("offline_access")?await Xw(t,{...e,session_id:o.id,scope:i,audience:s}):void 0;return{...o,refresh_token:c}}async function Tn(t,e){var h;const{authParams:n,user:r,client:i}=e,s=be(t,{type:me.SUCCESS_LOGIN,description:`Successful login for ${r.user_id}`,userId:r.user_id});if(Xe(t,t.env.data.logs.create(i.tenant.id,s)),Xe(t,t.env.data.users.update(i.tenant.id,r.user_id,{last_login:new Date().toISOString(),last_ip:t.req.header("x-real-ip")||"",login_count:r.login_count+1})),e!=null&&e.ticketAuth){if(!e.loginSession)throw new z(500,{message:"Login session not found"});const m=Yw(),y=qe(12),f=await t.env.data.codes.create(i.tenant.id,{code_id:qe(),code_type:"ticket",login_id:e.loginSession.login_id,expires_at:new Date(Date.now()+Ry).toISOString(),code_verifier:[y,m].join("|")});return t.json({login_ticket:f.code_id,co_verifier:m,co_id:y})}let o=e.refreshToken,c=e.sessionId;if(!c){const m=await Bg(t,{user:r,client:i,scope:n.scope,audience:n.audience});c=m.id,o=(h=m.refresh_token)==null?void 0:h.id}if(e.authParams.response_mode===Jt.SAML_POST)return Jw(t,e.client,e.authParams,r,c);const l=await Yl(t,{authParams:n,user:r,client:i,session_id:c,refresh_token:o}),u=new Headers({"set-cookie":Eg(i.tenant.id,c)});if(n.response_mode===Jt.WEB_MESSAGE)return t.json(l,{headers:u});if((n.response_type||mn.CODE)===mn.CODE){if(!e.loginSession)throw new z(500,{message:"Login session not found"});const m=await t.env.data.codes.create(i.tenant.id,{code_id:qe(),user_id:r.user_id,code_type:"authorization_code",login_id:e.loginSession.login_id,expires_at:new Date(Date.now()+Ty*1e3).toISOString()});u.set("location",`${n.redirect_uri}?state=${e.authParams.state}&code=${m.code_id}`)}return new Response("Redirecting",{status:302,headers:u})}function Qw(t){return async(e,n)=>{if(!n.email||!n.email_verified)return t.users.create(e,n);const r=await Zs({userAdapter:t.users,tenant_id:e,email:n.email});return r?(await t.users.create(e,{...n,linked_to:r.user_id}),r):t.users.create(e,n)}}async function Tg(t,e,n){for await(const r of e)if(!(await fetch(r.url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).ok){const s=be(t,{type:me.FAILED_LOGIN_INCORRECT_PASSWORD,description:"Invalid password"});await n.logs.create(t.var.tenant_id,s)}}function eb(t,e){return async(n,r)=>{const{hooks:i}=await e.hooks.list(n);return await Tg(t,i,{tenant_id:n,user:r,trigger_id:"post-user-registration"}),r}}function tb(t,e){return async(n,r)=>{const{hooks:i}=await e.hooks.list(n,{q:"trigger_id:pre-user-signup",page:0,per_page:100,include_totals:!1});await Tg(t,i,{tenant_id:n,email:r,trigger_id:"pre-user-signup"})}}function nb(t,e){return async(n,r)=>{let i=await Qw(e)(n,r);return await eb(t,e)(n,i),i}}async function Pg(t,e,n,r){if(e.disable_sign_ups&&!await Zs({userAdapter:t.env.data.users,tenant_id:e.tenant.id,email:r})){const s=be(t,{type:me.FAILED_SIGNUP,description:"Public signup is disabled"});throw await t.env.data.logs.create(e.tenant.id,s),new z(400,{message:"Signups are disabled for this client"})}await tb(t,n)(t.var.tenant_id||"",r)}function rb(t,e){return{...e,users:{...e.users,create:nb(t,e)}}}async function ib(t,e,n,r){if(!r.state)throw new z(400,{message:"State not found"});const i=e.connections.find(l=>l.name===n);if(!i){t.set("client_id",e.id);const l=be(t,{type:me.FAILED_LOGIN,description:"Connection not found"});throw await t.env.data.logs.create(e.tenant.id,l),new z(403,{message:"Connection Not Found"})}let s=await t.env.data.logins.get(e.tenant.id,r.state);s||(s=await t.env.data.logins.create(e.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:r,...Bn(t.req)}));const c=await kg(t,i.strategy).getRedirect(t,i);return await t.env.data.codes.create(e.tenant.id,{login_id:s.login_id,code_id:c.code,code_type:"oauth2_state",connection_id:i.id,code_verifier:c.codeVerifier,expires_at:new Date(Date.now()+Py*1e3).toISOString()}),t.redirect(c.redirectUrl)}async function Ep(t,{code:e,state:n}){var f;const{env:r}=t,i=await r.data.codes.get(t.var.tenant_id||"",n,"oauth2_state");if(!i||!i.connection_id)throw new z(403,{message:"State not found"});const s=await r.data.logins.get(t.var.tenant_id||"",i.login_id);if(!s)throw new z(403,{message:"Session not found"});const o=await Do(r,s.authParams.client_id);t.set("client_id",o.id),t.set("tenant_id",o.tenant.id);const c=o.connections.find(_=>_.id===i.connection_id);if(!c){const _=be(t,{type:me.FAILED_LOGIN,description:"Connection not found"});throw await r.data.logs.create(o.tenant.id,_),new z(403,{message:"Connection not found"})}if(t.set("connection",c.name),!s.authParams.redirect_uri){const _=be(t,{type:me.FAILED_LOGIN,description:"Redirect URI not defined"});throw await r.data.logs.create(o.tenant.id,_),new z(403,{message:"Redirect URI not defined"})}if(!Ho(s.authParams.redirect_uri,o.callbacks||[],{allowPathWildcards:!0})){const _=`Invalid redirect URI - ${s.authParams.redirect_uri}`,w=be(t,{type:me.FAILED_LOGIN,description:_});throw await r.data.logs.create(o.tenant.id,w),new z(403,{message:_})}const u=await kg(t,c.strategy).validateAuthorizationCodeAndGetUser(t,c,e,i.code_verifier),{sub:p,...h}=u;t.set("user_id",p);const m=((f=u.email)==null?void 0:f.toLocaleLowerCase())||`${c.name}.${p}@${new URL(t.env.ISSUER).hostname}`;t.set("username",m);let y=await _n({userAdapter:r.data.users,tenant_id:o.tenant.id,email:m,provider:c.name});if(!y){try{await Pg(t,o,t.env.data,m)}catch(_){const w=_;throw new z(500,{message:`Failed to run preUserSignupHook: ${w.message}`})}y=await r.data.users.create(o.tenant.id,{user_id:`${c.name}|${p}`,email:m,name:m,provider:c.name,connection:c.name,email_verified:!0,last_ip:"",is_social:!0,last_login:new Date().toISOString(),profileData:JSON.stringify(h)}),t.set("user_id",y.user_id)}return Tn(t,{client:o,authParams:s.authParams,loginSession:s,user:y})}async function Ip(t,e,n,r,i,s){const o=await t.env.data.codes.get(t.var.tenant_id||"",e,"oauth2_state");if(!o)throw new z(400,{message:"State not found"});const c=await t.env.data.logins.get(t.var.tenant_id,o.login_id);if(!c)throw new z(400,{message:"Login not found"});const{redirect_uri:l}=c.authParams;if(!l)throw new z(400,{message:"Redirect uri not found"});const u=be(t,{type:me.FAILED_LOGIN,description:`Failed connection login: ${i} ${n}, ${r}`});Xe(t,t.env.data.logs.create(t.var.tenant_id,u));const p=new URL(l);return Oy(p,{error:n,error_description:r,error_reason:s,error_code:i,state:c.authParams.state}),t.redirect(`${At(t.env)}enter-email?state=${c.login_id}&error=${n}`)}const sb=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"get",path:"/",request:{query:a.z.object({state:a.z.string(),code:a.z.string().optional(),scope:a.z.string().optional(),hd:a.z.string().optional(),error:a.z.string().optional(),error_description:a.z.string().optional(),error_code:a.z.string().optional(),error_reason:a.z.string().optional()})},responses:{302:{description:"Redirect to the client's redirect uri"}}}),async t=>{const{state:e,code:n,error:r,error_description:i,error_code:s,error_reason:o}=t.req.valid("query");if(r)return Ip(t,e,r,i,s,o);if(!n)throw new z(400,{message:"Code is required"});return Ep(t,{code:n,state:e})}).openapi(a.createRoute({tags:["oauth2"],method:"post",path:"/",request:{body:{content:{"application/x-www-form-urlencoded":{schema:a.z.object({state:a.z.string(),code:a.z.string().optional(),scope:a.z.string().optional(),hd:a.z.string().optional(),error:a.z.string().optional(),error_description:a.z.string().optional(),error_code:a.z.string().optional(),error_reason:a.z.string().optional()})}}}},responses:{302:{description:"Redirect to the client's redirect uri"}}}),async t=>{const{state:e,code:n,error:r,error_description:i,error_code:s,error_reason:o}=t.req.valid("form");if(r)return Ip(t,e,r,i,s,o);if(!n)throw new z(400,{message:"Code is required"});return Ep(t,{code:n,state:e})}),ob=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"get",path:"/",request:{query:a.z.object({client_id:a.z.string(),returnTo:a.z.string().optional()}),header:a.z.object({cookie:a.z.string().optional()})},responses:{302:{description:"Log the user out"}}}),async t=>{const{client_id:e,returnTo:n}=t.req.valid("query"),r=await t.env.data.clients.get(e);if(!r)return t.text("OK");const i=await t.env.data.clients.get("DEFAULT_CLIENT");t.set("client_id",e),t.set("tenant_id",r.tenant.id);const s=n||t.req.header("referer");if(!s)return t.text("OK");if(!Ho(s,[...r.allowed_logout_urls||[],...(i==null?void 0:i.allowed_logout_urls)||[]],{allowPathWildcards:!0}))throw new z(400,{message:"Invalid redirect uri"});const o=t.req.header("cookie");if(o){const l=Ag(r.tenant.id,o);if(l){const u=await t.env.data.sessions.get(r.tenant.id,l);if(u){const p=await t.env.data.users.get(r.tenant.id,u.user_id);p&&(t.set("user_id",p.user_id),t.set("connection",p.connection))}await t.env.data.sessions.remove(r.tenant.id,l)}}const c=be(t,{type:me.SUCCESS_LOGOUT,description:"User successfully logged out"});return await t.env.data.logs.create(r.tenant.id,c),new Response("Redirecting",{status:302,headers:{"set-cookie":Nv(r.tenant.id),location:s}})}),Cp=a.z.object({sub:a.z.string(),email:a.z.string().optional(),family_name:a.z.string().optional(),given_name:a.z.string().optional(),email_verified:a.z.boolean()}),ab=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"get",path:"/",request:{},security:[{Bearer:["openid"]}],responses:{200:{content:{"application/json":{schema:Cp}},description:"Userinfo"}}}),async t=>{if(!t.var.user)throw new z(404,{message:"User not found"});const e=await t.env.data.users.get(t.var.user.tenant_id,t.var.user.sub);if(!e)throw new z(404,{message:"User not found"});return t.json(Cp.parse({...e,sub:e.user_id}))}),cb=new a.OpenAPIHono().openapi(a.createRoute({tags:["well known"],method:"get",path:"/jwks.json",request:{},responses:{200:{content:{"application/json":{schema:sf}},description:"List of tenants"}}}),async t=>{const e=await t.env.data.keys.list(),n=await Promise.all(e.map(async r=>{const s=await new Dl(r.cert).publicKey.export(),o=await crypto.subtle.exportKey("jwk",s);return Xc.parse({...o,kid:r.kid})}));return t.json({keys:n},{headers:{"access-control-allow-origin":"*","access-control-allow-method":"GET","cache-control":`public, max-age=${Ti}, stale-while-revalidate=${Ti*2}, stale-if-error=86400`}})}).openapi(a.createRoute({tags:["well known"],method:"get",path:"/openid-configuration",request:{},responses:{200:{content:{"application/json":{schema:ba}},description:"List of tenants"}}}),async t=>{const e=ba.parse({issuer:pv(t.env),authorization_endpoint:`${Ne(t.env)}authorize`,token_endpoint:`${Ne(t.env)}oauth/token`,device_authorization_endpoint:`${Ne(t.env)}oauth/device/code`,userinfo_endpoint:`${Ne(t.env)}userinfo`,mfa_challenge_endpoint:`${Ne(t.env)}mfa/challenge`,jwks_uri:`${Ne(t.env)}.well-known/jwks.json`,registration_endpoint:`${Ne(t.env)}oidc/register`,revocation_endpoint:`${Ne(t.env)}oauth/revoke`,scopes_supported:["openid","profile","offline_access","name","given_name","family_name","nickname","email","email_verified","picture","created_at","identities","phone","address"],response_types_supported:["code","token","id_token","code token","code id_token","token id_token","code token id_token"],code_challenge_methods_supported:["S256","plain"],response_modes_supported:["query","fragment","form_post"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],token_endpoint_auth_methods_supported:["client_secret_basic","client_secret_post"],claims_supported:["aud","auth_time","created_at","email","email_verified","exp","family_name","given_name","iat","identities","iss","name","nickname","phone_number","picture","sub"],request_uri_parameter_supported:!1,request_parameter_supported:!1,token_endpoint_auth_signing_alg_values_supported:["RS256","RS384","PS256"]});return t.json(e,{headers:{"access-control-allow-origin":"*","access-control-allow-method":"GET","cache-control":`public, max-age=${Ti}, stale-while-revalidate=${Ti*2}, stale-if-error=86400`}})});function Fi(t,e){if(!t||!e||t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t.charCodeAt(r)^e.charCodeAt(r);return n===0}const Rg=a.z.object({grant_type:a.z.literal("client_credentials"),scope:a.z.string().optional(),client_secret:a.z.string(),client_id:a.z.string(),audience:a.z.string().optional()});async function lb(t,e){const n=await t.env.data.clients.get(e.client_id);if(!n)throw new z(403,{message:"Invalid client credentials"});if(n.client_secret&&!Fi(n.client_secret,e.client_secret))throw new z(403,{message:"Invalid client credentials"});const r={client_id:n.id,scope:e.scope,audience:e.audience},i=await Yl(t,{authParams:r,client:n});return t.json(i)}const ub=a.z.object({grant_type:a.z.literal("authorization_code"),client_id:a.z.string(),code:a.z.string(),redirect_uri:a.z.string().optional(),client_secret:a.z.string().optional(),code_verifier:a.z.string().optional()}).refine(t=>"client_secret"in t&&!("code_verifier"in t)||!("client_secret"in t)&&"code_verifier"in t,{message:"Must provide either client_secret (standard flow) or code_verifier/code_verifier_mode (PKCE flow), but not both"});async function db(t,e){const n=await t.env.data.clients.get(e.client_id);if(!n)throw new z(403,{message:"Client not found"});const r=await t.env.data.codes.get(n.tenant.id,e.code,"authorization_code");if(!r||!r.user_id)throw new z(403,{message:"Invalid client credentials"});if(new Date(r.expires_at)<new Date)throw new z(403,{message:"Code expired"});if(r.used_at)throw new z(403,{message:"Code already used"});const i=await t.env.data.logins.get(n.tenant.id,r.login_id);if(!i)throw new z(403,{message:"Invalid login"});if("client_secret"in e){const o=await t.env.data.clients.get("DEFAULT_CLIENT");if(!Fi(n.client_secret,e.client_secret)&&!Fi(o==null?void 0:o.client_secret,e.client_secret))throw new z(403,{message:"Invalid client credentials"})}else if("code_verifier"in e&&typeof e.code_verifier=="string"&&"code_challenge_method"in i.authParams&&typeof i.authParams.code_challenge_method=="string"){const o=await Iv(e.code_verifier,i.authParams.code_challenge_method);if(!Fi(o,i.authParams.code_challenge||""))throw new z(403,{message:"Invalid client credentials"})}if(i.authParams.redirect_uri&&i.authParams.redirect_uri!==e.redirect_uri)throw new z(403,{message:"Invalid redirect uri"});const s=await t.env.data.users.get(n.tenant.id,r.user_id);if(!s)throw new z(403,{message:"User not found"});return await t.env.data.codes.used(n.tenant.id,e.code),Tn(t,{user:s,client:n,loginSession:i,authParams:{...i.authParams,response_mode:Jt.WEB_MESSAGE}})}const pb=a.z.object({grant_type:a.z.literal("refresh_token"),client_id:a.z.string(),redirect_uri:a.z.string().optional(),refresh_token:a.z.string()});async function fb(t,e){const n=await t.env.data.clients.get(e.client_id);if(!n)throw new z(403,{message:"Client not found"});const r=await t.env.data.refreshTokens.get(n.tenant.id,e.refresh_token);if(r){if(r.expires_at&&new Date(r.expires_at)<new Date||r.idle_expires_at&&new Date(r.idle_expires_at)<new Date)throw new z(403,{message:JSON.stringify({error:"invalid_grant",error_description:"Refresh token has expired"})})}else throw new z(403,{message:JSON.stringify({error:"invalid_grant",error_description:"Invalid refresh token"})});const i=await t.env.data.users.get(n.tenant.id,r.user_id);if(!i)throw new z(403,{message:"User not found"});const s=r.resource_servers[0];if(r.idle_expires_at){const o=new Date(Date.now()+2592e6);await t.env.data.refreshTokens.update(n.tenant.id,r.id,{idle_expires_at:o.toISOString(),last_exchanged_at:new Date().toISOString(),device:{...r.device,last_ip:t.req.header["x-real-ip"]||"",last_user_agent:t.req.header["user-agent"]||""}})}return Tn(t,{user:i,client:n,refreshToken:r.id,sessionId:r.session_id,authParams:{client_id:n.id,audience:s==null?void 0:s.audience,scope:s==null?void 0:s.scopes,response_mode:Jt.WEB_MESSAGE}})}const Np=a.z.object({client_id:a.z.string().optional(),client_secret:a.z.string().optional()}),hb=a.z.union([Rg.extend(Np.shape),a.z.object({grant_type:a.z.literal("authorization_code"),client_id:a.z.string(),code:a.z.string(),redirect_uri:a.z.string(),code_verifier:a.z.string().min(43).max(128)}),a.z.object({grant_type:a.z.literal("authorization_code"),code:a.z.string(),redirect_uri:a.z.string().optional(),...Np.shape}),a.z.object({grant_type:a.z.literal("refresh_token"),client_id:a.z.string(),refresh_token:a.z.string(),redirect_uri:a.z.string().optional()})]);function gb(t){if(!t)return{};const[e,n]=t.split(" ");if((e==null?void 0:e.toLowerCase())==="basic"&&n){const[r,i]=atob(n).split(":");return{client_id:r,client_secret:i}}return{}}const mb=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"post",path:"/",request:{body:{content:{"application/x-www-form-urlencoded":{schema:hb}}}},responses:{200:{content:{"application/json":{schema:df}},description:"Tokens"}}}),async t=>{const e=t.req.valid("form"),n=gb(t.req.header("Authorization")),r={...e,...n};if(!r.client_id)throw new z(400,{message:"client_id is required"});switch(e.grant_type){case jr.AuthorizationCode:return db(t,ub.parse(r));case jr.ClientCredential:return lb(t,Rg.parse(r));case jr.RefreshToken:return fb(t,pb.parse(r));default:throw new z(400,{message:"Not implemented"})}});var Xl={exports:{}};const Ql=[{id:0,value:"Too weak",minDiversity:0,minLength:0},{id:1,value:"Weak",minDiversity:2,minLength:6},{id:2,value:"Medium",minDiversity:4,minLength:8},{id:3,value:"Strong",minDiversity:4,minLength:10}],Lg=(t,e=Ql,n="!\"#$%&'()*+,-./:;<=>?@[\\\\\\]^_`{|}~")=>{let r=t||"";e[0].minDiversity=0,e[0].minLength=0;const i=[{regex:"[a-z]",message:"lowercase"},{regex:"[A-Z]",message:"uppercase"},{regex:"[0-9]",message:"number"}];n&&i.push({regex:`[${n}]`,message:"symbol"});let s={};s.contains=i.filter(c=>new RegExp(`${c.regex}`).test(r)).map(c=>c.message),s.length=r.length;let o=e.filter(c=>s.contains.length>=c.minDiversity).filter(c=>s.length>=c.minLength).sort((c,l)=>l.id-c.id).map(c=>({id:c.id,value:c.value}));return Object.assign(s,o[0]),s};Xl.exports={passwordStrength:Lg,defaultOptions:Ql};var _b=Xl.exports.passwordStrength=Lg;Xl.exports.defaultOptions=Ql;function eu(t){return _b(t).id<2?!1:t.length>=8&&/[a-z]/.test(t)&&/[A-Z]/.test(t)&&/[0-9]/.test(t)&&/[^A-Za-z0-9]/.test(t)}async function Ko(t,e){var i;const n=await t.env.data.emailProviders.get(t.var.tenant_id)||(t.env.DEFAULT_TENANT_ID?await t.env.data.emailProviders.get(t.env.DEFAULT_TENANT_ID):null);if(!n)throw new z(500,{message:"Email provider not found"});const r=(i=t.env.emailProviders)==null?void 0:i[n.name];if(!r)throw new z(500,{message:"Email provider not found"});await r({emailProvider:n,...e,from:n.default_from_address||`login@${t.env.ISSUER}`})}async function Ug(t,e,n,r){const i=await t.env.data.tenants.get(t.var.tenant_id);if(!i)throw new z(500,{message:"Tenant not found"});const s=`${At(t.env)}reset-password?state=${r}&code=${n}`,o={vendorName:i.name,lng:i.language||"en"};await Ko(t,{to:e,subject:"Reset your password",html:`Click here to reset your password: ${At(t.env)}reset-password?state=${r}&code=${n}`,template:"auth-password-reset",data:{vendorName:i.name,logo:i.logo||"",passwordResetUrl:s,supportUrl:i.support_url||"https://support.sesamy.com",buttonColor:i.primary_color||"#7d68f4",passwordResetTitle:fe("password_reset_title",o),resetPasswordEmailClickToReset:fe("reset_password_email_click_to_reset",o),resetPasswordEmailReset:fe("reset_password_email_reset",o),supportInfo:fe("support_info",o),contactUs:fe("contact_us",o),copyright:fe("copyright",o)}})}async function Vg(t,e,n){const r=await t.env.data.tenants.get(t.var.tenant_id);if(!r)throw new z(500,{message:"Tenant not found"});const i={vendorName:r.name,code:n,lng:r.language||"en"};await Ko(t,{to:e,subject:fe("code_email_subject",i),html:`Click here to validate your email: ${At(t.env)}validate-email`,template:"auth-link",data:{code:n,vendorName:r.name,logo:r.logo||"",supportUrl:r.support_url||"",magicLink:`${Ne(t.env)}passwordless/verify_redirect?ticket=${n}`,buttonColor:r.primary_color||"",welcomeToYourAccount:fe("welcome_to_your_account",i),linkEmailClickToLogin:fe("link_email_click_to_login",i),linkEmailLogin:fe("link_email_login",i),linkEmailOrEnterCode:fe("link_email_or_enter_code",i),codeValid30Mins:fe("code_valid_30_minutes",i),supportInfo:fe("support_info",i),contactUs:fe("contact_us",i),copyright:fe("copyright",i)}});const s=be(t,{type:me.CODE_LINK_SENT,description:e});Xe(t,t.env.data.logs.create(r.id,s))}async function tu(t,e,n,r){const i=await t.env.data.tenants.get(t.var.tenant_id);if(!i)throw new z(500,{message:"Tenant not found"});if(!r.redirect_uri)throw new z(400,{message:"redirect_uri is required"});const s=new URL(Ne(t.env));s.pathname="passwordless/verify_redirect",s.searchParams.set("code",n),s.searchParams.set("client_id",r.client_id),s.searchParams.set("redirect_uri",r.redirect_uri),s.searchParams.set("email",e),r.response_type&&s.searchParams.set("response_type",r.response_type),r.scope&&s.searchParams.set("scope",r.scope),r.state&&s.searchParams.set("state",r.state),r.nonce&&s.searchParams.set("nonce",r.nonce),r.code_challenge&&s.searchParams.set("code_challenge",r.code_challenge),r.code_challenge_method&&s.searchParams.set("code_challenge_method",r.code_challenge_method),r.audience&&s.searchParams.set("audience",r.audience);const o={vendorName:i.name,code:n,lng:i.language||"en"};await Ko(t,{to:e,subject:fe("code_email_subject",o),html:`Click here to validate your email: ${At(t.env)}validate-email`,template:"auth-link",data:{code:n,vendorName:i.name,logo:i.logo||"",supportUrl:i.support_url||"",magicLink:s.toString(),buttonColor:i.primary_color||"",welcomeToYourAccount:fe("welcome_to_your_account",o),linkEmailClickToLogin:fe("link_email_click_to_login",o),linkEmailLogin:fe("link_email_login",o),linkEmailOrEnterCode:fe("link_email_or_enter_code",o),codeValid30Mins:fe("code_valid_30_minutes",o),supportInfo:fe("support_info",o),contactUs:fe("contact_us",o),copyright:fe("copyright",o)}});const c=be(t,{type:me.CODE_LINK_SENT,description:e});Xe(t,t.env.data.logs.create(i.id,c))}async function nu(t,e){const n=await t.env.data.tenants.get(t.var.tenant_id);if(!n)throw new z(500,{message:"Tenant not found"});const r={vendorName:n.name,lng:n.language||"en"};await Ko(t,{to:e.email,subject:"Validate your email address",html:`Click here to validate your email: ${At(t.env)}validate-email`,template:"auth-verify-email",data:{vendorName:n.name,logo:n.logo||"",emailValidationUrl:`${At(t.env)}validate-email`,supportUrl:n.support_url||"https://support.sesamy.com",buttonColor:n.primary_color||"#7d68f4",welcomeToYourAccount:fe("welcome_to_your_account",r),verifyEmailVerify:fe("verify_email_verify",r),supportInfo:fe("support_info",r),contactUs:fe("contact_us",r),copyright:fe("copyright",r)}})}const yb=new a.OpenAPIHono().openapi(a.createRoute({tags:["dbconnections"],method:"post",path:"/signup",request:{body:{content:{"application/json":{schema:a.z.object({client_id:a.z.string(),connection:a.z.literal("Username-Password-Authentication"),email:a.z.string().transform(t=>t.toLowerCase()),password:a.z.string()})}}}},responses:{200:{content:{"application/json":{schema:a.z.object({_id:a.z.string(),email:a.z.string(),email_verified:a.z.boolean(),app_metadata:a.z.object({}),user_metadata:a.z.object({})})}},description:"Created user"}}}),async t=>{const{email:e,password:n,client_id:r}=t.req.valid("json"),i=await t.env.data.clients.get(r);if(!i)throw new z(400,{message:"Client not found"});if(t.set("client_id",i.id),t.set("tenant_id",i.tenant.id),!eu(n))throw new z(400,{message:"Password does not meet the requirements"});if(await _n({userAdapter:t.env.data.users,tenant_id:i.tenant.id,email:e,provider:"auth2"}))throw new z(400,{message:"Invalid sign up"});const o=await t.env.data.users.create(i.tenant.id,{user_id:`auth2|${oi()}`,email:e,email_verified:!1,provider:"auth2",connection:"Username-Password-Authentication",is_social:!1});t.set("user_id",o.user_id),t.set("username",o.email),t.set("connection",o.connection);const c=await si.hash(n,10);await t.env.data.passwords.create(i.tenant.id,{user_id:o.user_id,password:c,algorithm:"bcrypt"}),await nu(t,o);const l=be(t,{type:me.SUCCESS_SIGNUP,description:"Successful signup"});return await t.env.data.logs.create(i.tenant.id,l),t.json({_id:o.user_id,email:o.email,email_verified:!1,app_metadata:{},user_metadata:{}})}).openapi(a.createRoute({tags:["dbconnections"],method:"post",path:"/change_password",request:{body:{content:{"application/json":{schema:a.z.object({client_id:a.z.string(),connection:a.z.literal("Username-Password-Authentication"),email:a.z.string().transform(t=>t.toLowerCase())})}}}},responses:{200:{description:"Redirect to the client's redirect uri"}}}),async t=>{const{email:e,client_id:n}=t.req.valid("json"),r=await t.env.data.clients.get(n);if(!r)throw new z(400,{message:"Client not found"});if(t.set("client_id",r.id),t.set("tenant_id",r.tenant.id),!await Kn({userAdapter:t.env.data.users,tenant_id:r.tenant.id,email:e,provider:"auth2"}))return t.html("If an account with that email exists, we've sent instructions to reset your password.");const s={client_id:n,username:e},o=await t.env.data.logins.create(r.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:s,...Bn(t.req)});return await Ug(t,e,o.login_id,o.authParams.state),t.html("If an account with that email exists, we've sent instructions to reset your password.")});function ir(){const t="1234567890";let e="";for(let n=0;n<6;n+=1)e+=t[Math.floor(Math.random()*10)];return e.toString()}async function ru(t,e,n,r,i,s){const{env:o}=t,c=await o.data.codes.get(e.tenant.id,i,"otp");if(!c)throw new z(400,{message:"Code not found or expired"});if(c.expires_at<new Date().toISOString())throw new z(400,{message:"Code expired"});if(c.used_at)throw new z(400,{message:"Code already used"});const l=await o.data.logins.get(e.tenant.id,c.login_id);if(!l||l.authParams.username!==r)throw new z(400,{message:"Code not found or expired"});const u=Bn(t.req);if(l.ip!==u.ip)return t.redirect(`${At(t.env)}invalid-session?state=${l.login_id}`);if(n.redirect_uri&&!Ho(n.redirect_uri,e.callbacks,{allowPathWildcards:!0}))throw new z(400,{message:`Invalid redirect URI - ${n.redirect_uri}`});const p=await _n({userAdapter:o.data.users,tenant_id:e.tenant.id,email:r,provider:"email"});if(!p)throw new z(400,{message:"User not found"});return await o.data.codes.used(e.tenant.id,i),Tn(t,{user:p,client:e,loginSession:l,authParams:n,ticketAuth:s})}const vb=new a.OpenAPIHono().openapi(a.createRoute({tags:["passwordless"],method:"post",path:"/start",request:{body:{content:{"application/json":{schema:a.z.object({client_id:a.z.string(),connection:a.z.string(),email:a.z.string().transform(t=>t.toLowerCase()),send:a.z.enum(["link","code"]),authParams:Yc.omit({client_id:!0})})}}}},responses:{200:{description:"Status"}}}),async t=>{const e=t.req.valid("json"),{env:n}=t,{client_id:r,email:i,send:s,authParams:o}=e,c=await t.env.data.clients.get(r);if(!c)throw new z(400,{message:"Client not found"});t.set("client_id",c.id),t.set("tenant_id",c.tenant.id);const l=await n.data.logins.create(c.tenant.id,{authParams:{...o,client_id:r,username:i},expires_at:new Date(Date.now()+qc).toISOString(),...Bn(t.req)}),u=await n.data.codes.create(c.tenant.id,{code_id:ir(),code_type:"otp",login_id:l.login_id,expires_at:new Date(Date.now()+qc).toISOString()});return s==="link"?await tu(t,i,u.code_id,{...o,client_id:r}):await Vg(t,i,u.code_id),t.html("OK")}).openapi(a.createRoute({tags:["passwordless"],method:"get",path:"/verify_redirect",request:{query:a.z.object({scope:a.z.string(),response_type:a.z.nativeEnum(mn),redirect_uri:a.z.string(),state:a.z.string(),nonce:a.z.string().optional(),verification_code:a.z.string(),connection:a.z.string(),client_id:a.z.string(),email:a.z.string().transform(t=>t.toLowerCase()),audience:a.z.string().optional()})},responses:{302:{description:"Status"}}}),async t=>{const{env:e}=t,{client_id:n,email:r,verification_code:i,redirect_uri:s,state:o,scope:c,audience:l,response_type:u,nonce:p}=t.req.valid("query"),h=await Do(e,n);return t.set("client_id",h.id),t.set("tenant_id",h.tenant.id),t.set("connection","email"),ru(t,h,{client_id:n,redirect_uri:s,state:o,nonce:p,scope:c,audience:l,response_type:u},r,i)});class Ir extends z{constructor(n,r){super(n,r);ee(this,"_code");this._code=r==null?void 0:r.code}get code(){return this._code}}async function iu(t,e,n,r,i){const{env:s}=t,o=n.username;if(t.set("username",o),!o)throw new z(400,{message:"Username is required"});const c=await Kn({userAdapter:t.env.data.users,tenant_id:e.tenant.id,email:o,provider:"auth2"});if(!c){const f=be(t,{type:me.FAILED_LOGIN_INCORRECT_PASSWORD,description:"Invalid user"});throw Xe(t,t.env.data.logs.create(e.tenant.id,f)),new Ir(403,{message:"User not found",code:"USER_NOT_FOUND"})}const l=c.linked_to?await s.data.users.get(e.tenant.id,c.linked_to):c;if(!l)throw new Ir(403,{message:"User not found",code:"USER_NOT_FOUND"});t.set("connection",c.connection),t.set("user_id",l.user_id);const{password:u}=await s.data.passwords.get(e.tenant.id,c.user_id);if(!await si.compare(n.password,u)){const f=be(t,{type:me.FAILED_LOGIN_INCORRECT_PASSWORD,description:"Invalid password"});throw Xe(t,t.env.data.logs.create(e.tenant.id,f)),new Ir(403,{message:"Invalid password",code:"INVALID_PASSWORD"})}if((await s.data.logs.list(e.tenant.id,{page:0,per_page:10,include_totals:!1,q:`user_id:${l.user_id}`})).logs.filter(f=>f.type===me.FAILED_LOGIN_INCORRECT_PASSWORD&&new Date(f.date)>new Date(Date.now()-1e3*60*5)).length>=3){const f=be(t,{type:me.FAILED_LOGIN,description:"Too many failed login attempts"});throw Xe(t,t.env.data.logs.create(e.tenant.id,f)),new Ir(403,{message:"Too many failed login attempts",code:"TOO_MANY_FAILED_LOGINS"})}if(!c.email_verified&&e.email_validation==="enforced"){await nu(t,c);const f=be(t,{type:me.FAILED_LOGIN,description:"Email not verified"});throw await t.env.data.logs.create(e.tenant.id,f),new Ir(403,{message:"Email not verified",code:"EMAIL_NOT_VERIFIED"})}const y=be(t,{type:me.SUCCESS_LOGIN,description:"Successful login",strategy_type:"Username-Password-Authentication",strategy:"Username-Password-Authentication"});return Xe(t,t.env.data.logs.create(e.tenant.id,y)),Tn(t,{client:e,authParams:n,user:l,ticketAuth:i,loginSession:r})}async function wb(t,e,n,r){let i=await _n({userAdapter:t.env.data.users,tenant_id:e.tenant.id,email:n,provider:"auth2"});if(!i){if(!(await el(t.env.data.users,e.tenant.id,n)).length)return;i=await t.env.data.users.create(e.tenant.id,{user_id:`email|${oi()}`,email:n,email_verified:!1,is_social:!1,provider:"auth2",connection:"Username-Password-Authentication"})}const s=await t.env.data.logins.create(e.tenant.id,{expires_at:new Date(Date.now()+Uy).toISOString(),authParams:{client_id:e.id,username:n},...Bn(t.req)});let o=ir(),c=await t.env.data.codes.get(e.tenant.id,o,"password_reset");for(;c;)o=ir(),c=await t.env.data.codes.get(e.tenant.id,o,"password_reset");const l=await t.env.data.codes.create(e.tenant.id,{code_id:o,code_type:"password_reset",login_id:s.login_id,expires_at:new Date(Date.now()+Ly).toISOString()});await Ug(t,n,l.code_id,r)}const bb=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:a.z.union([a.z.object({credential_type:a.z.literal("http://auth0.com/oauth/grant-type/passwordless/otp"),otp:a.z.string(),client_id:a.z.string(),username:a.z.string().transform(t=>t.toLowerCase()),realm:a.z.enum(["email"]),scope:a.z.string().optional()}),a.z.object({credential_type:a.z.literal("http://auth0.com/oauth/grant-type/password-realm"),client_id:a.z.string(),username:a.z.string().transform(t=>t.toLowerCase()),password:a.z.string(),realm:a.z.enum(["Username-Password-Authentication"]),scope:a.z.string().optional()})])}}}},responses:{200:{description:"List of tenants"}}}),async t=>{const e=t.req.valid("json"),{client_id:n,username:r}=e;t.set("username",r);const i=await t.env.data.clients.get(n);if(!i)throw new z(400,{message:"Client not found"});t.set("client_id",n),t.set("tenant_id",i.tenant.id);const s=r.toLocaleLowerCase();if("otp"in e)return ru(t,i,{client_id:n,username:s},s,e.otp,!0);if("password"in e){const o=await t.env.data.logins.create(i.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:{client_id:n,username:s},...Bn(t.req)});return iu(t,i,{username:s,password:e.password,client_id:n},o,!0)}else throw new z(400,{message:"Code or password required"})});function xb(t,e){var r,i,s;if(!t||e.length===0)return!1;const n=((r=ua(t))==null?void 0:r.host)??null;if(!n)return!1;for(const o of e){let c;if(o.startsWith("http://")||o.startsWith("https://")?c=((i=ua(o))==null?void 0:i.host)??null:c=((s=ua("https://"+o))==null?void 0:s.host)??null,n===c)return!0}return!1}function ua(t){try{return new URL(t)}catch{return null}}async function kb({ctx:t,session:e,client:n,authParams:r,connection:i,login_hint:s}){const o=await t.env.data.logins.create(n.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:r,...Bn(t.req)});if(e&&s){const c=await t.env.data.users.get(n.tenant.id,e.user_id);if((c==null?void 0:c.email)===s)return Tn(t,{client:n,loginSession:o,authParams:r,user:c,sessionId:e.id})}if(i==="email"&&s){const c=ir();return await t.env.data.codes.create(n.tenant.id,{code_id:c,code_type:"otp",login_id:o.login_id,expires_at:new Date(Date.now()+Xr*1e3).toISOString()}),await tu(t,s,c,r),t.redirect(`/u/enter-code?state=${o.login_id}`)}return e?t.redirect(`/u/check-account?state=${o.login_id}`):t.redirect(`/u/enter-email?state=${o.login_id}`)}function Sb(t){if(t==="Username-Password-Authentication")return"auth2";if(t==="email")return"email";throw new z(403,{message:"Invalid realm"})}async function Ab(t,e,n,r,i){var m;const{env:s}=t;t.set("connection",i);const o=await s.data.codes.get(e,n,"ticket");if(!o||o.used_at)throw new z(403,{message:"Ticket not found"});const c=await s.data.logins.get(e,o.login_id);if(!c||!c.authParams.username)throw new z(403,{message:"Session not found"});const l=await s.data.clients.get(c.authParams.client_id);if(!l)throw new z(403,{message:"Client not found"});t.set("client_id",c.authParams.client_id),await s.data.codes.used(e,n);const u=Sb(i);let p=await _n({userAdapter:s.data.users,tenant_id:e,email:c.authParams.username,provider:u});p||(p=await s.data.users.create(e,{user_id:`email|${oi()}`,email:c.authParams.username,name:c.authParams.username,provider:"email",connection:"email",email_verified:!0,is_social:!1,last_ip:"",last_login:new Date().toISOString()})),t.set("username",p.email),t.set("user_id",p.user_id);const h=await Bg(t,{user:p,client:l,scope:r.scope,audience:r.audience});return Tn(t,{authParams:{scope:(m=c.authParams)==null?void 0:m.scope,...r},loginSession:c,sessionId:h.id,user:p,client:l})}async function zp(t,e){return`<!DOCTYPE html>
|
|
149
|
+
</html>`;return new Response(i,{headers:{"Content-Type":"text/html"}})}async function Jw(t,e,n,r,i){var m,y,f;if(!n.redirect_uri)throw new z(400,{message:"Missing redirect_uri in authParams"});const[s]=await t.env.data.keys.list();if(!s)throw new z(500,{message:"No signing key found"});if(!((m=e.addons)!=null&&m.samlp))throw new z(400,{message:`SAML Addon is not enabled for client ${e.id}`});const{recipient:o,audience:c}=e.addons.samlp,l=n.state||"";if(!o||!l||!r||!n.state)throw new z(400,{message:"Missing recipient or inResponseTo"});const u=JSON.parse(n.state),p=new URL(n.redirect_uri),h=await Zw(t,{issuer:t.env.ISSUER,audience:c||n.client_id,destination:p.toString(),inResponseTo:u.requestId,userId:((f=(y=r.app_metadata)==null?void 0:y.vimeo)==null?void 0:f.user_id)||r.user_id,email:r.email,sessionIndex:i,signature:{privateKeyPem:s.pkcs7,cert:s.cert,kid:s.kid}});return Gw(p.toString(),h,u.relayState)}async function Zw(t,e){const n=e.notBefore||new Date().toISOString(),r=e.notAfter||new Date(new Date(n).getTime()+10*60*1e3).toISOString(),i=e.issueInstant||n,s=e.sessionNotOnOrAfter||r,o=e.responseId||`_${qe()}`,c=e.assertionId||`_${qe()}`,l=[{"samlp:Response":[{"saml:Issuer":[{"#text":e.issuer}]},{"samlp:Status":[{"samlp:StatusCode":[],":@":{"@_Value":"urn:oasis:names:tc:SAML:2.0:status:Success"}}]},{"saml:Assertion":[{"saml:Issuer":[{"#text":e.issuer}]},{"saml:Subject":[{"saml:NameID":[{"#text":e.email}],":@":{"@_Format":"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"}},{"saml:SubjectConfirmation":[{"saml:SubjectConfirmationData":[],":@":{"@_InResponseTo":e.inResponseTo,"@_NotOnOrAfter":r,"@_Recipient":e.destination}}],":@":{"@_Method":"urn:oasis:names:tc:SAML:2.0:cm:bearer"}}]},{"saml:Conditions":[{"saml:AudienceRestriction":[{"saml:Audience":[{"#text":e.audience}]}]}],":@":{"@_NotBefore":n,"@_NotOnOrAfter":r}},{"saml:AuthnStatement":[{"saml:AuthnContext":[{"saml:AuthnContextClassRef":[{"#text":"urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"}]}]}],":@":{"@_AuthnInstant":i,"@_SessionIndex":e.sessionIndex,"@_SessionNotOnOrAfter":s}},{"saml:AttributeStatement":[{"saml:Attribute":[{"saml:AttributeValue":[{"#text":e.userId}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_FriendlyName":"persistent","@_Name":"id","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":e.email}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"email","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"manage-account"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"default-roles-master"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"offline_access"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"view-profile"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"uma_authorization"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}},{"saml:Attribute":[{"saml:AttributeValue":[{"#text":"manage-account-links"}],":@":{"@_xmlns:xs":"http://www.w3.org/2001/XMLSchema","@_xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","@_xsi:type":"xs:string"}}],":@":{"@_Name":"Role","@_NameFormat":"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"}}]}],":@":{"@_xmlns":"urn:oasis:names:tc:SAML:2.0:assertion","@_ID":c,"@_IssueInstant":i,"@_Version":"2.0"}}],":@":{"@_xmlns:samlp":"urn:oasis:names:tc:SAML:2.0:protocol","@_xmlns:saml":"urn:oasis:names:tc:SAML:2.0:assertion","@_Destination":e.destination,"@_ID":o,"@_InResponseTo":e.inResponseTo,"@_IssueInstant":i,"@_Version":"2.0"}}];let p=new Ww.XMLBuilder({ignoreAttributes:!1,suppressEmptyNode:!0,preserveOrder:!0}).build(l);if(e.signature){const m=await fetch(t.env.SAML_SIGN_URL,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({xmlContent:p,privateKey:e.signature.privateKeyPem,publicCert:e.signature.cert})});if(!m.ok)throw new Error(`Failed to sign SAML response: ${m.status}`);p=await m.text()}return e.encode===!1?p:btoa(p)}function Yw(){const t=new Uint8Array(32);return crypto.getRandomValues(t),gn.encode(t,{includePadding:!1})}const Ap=["sub","iss","aud","exp","nbf","iat","jti"];async function Yl(t,e){var _,w;const{authParams:n,user:r,client:i,session_id:s}=e,c=(await t.env.data.keys.list()).filter(S=>!S.revoked_at||new Date(S.revoked_at)>new Date),l=c[c.length-1];if(!(l!=null&&l.pkcs7))throw new z(500,{message:"No signing key available"});const u=Ev(l.pkcs7),p={aud:n.audience||"default",scope:n.scope||"",sub:(r==null?void 0:r.user_id)||n.client_id,iss:t.env.ISSUER,tenant_id:t.var.tenant_id,sid:s},h=r&&((_=n.scope)!=null&&_.split(" ").includes("openid"))?{aud:n.client_id,sub:r.user_id,iss:t.env.ISSUER,sid:s,nonce:n.nonce,given_name:r.given_name,family_name:r.family_name,nickname:r.nickname,picture:r.picture,locale:r.locale,name:r.name,email:r.email,email_verified:r.email_verified}:void 0;(w=t.env.hooks)!=null&&w.onExecuteCredentialsExchange&&await t.env.hooks.onExecuteCredentialsExchange({client:i,user:r,scope:n.scope||"",grant_type:""},{accessToken:{setCustomClaim:(S,N)=>{if(Ap.includes(S))throw new Error(`Cannot overwrite reserved claim '${S}'`);p[S]=N}},idToken:{setCustomClaim:(S,N)=>{if(Ap.includes(S))throw new Error(`Cannot overwrite reserved claim '${S}'`);h&&(h[S]=N)}},access:{deny:S=>{throw new z(400,{message:`Access denied: ${S}`})}}});const m={includeIssuedTimestamp:!0,expiresIn:new Fl(1,"d"),headers:{kid:l.kid}},y=await vp("RS256",u,p,m),f=h?await vp("RS256",u,h,m):void 0;return{access_token:y,refresh_token:e.refresh_token,id_token:f,token_type:"Bearer",expires_in:86400}}async function Xw(t,e){const{client:n,scope:r,audience:i=n.tenant.audience,session_id:s}=e;return await t.env.data.refreshTokens.create(n.tenant.id,{id:qe(),session_id:s,client_id:n.id,expires_at:new Date(Date.now()+Mo*1e3).toISOString(),user_id:e.user.user_id,device:{last_ip:t.req.header("x-real-ip")||"",initial_ip:t.req.header("x-real-ip")||"",last_user_agent:t.req.header("user-agent")||"",initial_user_agent:t.req.header("user-agent")||"",initial_asn:"",last_asn:""},resource_servers:[{audience:i,scopes:r}],rotating:!1})}async function Bg(t,e){const{user:n,client:r,scope:i,audience:s}=e,o=await t.env.data.sessions.create(r.tenant.id,{id:qe(),user_id:n.user_id,idle_expires_at:new Date(Date.now()+Mo*1e3).toISOString(),device:{last_ip:t.req.header("x-real-ip")||"",initial_ip:t.req.header("x-real-ip")||"",last_user_agent:t.req.header("user-agent")||"",initial_user_agent:t.req.header("user-agent")||"",initial_asn:"",last_asn:""},clients:[r.id]}),c=i!=null&&i.split(" ").includes("offline_access")?await Xw(t,{...e,session_id:o.id,scope:i,audience:s}):void 0;return{...o,refresh_token:c}}async function Tn(t,e){var h;const{authParams:n,user:r,client:i}=e,s=be(t,{type:me.SUCCESS_LOGIN,description:`Successful login for ${r.user_id}`,userId:r.user_id});if(Xe(t,t.env.data.logs.create(i.tenant.id,s)),Xe(t,t.env.data.users.update(i.tenant.id,r.user_id,{last_login:new Date().toISOString(),last_ip:t.req.header("x-real-ip")||"",login_count:r.login_count+1})),e!=null&&e.ticketAuth){if(!e.loginSession)throw new z(500,{message:"Login session not found"});const m=Yw(),y=qe(12),f=await t.env.data.codes.create(i.tenant.id,{code_id:qe(),code_type:"ticket",login_id:e.loginSession.login_id,expires_at:new Date(Date.now()+Ry).toISOString(),code_verifier:[y,m].join("|")});return t.json({login_ticket:f.code_id,co_verifier:m,co_id:y})}let o=e.refreshToken,c=e.sessionId;if(!c){const m=await Bg(t,{user:r,client:i,scope:n.scope,audience:n.audience});c=m.id,o=(h=m.refresh_token)==null?void 0:h.id}if(e.authParams.response_mode===Jt.SAML_POST)return Jw(t,e.client,e.authParams,r,c);const l=await Yl(t,{authParams:n,user:r,client:i,session_id:c,refresh_token:o}),u=new Headers({"set-cookie":Eg(i.tenant.id,c)});if(n.response_mode===Jt.WEB_MESSAGE)return t.json(l,{headers:u});if((n.response_type||mn.CODE)===mn.CODE){if(!e.loginSession)throw new z(500,{message:"Login session not found"});const m=await t.env.data.codes.create(i.tenant.id,{code_id:qe(),user_id:r.user_id,code_type:"authorization_code",login_id:e.loginSession.login_id,expires_at:new Date(Date.now()+Ty*1e3).toISOString()});u.set("location",`${n.redirect_uri}?state=${e.authParams.state}&code=${m.code_id}`)}return new Response("Redirecting",{status:302,headers:u})}function Qw(t){return async(e,n)=>{if(!n.email||!n.email_verified)return t.users.create(e,n);const r=await Zs({userAdapter:t.users,tenant_id:e,email:n.email});return r?(await t.users.create(e,{...n,linked_to:r.user_id}),r):t.users.create(e,n)}}async function Tg(t,e,n){for await(const r of e)if(!(await fetch(r.url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).ok){const s=be(t,{type:me.FAILED_LOGIN_INCORRECT_PASSWORD,description:"Invalid password"});await n.logs.create(t.var.tenant_id,s)}}function eb(t,e){return async(n,r)=>{const{hooks:i}=await e.hooks.list(n);return await Tg(t,i,{tenant_id:n,user:r,trigger_id:"post-user-registration"}),r}}function tb(t,e){return async(n,r)=>{const{hooks:i}=await e.hooks.list(n,{q:"trigger_id:pre-user-signup",page:0,per_page:100,include_totals:!1});await Tg(t,i,{tenant_id:n,email:r,trigger_id:"pre-user-signup"})}}function nb(t,e){return async(n,r)=>{let i=await Qw(e)(n,r);return await eb(t,e)(n,i),i}}async function Pg(t,e,n,r){if(e.disable_sign_ups&&!await Zs({userAdapter:t.env.data.users,tenant_id:e.tenant.id,email:r})){const s=be(t,{type:me.FAILED_SIGNUP,description:"Public signup is disabled"});throw await t.env.data.logs.create(e.tenant.id,s),new z(400,{message:"Signups are disabled for this client"})}await tb(t,n)(t.var.tenant_id||"",r)}function rb(t,e){return{...e,users:{...e.users,create:nb(t,e)}}}async function ib(t,e,n,r){if(!r.state)throw new z(400,{message:"State not found"});const i=e.connections.find(l=>l.name===n);if(!i){t.set("client_id",e.id);const l=be(t,{type:me.FAILED_LOGIN,description:"Connection not found"});throw await t.env.data.logs.create(e.tenant.id,l),new z(403,{message:"Connection Not Found"})}let s=await t.env.data.logins.get(e.tenant.id,r.state);s||(s=await t.env.data.logins.create(e.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:r,...Bn(t.req)}));const c=await kg(t,i.strategy).getRedirect(t,i);return await t.env.data.codes.create(e.tenant.id,{login_id:s.login_id,code_id:c.code,code_type:"oauth2_state",connection_id:i.id,code_verifier:c.codeVerifier,expires_at:new Date(Date.now()+Py*1e3).toISOString()}),t.redirect(c.redirectUrl)}async function Ep(t,{code:e,state:n}){var f;const{env:r}=t,i=await r.data.codes.get(t.var.tenant_id||"",n,"oauth2_state");if(!i||!i.connection_id)throw new z(403,{message:"State not found"});const s=await r.data.logins.get(t.var.tenant_id||"",i.login_id);if(!s)throw new z(403,{message:"Session not found"});const o=await Do(r,s.authParams.client_id);t.set("client_id",o.id),t.set("tenant_id",o.tenant.id);const c=o.connections.find(_=>_.id===i.connection_id);if(!c){const _=be(t,{type:me.FAILED_LOGIN,description:"Connection not found"});throw await r.data.logs.create(o.tenant.id,_),new z(403,{message:"Connection not found"})}if(t.set("connection",c.name),!s.authParams.redirect_uri){const _=be(t,{type:me.FAILED_LOGIN,description:"Redirect URI not defined"});throw await r.data.logs.create(o.tenant.id,_),new z(403,{message:"Redirect URI not defined"})}if(!Ho(s.authParams.redirect_uri,o.callbacks||[],{allowPathWildcards:!0})){const _=`Invalid redirect URI - ${s.authParams.redirect_uri}`,w=be(t,{type:me.FAILED_LOGIN,description:_});throw await r.data.logs.create(o.tenant.id,w),new z(403,{message:_})}const u=await kg(t,c.strategy).validateAuthorizationCodeAndGetUser(t,c,e,i.code_verifier),{sub:p,...h}=u;t.set("user_id",p);const m=((f=u.email)==null?void 0:f.toLocaleLowerCase())||`${c.name}.${p}@${new URL(t.env.ISSUER).hostname}`;t.set("username",m);let y=await _n({userAdapter:r.data.users,tenant_id:o.tenant.id,email:m,provider:c.name});if(!y){try{await Pg(t,o,t.env.data,m)}catch(_){const w=_;throw new z(500,{message:`Failed to run preUserSignupHook: ${w.message}`})}y=await r.data.users.create(o.tenant.id,{user_id:`${c.name}|${p}`,email:m,name:m,provider:c.name,connection:c.name,email_verified:!0,last_ip:"",is_social:!0,last_login:new Date().toISOString(),profileData:JSON.stringify(h)}),t.set("user_id",y.user_id)}return Tn(t,{client:o,authParams:s.authParams,loginSession:s,user:y})}async function Ip(t,e,n,r,i,s){const o=await t.env.data.codes.get(t.var.tenant_id||"",e,"oauth2_state");if(!o)throw new z(400,{message:"State not found"});const c=await t.env.data.logins.get(t.var.tenant_id,o.login_id);if(!c)throw new z(400,{message:"Login not found"});const{redirect_uri:l}=c.authParams;if(!l)throw new z(400,{message:"Redirect uri not found"});const u=be(t,{type:me.FAILED_LOGIN,description:`Failed connection login: ${i} ${n}, ${r}`});Xe(t,t.env.data.logs.create(t.var.tenant_id,u));const p=new URL(l);return Oy(p,{error:n,error_description:r,error_reason:s,error_code:i,state:c.authParams.state}),t.redirect(`${At(t.env)}enter-email?state=${c.login_id}&error=${n}`)}const sb=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"get",path:"/",request:{query:a.z.object({state:a.z.string(),code:a.z.string().optional(),scope:a.z.string().optional(),hd:a.z.string().optional(),error:a.z.string().optional(),error_description:a.z.string().optional(),error_code:a.z.string().optional(),error_reason:a.z.string().optional()})},responses:{302:{description:"Redirect to the client's redirect uri"}}}),async t=>{const{state:e,code:n,error:r,error_description:i,error_code:s,error_reason:o}=t.req.valid("query");if(r)return Ip(t,e,r,i,s,o);if(!n)throw new z(400,{message:"Code is required"});return Ep(t,{code:n,state:e})}).openapi(a.createRoute({tags:["oauth2"],method:"post",path:"/",request:{body:{content:{"application/x-www-form-urlencoded":{schema:a.z.object({state:a.z.string(),code:a.z.string().optional(),scope:a.z.string().optional(),hd:a.z.string().optional(),error:a.z.string().optional(),error_description:a.z.string().optional(),error_code:a.z.string().optional(),error_reason:a.z.string().optional()})}}}},responses:{302:{description:"Redirect to the client's redirect uri"}}}),async t=>{const{state:e,code:n,error:r,error_description:i,error_code:s,error_reason:o}=t.req.valid("form");if(r)return Ip(t,e,r,i,s,o);if(!n)throw new z(400,{message:"Code is required"});return Ep(t,{code:n,state:e})}),ob=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"get",path:"/",request:{query:a.z.object({client_id:a.z.string(),returnTo:a.z.string().optional()}),header:a.z.object({cookie:a.z.string().optional()})},responses:{302:{description:"Log the user out"}}}),async t=>{const{client_id:e,returnTo:n}=t.req.valid("query"),r=await t.env.data.clients.get(e);if(!r)return t.text("OK");const i=await t.env.data.clients.get("DEFAULT_CLIENT");t.set("client_id",e),t.set("tenant_id",r.tenant.id);const s=n||t.req.header("referer");if(!s)return t.text("OK");if(!Ho(s,[...r.allowed_logout_urls||[],...(i==null?void 0:i.allowed_logout_urls)||[]],{allowPathWildcards:!0}))throw new z(400,{message:"Invalid redirect uri"});const o=t.req.header("cookie");if(o){const l=Ag(r.tenant.id,o);if(l){const u=await t.env.data.sessions.get(r.tenant.id,l);if(u){const p=await t.env.data.users.get(r.tenant.id,u.user_id);p&&(t.set("user_id",p.user_id),t.set("connection",p.connection))}await t.env.data.sessions.remove(r.tenant.id,l)}}const c=be(t,{type:me.SUCCESS_LOGOUT,description:"User successfully logged out"});return await t.env.data.logs.create(r.tenant.id,c),new Response("Redirecting",{status:302,headers:{"set-cookie":Nv(r.tenant.id),location:s}})}),Cp=a.z.object({sub:a.z.string(),email:a.z.string().optional(),family_name:a.z.string().optional(),given_name:a.z.string().optional(),email_verified:a.z.boolean()}),ab=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"get",path:"/",request:{},security:[{Bearer:["openid"]}],responses:{200:{content:{"application/json":{schema:Cp}},description:"Userinfo"}}}),async t=>{if(!t.var.user)throw new z(404,{message:"User not found"});const e=await t.env.data.users.get(t.var.user.tenant_id,t.var.user.sub);if(!e)throw new z(404,{message:"User not found"});return t.json(Cp.parse({...e,sub:e.user_id}))}),cb=new a.OpenAPIHono().openapi(a.createRoute({tags:["well known"],method:"get",path:"/jwks.json",request:{},responses:{200:{content:{"application/json":{schema:sf}},description:"List of tenants"}}}),async t=>{const e=await t.env.data.keys.list(),n=await Promise.all(e.map(async r=>{const s=await new Dl(r.cert).publicKey.export(),o=await crypto.subtle.exportKey("jwk",s);return Xc.parse({...o,kid:r.kid})}));return t.json({keys:n},{headers:{"access-control-allow-origin":"*","access-control-allow-method":"GET","cache-control":`public, max-age=${Ti}, stale-while-revalidate=${Ti*2}, stale-if-error=86400`}})}).openapi(a.createRoute({tags:["well known"],method:"get",path:"/openid-configuration",request:{},responses:{200:{content:{"application/json":{schema:ba}},description:"List of tenants"}}}),async t=>{const e=ba.parse({issuer:pv(t.env),authorization_endpoint:`${Ne(t.env)}authorize`,token_endpoint:`${Ne(t.env)}oauth/token`,device_authorization_endpoint:`${Ne(t.env)}oauth/device/code`,userinfo_endpoint:`${Ne(t.env)}userinfo`,mfa_challenge_endpoint:`${Ne(t.env)}mfa/challenge`,jwks_uri:`${Ne(t.env)}.well-known/jwks.json`,registration_endpoint:`${Ne(t.env)}oidc/register`,revocation_endpoint:`${Ne(t.env)}oauth/revoke`,scopes_supported:["openid","profile","offline_access","name","given_name","family_name","nickname","email","email_verified","picture","created_at","identities","phone","address"],response_types_supported:["code","token","id_token","code token","code id_token","token id_token","code token id_token"],code_challenge_methods_supported:["S256","plain"],response_modes_supported:["query","fragment","form_post"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],token_endpoint_auth_methods_supported:["client_secret_basic","client_secret_post"],claims_supported:["aud","auth_time","created_at","email","email_verified","exp","family_name","given_name","iat","identities","iss","name","nickname","phone_number","picture","sub"],request_uri_parameter_supported:!1,request_parameter_supported:!1,token_endpoint_auth_signing_alg_values_supported:["RS256","RS384","PS256"]});return t.json(e,{headers:{"access-control-allow-origin":"*","access-control-allow-method":"GET","cache-control":`public, max-age=${Ti}, stale-while-revalidate=${Ti*2}, stale-if-error=86400`}})});function Fi(t,e){if(!t||!e||t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t.charCodeAt(r)^e.charCodeAt(r);return n===0}const Rg=a.z.object({grant_type:a.z.literal("client_credentials"),scope:a.z.string().optional(),client_secret:a.z.string(),client_id:a.z.string(),audience:a.z.string().optional()});async function lb(t,e){const n=await t.env.data.clients.get(e.client_id);if(!n)throw new z(403,{message:"Invalid client credentials"});if(n.client_secret&&!Fi(n.client_secret,e.client_secret))throw new z(403,{message:"Invalid client credentials"});const r={client_id:n.id,scope:e.scope,audience:e.audience},i=await Yl(t,{authParams:r,client:n});return t.json(i)}const ub=a.z.object({grant_type:a.z.literal("authorization_code"),client_id:a.z.string(),code:a.z.string(),redirect_uri:a.z.string().optional(),client_secret:a.z.string().optional(),code_verifier:a.z.string().optional()}).refine(t=>"client_secret"in t&&!("code_verifier"in t)||!("client_secret"in t)&&"code_verifier"in t,{message:"Must provide either client_secret (standard flow) or code_verifier/code_verifier_mode (PKCE flow), but not both"});async function db(t,e){const n=await t.env.data.clients.get(e.client_id);if(!n)throw new z(403,{message:"Client not found"});const r=await t.env.data.codes.get(n.tenant.id,e.code,"authorization_code");if(!r||!r.user_id)throw new z(403,{message:"Invalid client credentials"});if(new Date(r.expires_at)<new Date)throw new z(403,{message:"Code expired"});if(r.used_at)throw new z(403,{message:"Code already used"});const i=await t.env.data.logins.get(n.tenant.id,r.login_id);if(!i)throw new z(403,{message:"Invalid login"});if("client_secret"in e){const o=await t.env.data.clients.get("DEFAULT_CLIENT");if(!Fi(n.client_secret,e.client_secret)&&!Fi(o==null?void 0:o.client_secret,e.client_secret))throw new z(403,{message:"Invalid client credentials"})}else if("code_verifier"in e&&typeof e.code_verifier=="string"&&"code_challenge_method"in i.authParams&&typeof i.authParams.code_challenge_method=="string"){const o=await Iv(e.code_verifier,i.authParams.code_challenge_method);if(!Fi(o,i.authParams.code_challenge||""))throw new z(403,{message:"Invalid client credentials"})}if(i.authParams.redirect_uri&&i.authParams.redirect_uri!==e.redirect_uri)throw new z(403,{message:"Invalid redirect uri"});const s=await t.env.data.users.get(n.tenant.id,r.user_id);if(!s)throw new z(403,{message:"User not found"});return await t.env.data.codes.used(n.tenant.id,e.code),Tn(t,{user:s,client:n,loginSession:i,authParams:{...i.authParams,response_mode:Jt.WEB_MESSAGE}})}const pb=a.z.object({grant_type:a.z.literal("refresh_token"),client_id:a.z.string(),redirect_uri:a.z.string().optional(),refresh_token:a.z.string()});async function fb(t,e){const n=await t.env.data.clients.get(e.client_id);if(!n)throw new z(403,{message:"Client not found"});const r=await t.env.data.refreshTokens.get(n.tenant.id,e.refresh_token);if(r){if(r.expires_at&&new Date(r.expires_at)<new Date||r.idle_expires_at&&new Date(r.idle_expires_at)<new Date)throw new z(403,{message:JSON.stringify({error:"invalid_grant",error_description:"Refresh token has expired"})})}else throw new z(403,{message:JSON.stringify({error:"invalid_grant",error_description:"Invalid refresh token"})});const i=await t.env.data.users.get(n.tenant.id,r.user_id);if(!i)throw new z(403,{message:"User not found"});const s=r.resource_servers[0];if(r.idle_expires_at){const o=new Date(Date.now()+2592e6);await t.env.data.refreshTokens.update(n.tenant.id,r.id,{idle_expires_at:o.toISOString(),last_exchanged_at:new Date().toISOString(),device:{...r.device,last_ip:t.req.header["x-real-ip"]||"",last_user_agent:t.req.header["user-agent"]||""}})}return Tn(t,{user:i,client:n,refreshToken:r.id,sessionId:r.session_id,authParams:{client_id:n.id,audience:s==null?void 0:s.audience,scope:s==null?void 0:s.scopes,response_mode:Jt.WEB_MESSAGE}})}const Np=a.z.object({client_id:a.z.string().optional(),client_secret:a.z.string().optional()}),hb=a.z.union([Rg.extend(Np.shape),a.z.object({grant_type:a.z.literal("authorization_code"),client_id:a.z.string(),code:a.z.string(),redirect_uri:a.z.string(),code_verifier:a.z.string().min(43).max(128)}),a.z.object({grant_type:a.z.literal("authorization_code"),code:a.z.string(),redirect_uri:a.z.string().optional(),...Np.shape}),a.z.object({grant_type:a.z.literal("refresh_token"),client_id:a.z.string(),refresh_token:a.z.string(),redirect_uri:a.z.string().optional()})]);function gb(t){if(!t)return{};const[e,n]=t.split(" ");if((e==null?void 0:e.toLowerCase())==="basic"&&n){const[r,i]=atob(n).split(":");return{client_id:r,client_secret:i}}return{}}const mb=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth2"],method:"post",path:"/",request:{body:{content:{"application/x-www-form-urlencoded":{schema:hb}}}},responses:{200:{content:{"application/json":{schema:df}},description:"Tokens"}}}),async t=>{const e=t.req.valid("form"),n=gb(t.req.header("Authorization")),r={...e,...n};if(!r.client_id)throw new z(400,{message:"client_id is required"});switch(e.grant_type){case jr.AuthorizationCode:return db(t,ub.parse(r));case jr.ClientCredential:return lb(t,Rg.parse(r));case jr.RefreshToken:return fb(t,pb.parse(r));default:throw new z(400,{message:"Not implemented"})}});var Xl={exports:{}};const Ql=[{id:0,value:"Too weak",minDiversity:0,minLength:0},{id:1,value:"Weak",minDiversity:2,minLength:6},{id:2,value:"Medium",minDiversity:4,minLength:8},{id:3,value:"Strong",minDiversity:4,minLength:10}],Lg=(t,e=Ql,n="!\"#$%&'()*+,-./:;<=>?@[\\\\\\]^_`{|}~")=>{let r=t||"";e[0].minDiversity=0,e[0].minLength=0;const i=[{regex:"[a-z]",message:"lowercase"},{regex:"[A-Z]",message:"uppercase"},{regex:"[0-9]",message:"number"}];n&&i.push({regex:`[${n}]`,message:"symbol"});let s={};s.contains=i.filter(c=>new RegExp(`${c.regex}`).test(r)).map(c=>c.message),s.length=r.length;let o=e.filter(c=>s.contains.length>=c.minDiversity).filter(c=>s.length>=c.minLength).sort((c,l)=>l.id-c.id).map(c=>({id:c.id,value:c.value}));return Object.assign(s,o[0]),s};Xl.exports={passwordStrength:Lg,defaultOptions:Ql};var _b=Xl.exports.passwordStrength=Lg;Xl.exports.defaultOptions=Ql;function eu(t){return _b(t).id<2?!1:t.length>=8&&/[a-z]/.test(t)&&/[A-Z]/.test(t)&&/[0-9]/.test(t)&&/[^A-Za-z0-9]/.test(t)}async function Ko(t,e){var i;const n=await t.env.data.emailProviders.get(t.var.tenant_id)||(t.env.DEFAULT_TENANT_ID?await t.env.data.emailProviders.get(t.env.DEFAULT_TENANT_ID):null);if(!n)throw new z(500,{message:"Email provider not found"});const r=(i=t.env.emailProviders)==null?void 0:i[n.name];if(!r)throw new z(500,{message:"Email provider not found"});await r({emailProvider:n,...e,from:n.default_from_address||`login@${t.env.ISSUER}`})}async function Ug(t,e,n,r){const i=await t.env.data.tenants.get(t.var.tenant_id);if(!i)throw new z(500,{message:"Tenant not found"});const s=`${At(t.env)}reset-password?state=${r}&code=${n}`,o={vendorName:i.name,lng:i.language||"en"};await Ko(t,{to:e,subject:"Reset your password",html:`Click here to reset your password: ${At(t.env)}reset-password?state=${r}&code=${n}`,template:"auth-password-reset",data:{vendorName:i.name,logo:i.logo||"",passwordResetUrl:s,supportUrl:i.support_url||"https://support.sesamy.com",buttonColor:i.primary_color||"#7d68f4",passwordResetTitle:fe("password_reset_title",o),resetPasswordEmailClickToReset:fe("reset_password_email_click_to_reset",o),resetPasswordEmailReset:fe("reset_password_email_reset",o),supportInfo:fe("support_info",o),contactUs:fe("contact_us",o),copyright:fe("copyright",o)}})}async function Vg(t,e,n){const r=await t.env.data.tenants.get(t.var.tenant_id);if(!r)throw new z(500,{message:"Tenant not found"});const i={vendorName:r.name,code:n,lng:r.language||"en"};await Ko(t,{to:e,subject:fe("code_email_subject",i),html:`Click here to validate your email: ${At(t.env)}validate-email`,template:"auth-link",data:{code:n,vendorName:r.name,logo:r.logo||"",supportUrl:r.support_url||"",magicLink:`${Ne(t.env)}passwordless/verify_redirect?ticket=${n}`,buttonColor:r.primary_color||"",welcomeToYourAccount:fe("welcome_to_your_account",i),linkEmailClickToLogin:fe("link_email_click_to_login",i),linkEmailLogin:fe("link_email_login",i),linkEmailOrEnterCode:fe("link_email_or_enter_code",i),codeValid30Mins:fe("code_valid_30_minutes",i),supportInfo:fe("support_info",i),contactUs:fe("contact_us",i),copyright:fe("copyright",i)}});const s=be(t,{type:me.CODE_LINK_SENT,description:e});Xe(t,t.env.data.logs.create(r.id,s))}async function tu(t,e,n,r){const i=await t.env.data.tenants.get(t.var.tenant_id);if(!i)throw new z(500,{message:"Tenant not found"});if(!r.redirect_uri)throw new z(400,{message:"redirect_uri is required"});const s=new URL(Ne(t.env));s.pathname="passwordless/verify_redirect",s.searchParams.set("verification_code",n),s.searchParams.set("connection","email"),s.searchParams.set("client_id",r.client_id),s.searchParams.set("redirect_uri",r.redirect_uri),s.searchParams.set("email",e),r.response_type&&s.searchParams.set("response_type",r.response_type),r.scope&&s.searchParams.set("scope",r.scope),r.state&&s.searchParams.set("state",r.state),r.nonce&&s.searchParams.set("nonce",r.nonce),r.code_challenge&&s.searchParams.set("code_challenge",r.code_challenge),r.code_challenge_method&&s.searchParams.set("code_challenge_method",r.code_challenge_method),r.audience&&s.searchParams.set("audience",r.audience);const o={vendorName:i.name,code:n,lng:i.language||"en"};await Ko(t,{to:e,subject:fe("code_email_subject",o),html:`Click here to validate your email: ${At(t.env)}validate-email`,template:"auth-link",data:{code:n,vendorName:i.name,logo:i.logo||"",supportUrl:i.support_url||"",magicLink:s.toString(),buttonColor:i.primary_color||"",welcomeToYourAccount:fe("welcome_to_your_account",o),linkEmailClickToLogin:fe("link_email_click_to_login",o),linkEmailLogin:fe("link_email_login",o),linkEmailOrEnterCode:fe("link_email_or_enter_code",o),codeValid30Mins:fe("code_valid_30_minutes",o),supportInfo:fe("support_info",o),contactUs:fe("contact_us",o),copyright:fe("copyright",o)}});const c=be(t,{type:me.CODE_LINK_SENT,description:e});Xe(t,t.env.data.logs.create(i.id,c))}async function nu(t,e){const n=await t.env.data.tenants.get(t.var.tenant_id);if(!n)throw new z(500,{message:"Tenant not found"});const r={vendorName:n.name,lng:n.language||"en"};await Ko(t,{to:e.email,subject:"Validate your email address",html:`Click here to validate your email: ${At(t.env)}validate-email`,template:"auth-verify-email",data:{vendorName:n.name,logo:n.logo||"",emailValidationUrl:`${At(t.env)}validate-email`,supportUrl:n.support_url||"https://support.sesamy.com",buttonColor:n.primary_color||"#7d68f4",welcomeToYourAccount:fe("welcome_to_your_account",r),verifyEmailVerify:fe("verify_email_verify",r),supportInfo:fe("support_info",r),contactUs:fe("contact_us",r),copyright:fe("copyright",r)}})}const yb=new a.OpenAPIHono().openapi(a.createRoute({tags:["dbconnections"],method:"post",path:"/signup",request:{body:{content:{"application/json":{schema:a.z.object({client_id:a.z.string(),connection:a.z.literal("Username-Password-Authentication"),email:a.z.string().transform(t=>t.toLowerCase()),password:a.z.string()})}}}},responses:{200:{content:{"application/json":{schema:a.z.object({_id:a.z.string(),email:a.z.string(),email_verified:a.z.boolean(),app_metadata:a.z.object({}),user_metadata:a.z.object({})})}},description:"Created user"}}}),async t=>{const{email:e,password:n,client_id:r}=t.req.valid("json"),i=await t.env.data.clients.get(r);if(!i)throw new z(400,{message:"Client not found"});if(t.set("client_id",i.id),t.set("tenant_id",i.tenant.id),!eu(n))throw new z(400,{message:"Password does not meet the requirements"});if(await _n({userAdapter:t.env.data.users,tenant_id:i.tenant.id,email:e,provider:"auth2"}))throw new z(400,{message:"Invalid sign up"});const o=await t.env.data.users.create(i.tenant.id,{user_id:`auth2|${oi()}`,email:e,email_verified:!1,provider:"auth2",connection:"Username-Password-Authentication",is_social:!1});t.set("user_id",o.user_id),t.set("username",o.email),t.set("connection",o.connection);const c=await si.hash(n,10);await t.env.data.passwords.create(i.tenant.id,{user_id:o.user_id,password:c,algorithm:"bcrypt"}),await nu(t,o);const l=be(t,{type:me.SUCCESS_SIGNUP,description:"Successful signup"});return await t.env.data.logs.create(i.tenant.id,l),t.json({_id:o.user_id,email:o.email,email_verified:!1,app_metadata:{},user_metadata:{}})}).openapi(a.createRoute({tags:["dbconnections"],method:"post",path:"/change_password",request:{body:{content:{"application/json":{schema:a.z.object({client_id:a.z.string(),connection:a.z.literal("Username-Password-Authentication"),email:a.z.string().transform(t=>t.toLowerCase())})}}}},responses:{200:{description:"Redirect to the client's redirect uri"}}}),async t=>{const{email:e,client_id:n}=t.req.valid("json"),r=await t.env.data.clients.get(n);if(!r)throw new z(400,{message:"Client not found"});if(t.set("client_id",r.id),t.set("tenant_id",r.tenant.id),!await Kn({userAdapter:t.env.data.users,tenant_id:r.tenant.id,email:e,provider:"auth2"}))return t.html("If an account with that email exists, we've sent instructions to reset your password.");const s={client_id:n,username:e},o=await t.env.data.logins.create(r.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:s,...Bn(t.req)});return await Ug(t,e,o.login_id,o.authParams.state),t.html("If an account with that email exists, we've sent instructions to reset your password.")});function ir(){const t="1234567890";let e="";for(let n=0;n<6;n+=1)e+=t[Math.floor(Math.random()*10)];return e.toString()}async function ru(t,e,n,r,i,s){const{env:o}=t,c=await o.data.codes.get(e.tenant.id,i,"otp");if(!c)throw new z(400,{message:"Code not found or expired"});if(c.expires_at<new Date().toISOString())throw new z(400,{message:"Code expired"});if(c.used_at)throw new z(400,{message:"Code already used"});const l=await o.data.logins.get(e.tenant.id,c.login_id);if(!l||l.authParams.username!==r)throw new z(400,{message:"Code not found or expired"});const u=Bn(t.req);if(l.ip!==u.ip)return t.redirect(`${At(t.env)}invalid-session?state=${l.login_id}`);if(n.redirect_uri&&!Ho(n.redirect_uri,e.callbacks,{allowPathWildcards:!0}))throw new z(400,{message:`Invalid redirect URI - ${n.redirect_uri}`});const p=await _n({userAdapter:o.data.users,tenant_id:e.tenant.id,email:r,provider:"email"});if(!p)throw new z(400,{message:"User not found"});return await o.data.codes.used(e.tenant.id,i),Tn(t,{user:p,client:e,loginSession:l,authParams:n,ticketAuth:s})}const vb=new a.OpenAPIHono().openapi(a.createRoute({tags:["passwordless"],method:"post",path:"/start",request:{body:{content:{"application/json":{schema:a.z.object({client_id:a.z.string(),connection:a.z.string(),email:a.z.string().transform(t=>t.toLowerCase()),send:a.z.enum(["link","code"]),authParams:Yc.omit({client_id:!0})})}}}},responses:{200:{description:"Status"}}}),async t=>{const e=t.req.valid("json"),{env:n}=t,{client_id:r,email:i,send:s,authParams:o}=e,c=await t.env.data.clients.get(r);if(!c)throw new z(400,{message:"Client not found"});t.set("client_id",c.id),t.set("tenant_id",c.tenant.id);const l=await n.data.logins.create(c.tenant.id,{authParams:{...o,client_id:r,username:i},expires_at:new Date(Date.now()+qc).toISOString(),...Bn(t.req)}),u=await n.data.codes.create(c.tenant.id,{code_id:ir(),code_type:"otp",login_id:l.login_id,expires_at:new Date(Date.now()+qc).toISOString()});return s==="link"?await tu(t,i,u.code_id,{...o,client_id:r}):await Vg(t,i,u.code_id),t.html("OK")}).openapi(a.createRoute({tags:["passwordless"],method:"get",path:"/verify_redirect",request:{query:a.z.object({scope:a.z.string(),response_type:a.z.nativeEnum(mn),redirect_uri:a.z.string(),state:a.z.string(),nonce:a.z.string().optional(),verification_code:a.z.string(),connection:a.z.string(),client_id:a.z.string(),email:a.z.string().transform(t=>t.toLowerCase()),audience:a.z.string().optional()})},responses:{302:{description:"Status"}}}),async t=>{const{env:e}=t,{client_id:n,email:r,verification_code:i,redirect_uri:s,state:o,scope:c,audience:l,response_type:u,nonce:p}=t.req.valid("query"),h=await Do(e,n);return t.set("client_id",h.id),t.set("tenant_id",h.tenant.id),t.set("connection","email"),ru(t,h,{client_id:n,redirect_uri:s,state:o,nonce:p,scope:c,audience:l,response_type:u},r,i)});class Ir extends z{constructor(n,r){super(n,r);ee(this,"_code");this._code=r==null?void 0:r.code}get code(){return this._code}}async function iu(t,e,n,r,i){const{env:s}=t,o=n.username;if(t.set("username",o),!o)throw new z(400,{message:"Username is required"});const c=await Kn({userAdapter:t.env.data.users,tenant_id:e.tenant.id,email:o,provider:"auth2"});if(!c){const f=be(t,{type:me.FAILED_LOGIN_INCORRECT_PASSWORD,description:"Invalid user"});throw Xe(t,t.env.data.logs.create(e.tenant.id,f)),new Ir(403,{message:"User not found",code:"USER_NOT_FOUND"})}const l=c.linked_to?await s.data.users.get(e.tenant.id,c.linked_to):c;if(!l)throw new Ir(403,{message:"User not found",code:"USER_NOT_FOUND"});t.set("connection",c.connection),t.set("user_id",l.user_id);const{password:u}=await s.data.passwords.get(e.tenant.id,c.user_id);if(!await si.compare(n.password,u)){const f=be(t,{type:me.FAILED_LOGIN_INCORRECT_PASSWORD,description:"Invalid password"});throw Xe(t,t.env.data.logs.create(e.tenant.id,f)),new Ir(403,{message:"Invalid password",code:"INVALID_PASSWORD"})}if((await s.data.logs.list(e.tenant.id,{page:0,per_page:10,include_totals:!1,q:`user_id:${l.user_id}`})).logs.filter(f=>f.type===me.FAILED_LOGIN_INCORRECT_PASSWORD&&new Date(f.date)>new Date(Date.now()-1e3*60*5)).length>=3){const f=be(t,{type:me.FAILED_LOGIN,description:"Too many failed login attempts"});throw Xe(t,t.env.data.logs.create(e.tenant.id,f)),new Ir(403,{message:"Too many failed login attempts",code:"TOO_MANY_FAILED_LOGINS"})}if(!c.email_verified&&e.email_validation==="enforced"){await nu(t,c);const f=be(t,{type:me.FAILED_LOGIN,description:"Email not verified"});throw await t.env.data.logs.create(e.tenant.id,f),new Ir(403,{message:"Email not verified",code:"EMAIL_NOT_VERIFIED"})}const y=be(t,{type:me.SUCCESS_LOGIN,description:"Successful login",strategy_type:"Username-Password-Authentication",strategy:"Username-Password-Authentication"});return Xe(t,t.env.data.logs.create(e.tenant.id,y)),Tn(t,{client:e,authParams:n,user:l,ticketAuth:i,loginSession:r})}async function wb(t,e,n,r){let i=await _n({userAdapter:t.env.data.users,tenant_id:e.tenant.id,email:n,provider:"auth2"});if(!i){if(!(await el(t.env.data.users,e.tenant.id,n)).length)return;i=await t.env.data.users.create(e.tenant.id,{user_id:`email|${oi()}`,email:n,email_verified:!1,is_social:!1,provider:"auth2",connection:"Username-Password-Authentication"})}const s=await t.env.data.logins.create(e.tenant.id,{expires_at:new Date(Date.now()+Uy).toISOString(),authParams:{client_id:e.id,username:n},...Bn(t.req)});let o=ir(),c=await t.env.data.codes.get(e.tenant.id,o,"password_reset");for(;c;)o=ir(),c=await t.env.data.codes.get(e.tenant.id,o,"password_reset");const l=await t.env.data.codes.create(e.tenant.id,{code_id:o,code_type:"password_reset",login_id:s.login_id,expires_at:new Date(Date.now()+Ly).toISOString()});await Ug(t,n,l.code_id,r)}const bb=new a.OpenAPIHono().openapi(a.createRoute({tags:["oauth"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:a.z.union([a.z.object({credential_type:a.z.literal("http://auth0.com/oauth/grant-type/passwordless/otp"),otp:a.z.string(),client_id:a.z.string(),username:a.z.string().transform(t=>t.toLowerCase()),realm:a.z.enum(["email"]),scope:a.z.string().optional()}),a.z.object({credential_type:a.z.literal("http://auth0.com/oauth/grant-type/password-realm"),client_id:a.z.string(),username:a.z.string().transform(t=>t.toLowerCase()),password:a.z.string(),realm:a.z.enum(["Username-Password-Authentication"]),scope:a.z.string().optional()})])}}}},responses:{200:{description:"List of tenants"}}}),async t=>{const e=t.req.valid("json"),{client_id:n,username:r}=e;t.set("username",r);const i=await t.env.data.clients.get(n);if(!i)throw new z(400,{message:"Client not found"});t.set("client_id",n),t.set("tenant_id",i.tenant.id);const s=r.toLocaleLowerCase();if("otp"in e)return ru(t,i,{client_id:n,username:s},s,e.otp,!0);if("password"in e){const o=await t.env.data.logins.create(i.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:{client_id:n,username:s},...Bn(t.req)});return iu(t,i,{username:s,password:e.password,client_id:n},o,!0)}else throw new z(400,{message:"Code or password required"})});function xb(t,e){var r,i,s;if(!t||e.length===0)return!1;const n=((r=ua(t))==null?void 0:r.host)??null;if(!n)return!1;for(const o of e){let c;if(o.startsWith("http://")||o.startsWith("https://")?c=((i=ua(o))==null?void 0:i.host)??null:c=((s=ua("https://"+o))==null?void 0:s.host)??null,n===c)return!0}return!1}function ua(t){try{return new URL(t)}catch{return null}}async function kb({ctx:t,session:e,client:n,authParams:r,connection:i,login_hint:s}){const o=await t.env.data.logins.create(n.tenant.id,{expires_at:new Date(Date.now()+Xr*1e3).toISOString(),authParams:r,...Bn(t.req)});if(e&&s){const c=await t.env.data.users.get(n.tenant.id,e.user_id);if((c==null?void 0:c.email)===s)return Tn(t,{client:n,loginSession:o,authParams:r,user:c,sessionId:e.id})}if(i==="email"&&s){const c=ir();return await t.env.data.codes.create(n.tenant.id,{code_id:c,code_type:"otp",login_id:o.login_id,expires_at:new Date(Date.now()+Xr*1e3).toISOString()}),await tu(t,s,c,r),t.redirect(`/u/enter-code?state=${o.login_id}`)}return e?t.redirect(`/u/check-account?state=${o.login_id}`):t.redirect(`/u/enter-email?state=${o.login_id}`)}function Sb(t){if(t==="Username-Password-Authentication")return"auth2";if(t==="email")return"email";throw new z(403,{message:"Invalid realm"})}async function Ab(t,e,n,r,i){var m;const{env:s}=t;t.set("connection",i);const o=await s.data.codes.get(e,n,"ticket");if(!o||o.used_at)throw new z(403,{message:"Ticket not found"});const c=await s.data.logins.get(e,o.login_id);if(!c||!c.authParams.username)throw new z(403,{message:"Session not found"});const l=await s.data.clients.get(c.authParams.client_id);if(!l)throw new z(403,{message:"Client not found"});t.set("client_id",c.authParams.client_id),await s.data.codes.used(e,n);const u=Sb(i);let p=await _n({userAdapter:s.data.users,tenant_id:e,email:c.authParams.username,provider:u});p||(p=await s.data.users.create(e,{user_id:`email|${oi()}`,email:c.authParams.username,name:c.authParams.username,provider:"email",connection:"email",email_verified:!0,is_social:!1,last_ip:"",last_login:new Date().toISOString()})),t.set("username",p.email),t.set("user_id",p.user_id);const h=await Bg(t,{user:p,client:l,scope:r.scope,audience:r.audience});return Tn(t,{authParams:{scope:(m=c.authParams)==null?void 0:m.scope,...r},loginSession:c,sessionId:h.id,user:p,client:l})}async function zp(t,e){return`<!DOCTYPE html>
|
|
150
150
|
<html>
|
|
151
151
|
|
|
152
152
|
<head>
|
package/dist/authhero.mjs
CHANGED
|
@@ -18779,7 +18779,7 @@ async function Zl(t, e, n, r) {
|
|
|
18779
18779
|
if (!r.redirect_uri)
|
|
18780
18780
|
throw new $(400, { message: "redirect_uri is required" });
|
|
18781
18781
|
const s = new URL(je(t.env));
|
|
18782
|
-
s.pathname = "passwordless/verify_redirect", s.searchParams.set("
|
|
18782
|
+
s.pathname = "passwordless/verify_redirect", s.searchParams.set("verification_code", n), s.searchParams.set("connection", "email"), s.searchParams.set("client_id", r.client_id), s.searchParams.set("redirect_uri", r.redirect_uri), s.searchParams.set("email", e), r.response_type && s.searchParams.set("response_type", r.response_type), r.scope && s.searchParams.set("scope", r.scope), r.state && s.searchParams.set("state", r.state), r.nonce && s.searchParams.set("nonce", r.nonce), r.code_challenge && s.searchParams.set("code_challenge", r.code_challenge), r.code_challenge_method && s.searchParams.set(
|
|
18783
18783
|
"code_challenge_method",
|
|
18784
18784
|
r.code_challenge_method
|
|
18785
18785
|
), r.audience && s.searchParams.set("audience", r.audience);
|