/**
 * Minified by jsDelivr using Terser v5.39.0.
 * Original file: /npm/senomas-auth@0.9.14/dist/index.js
 *
 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
 */
"use strict";var __awaiter=this&&this.__awaiter||function(e,t,s,r){return new(s||(s=Promise))((function(a,i){function o(e){try{l(r.next(e))}catch(e){i(e)}}function n(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){e.done?a(e.value):new s((function(t){t(e.value)})).then(o,n)}l((r=r.apply(e,t||[])).next())}))};Object.defineProperty(exports,"__esModule",{value:!0});const express_1=require("express"),crypto=require("crypto"),scrypt=require("scryptsy"),jwt=require("jsonwebtoken");class AuthRouter{constructor(){this.hook=e=>(t,s,r)=>Promise.resolve(e(t,s,r)).catch((e=>r(e))),this.getSalt=(e=!0,t=null)=>(t||(t=String(Math.floor(Date.now()/9e5))),{key:t,value:"dodol"}),this.getUsernameSalt=(e,t,s)=>__awaiter(this,void 0,void 0,(function*(){"string"==typeof this.config.userSalt?t.json({salt:this.config.userSalt,scrypt:this.config.scrypt}):t.json({salt:this.config.userSalt[this.getSaltIndex(e)],scrypt:this.config.scrypt})})),this.getLoginSalt=(e,t,s)=>__awaiter(this,void 0,void 0,(function*(){let s=e.body.userhash;if(!s)throw{status:401,name:"AuthError",message:"Invalid user password",detail:"getLoginSalt: no user hash"};if(!e.body.nonce)throw{status:400,name:"AuthError",message:"Invalid request",detail:"getLoginSalt: no nonce"};let r=crypto.createHmac("sha256",e.body.nonce);if(r.update(String(e.body.iat)),r.update(Buffer.from(e.body.eckey,"base64")),r.update(Buffer.from(s,"base64")),"000"!==r.digest("hex").slice(-3))throw{status:400,name:"AuthError",message:"Invalid request",detail:"getLoginSalt: invalid nonce"};let a=e.headers["x-forwarded-for"]||e.connection.remoteAddress,i=crypto.createECDH("secp256k1");i.generateKeys();let o=yield this.getAuth(s);o||(o={userhash:s}),o.eckey=i.getPrivateKey("base64"),o.key=i.computeSecret(Buffer.from(e.body.eckey,"base64")).toString("base64"),this.setAuth(o);let n=yield this.getUser(s,this.getSaltIndex(e));if(!n)throw{status:401,name:"AuthError",message:"Invalid user password",detail:"getLoginSalt: Invalid user"};let l={sub:s,cip:a,salt:n.salt,eckey:i.getPublicKey("base64")},u=yield this.getSalt();l.sk=u.key,t.json({salt:jwt.sign(l,u.value,{expiresIn:"120s"})})})),this.login=(e,t,s)=>__awaiter(this,void 0,void 0,(function*(){if(!e.body.salt)throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: no login salt"};let s=jwt.decode(e.body.salt);if(!e.body.eckey)throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: no eckey"};if(!e.body.passkey2)throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: no passkey2"};if(!e.body.nonce)throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: no nonce"};let r=crypto.createHmac("sha256",e.body.nonce);if(r.update(e.body.salt),r.update(Buffer.from(e.body.eckey,"base64")),r.update(e.body.passkey2),"000"!==r.digest("hex").slice(-3))throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: invalid nonce"};let a=s.sub,i=(e.body.passkey2,yield this.getAuth(a));if(!i)throw{status:400,name:"AuthError",message:"Invalid request",detail:`No auth ${a}`};let o=crypto.createECDH("secp256k1");if(o.setPrivateKey(Buffer.from(i.eckey,"base64")),o.getPublicKey("base64")!==s.eckey)throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: invalid eckey"};let n=yield this.getSalt(!1,s.sk);if(!n)throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: no salt"};try{s=jwt.verify(e.body.salt,n.value)}catch(e){throw{status:403,name:"TokenExpiredError",message:e.message,detail:"login: salt jwt error"}}let l=e.headers["x-forwarded-for"]||e.connection.remoteAddress;if(l!==s.cip)throw{status:400,name:"AuthError",message:"Invalid request",detail:"login: invalid ip"};let u=yield this.getUser(a,this.getSaltIndex(e));if(!u)throw{status:401,name:"AuthError",message:"Invalid user password",detail:"login: Invalid user"};let h=scrypt(u.password,e.body.salt,this.config.scrypt.N,this.config.scrypt.r,this.config.scrypt.p,64).toString("base64"),d=crypto.createDecipheriv("aes-256-ctr",Buffer.from(i.key,"base64"),o.getPublicKey().slice(0,16)),c=Buffer.concat([d.update(Buffer.from(e.body.passkey2,"base64")),d.final()]).toString("base64");if(h!=c)throw{status:401,name:"AuthError",message:"Invalid user password",detail:`login: Invalid password '${h}' != '${c}'`};let g={sub:a,sk:n.key,cip:l,user:{username:u.username,name:u.name},roles:u.roles.map((e=>e.code))},f=jwt.sign(g,n.value,{expiresIn:this.config.tokenExpiry});i.token=jwt.sign({sub:a,sk:n.key,cip:l},n.value,{expiresIn:this.config.refreshTokenExpiry}),i.attempts||(i.attempts=[]),i.attempts.push({time:new Date,saltKey:n.key}),i.attempts.length>10&&(i.attempts=i.attempts.slice(-10)),this.setAuth(i);let m=crypto.createCipheriv("aes-256-ctr",Buffer.from(i.key,"base64"),o.getPublicKey().slice(0,16)),p=Buffer.concat([m.update(Buffer.from(JSON.stringify(u))),m.final()]).toString("base64");r=crypto.createHmac("sha256",Buffer.from(i.key,"base64")),r.update(f),r.update(i.token),r.update(p),t.json({token:f,refreshToken:i.token,user:p,sig:r.digest("base64")})})),this.getLoginUser=authHook(((e,t,s)=>__awaiter(this,void 0,void 0,(function*(){if(!t.locals.token)throw{status:403,name:"AuthError",message:"Invalid request",detail:"getLoginUser: no token"};let s=t.locals.token;if(!(yield this.getAuth(s.sub)))throw{status:400,name:"AuthError",message:"Invalid request",detail:"getLoginUser: no va"};let r=yield this.getUser(s.sub,this.getSaltIndex(e));if(!r)throw{status:400,name:"AuthError",message:"Invalid request",detail:"getLoginUser: no user"};t.json(r)})))),this.refreshToken=(e,t,s)=>__awaiter(this,void 0,void 0,(function*(){if(!e.params.token)throw{status:403,name:"AuthError",message:"Invalid request",detail:"refreshToken: no token"};let s=jwt.decode(e.params.token),r=yield this.getSalt(!1,s.sk);s=jwt.verify(e.params.token,r.value,{ignoreExpiration:!0});let a=e.headers["x-forwarded-for"]||e.connection.remoteAddress;if(a!==s.cip)throw{status:400,name:"AuthError",message:"Invalid request",detail:"refreshToken: invalid ip"};if(!e.params.refreshToken)throw{status:403,name:"AuthError",message:"Invalid request",detail:"refreshToken: no refreshToken"};let i=jwt.decode(e.params.refreshToken);r=yield this.getSalt(!1,i.sk);try{i=jwt.verify(e.params.refreshToken,r.value)}catch(e){throw{status:403,name:"TokenExpiredError",message:e.message,detail:"refreshToken: jwt error"}}if(s.sub!==i.sub)throw{status:403,name:"AuthError",message:"Invalid request",detail:"refreshToken: invalid refreshToken.sub"};if(a!==i.cip)throw{status:400,name:"AuthError",message:"Invalid request",detail:"refreshToken: invalid refreshToken ip"};let o=yield this.getAuth(s.sub);if(!o)throw{status:400,name:"AuthError",message:"Invalid request",detail:"refreshToken: no va"};let n=crypto.createECDH("secp256k1");n.setPrivateKey(Buffer.from(o.eckey,"base64"));let l=yield this.getUser(s.sub,this.getSaltIndex(e));if(!l)throw{status:401,name:"AuthError",message:"Invalid user",detail:"refreshToken: no user"};let u={sub:i.sub,sk:r.key,cip:a,user:{username:l.username,name:l.name},roles:l.roles},h=jwt.sign(u,r.value,{expiresIn:this.config.tokenExpiry});o.token=jwt.sign({sub:s.sub,sk:r.key,cip:a},r.value,{expiresIn:this.config.refreshTokenExpiry}),o.attempts||(o.attempts=[]),o.attempts.push({time:new Date,saltKey:r.key}),o.attempts.length>10&&(o.attempts=o.attempts.slice(-10)),this.setAuth(o);let d=crypto.createCipheriv("aes-256-ctr",Buffer.from(o.key,"base64"),n.getPublicKey().slice(0,16)),c=Buffer.concat([d.update(Buffer.from(JSON.stringify(l))),d.final()]).toString("base64"),g=crypto.createHmac("sha256",Buffer.from(o.key,"base64"));g.update(h),g.update(o.token),g.update(c),t.json({token:h,refreshToken:o.token,user:c,sig:g.digest("base64")})})),this.logout=(e,t,s)=>__awaiter(this,void 0,void 0,(function*(){if(!e.params.token)throw{status:403,name:"AuthError",message:"Invalid request",detail:"logout: no token"};let s=jwt.decode(e.params.token),r=yield this.getSalt(!1,s.sk);try{s=jwt.verify(e.params.token,r.value)}catch(e){throw{status:403,name:"TokenExpiredError",message:e.message,detail:"logout: jwt error"}}yield this.removeAuth(s.sub);t.json({token:s})})),this.validateAuthorization=this.hook(((e,t,s)=>__awaiter(this,void 0,void 0,(function*(){let r=e.headers["x-forwarded-for"]||e.connection.remoteAddress,a=yield this.getCache("block:"+r);if(a&&"t"===a)throw{status:400,name:"AuthError",message:"IP blocked",detail:"validateAuthorization: ip blocked"};if(e.headers.authorization){let s=e.headers.authorization;if(!s.startsWith("Bearer "))throw{status:400,name:"AuthError",message:"Invalid request",detail:"validateAuthorization: no authorization"};let a=s.slice(7).trim().split("."),i=a[0]+"."+a[1]+"."+a[2],o=jwt.decode(i),n=yield this.getSalt(!1,o.sk);if(!n)throw{status:400,name:"AuthError",message:"Invalid request",detail:"validateAuthorization: invalid salt"};try{o=jwt.verify(i,n.value)}catch(e){throw{status:403,name:"TokenExpiredError",message:e.message,detail:"validateAuthorization: jwt error"}}if(t.locals.token=o,!(a.length>4))throw{status:400,name:"AuthError",message:"Invalid request",detail:"validateAuthorization: no request sequence"};if(t.locals.requestSequence=a[3],t.locals.requestSignature=a[4],!(yield this.validateNonce(o.sub,parseInt(a[3]))))throw{status:400,name:"AuthError",message:"Invalid request",detail:"validateAuthorization: invalid request sequence"};if(r!==o.cip)throw{status:400,name:"AuthError",message:"Invalid request",detail:"invalid ip"};let l=yield this.getCache("auth:"+o.sub);if(l)t.locals.permissions=l.permissions,t.locals.key=l.key;else{let e=[];(yield this.getRoles(o.roles)).forEach((t=>{if("root"===t.code)e.push("root");else if(t.permissions)for(let s in t.permissions)"boolean"==typeof t.permissions[s]&&t.permissions[s]&&e.push(s)}));let s=yield this.getAuth(o.sub);l={permissions:e,key:Buffer.from(s.key,"base64")},this.setCache("auth:"+o.sub,l,10),t.locals.permissions=e,t.locals.key=l.key}}else t.locals.permissions=[];return s()}))))}get router(){let e=express_1.Router();return e.get("",this.hook(this.getUsernameSalt)),e.post("",this.hook(this.getLoginSalt)),e.post("/login",this.hook(this.login)),e.get("/user",this.getLoginUser),e.get("/:token/refresh/:refreshToken",this.hook(this.refreshToken)),e.delete("/:token",this.hook(this.logout)),e}init(e){this.config=e.config,this.getAuth=e.getAuth,this.setAuth=e.setAuth,this.removeAuth=e.removeAuth,this.getCache=e.getCache,this.setCache=e.setCache,this.removeCache=e.removeCache,this.getUser=e.getUser,this.getRoles=e.getRoles,this.validateNonce=e.validateNonce,this.getSaltIndex=e.getSaltIndex||(e=>0)}}exports.AuthRouter=AuthRouter;const authHook=e=>(t,s,r)=>{try{if(!t.headers.authorization)throw{status:400,name:"AuthError",message:"Invalid request",detail:"no authorization"};if(!s.locals.key)throw{status:400,name:"AuthError",message:"Invalid request",detail:"no secret key"};{if(!s.locals.requestSequence)throw{status:400,name:"AuthError",message:"Invalid request",detail:"no request sequence"};if(!s.locals.requestSignature)throw{status:400,name:"AuthError",message:"Invalid request",detail:"no request signature"};let e=crypto.createHmac("sha256",s.locals.key);if(e.update(s.locals.requestSequence),e.update(t.url),!t.body||"PATCH"!==t.method&&"POST"!==t.method||e.update(JSON.stringify(t.body)),e.digest("base64")!==s.locals.requestSignature)throw{status:400,name:"AuthError",message:"Invalid request",detail:"invalid signature",data:"development"===process.env.NODE_ENV?{seq:s.locals.requestSequence,url:t.url,body:!t.body||"PATCH"!==t.method&&"POST"!==t.method?void 0:JSON.stringify(t.body)}:void 0}}return Promise.resolve(e(t,s,r)).catch((e=>r(e)))}catch(e){r(e)}};function toSecond(e){let t=e.slice(-1),s=parseInt(e.slice(0,-1));if("s"===t);else if("m"==t)s*=60;else if("h"==t)s*=3600;else{if("d"!=t)throw`Invalid tokenExpiry '${e}'`;s*=86400}return s}exports.hook=authHook,exports.toSecond=toSecond,exports.authRouter=new AuthRouter;
//# sourceMappingURL=/sm/7c39632b322e4d88144949ca52dbf31d0c0b2b3ae367051e5c061b36df66d33a.map