pico-auth 0.0.5 → 0.0.7

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.
@@ -1,18 +1,29 @@
1
1
  declare module "core/auth" {
2
+ export interface UserProvider {
3
+ getUser(login: string): Promise<any>;
4
+ putUser(user: any): Promise<any>;
5
+ userSecretPath?: string;
6
+ userPasswordPath?: string;
7
+ }
8
+ export interface ImpersonateProvider {
9
+ canImpersonate(user: any, target: string): Promise<any>;
10
+ impersonateOrg(user: any, target: string): Promise<any>;
11
+ }
2
12
  /**
3
13
  * When mfaToken is provided
4
14
  */
5
- export const authenticate: (login: string, password: string, mfaToken: string, impersonateEntity: string, userProvider: any, impersonateProvider: any) => Promise<any>;
15
+ export const authenticate: (login: string, password: string, mfaToken: string, impersonateEntity: string, userProvider: UserProvider, impersonateProvider: any) => Promise<any>;
6
16
  /**
7
17
  * Will prepare user for MFA activation. Next step is to call verify with token generated in MFA app by the user.
8
18
  */
9
- export const mfaRegister: (appName: string, login: string, userProvider: any) => Promise<unknown>;
19
+ export const mfaRegister: (appName: string, login: string, userProvider: UserProvider) => Promise<unknown>;
10
20
  /**
11
21
  * Will return true and fully initialize MFA for user when token verification was ok. Otherwise will result false;
12
22
  */
13
- export const mfaVerify: (login: string, mfaToken: string, userProvider: any) => Promise<boolean>;
14
- export const mfaEnabled: (login: string, userProvider: any) => Promise<any>;
23
+ export const mfaVerify: (login: string, mfaToken: string, userProvider: UserProvider) => Promise<boolean>;
24
+ export const mfaEnabled: (login: string, userProvider: UserProvider) => Promise<any>;
15
25
  }
16
26
  declare module "pico-auth" {
17
27
  export { mfaRegister, mfaVerify, mfaEnabled, authenticate } from "core/auth";
28
+ export type { UserProvider, ImpersonateProvider } from "core/auth";
18
29
  }
@@ -6,12 +6,14 @@ const jwt = require('jsonwebtoken');
6
6
  * When mfaToken is provided
7
7
  */
8
8
  const authenticate = async (login, password, mfaToken, impersonateEntity, userProvider, impersonateProvider) => {
9
- var _a, _b, _c;
9
+ var _a;
10
10
  let user = await userProvider.getUser(login);
11
- if ((_a = user.mfa) === null || _a === void 0 ? void 0 : _a.enabled) {
11
+ const mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
12
+ const userPassword = userProvider.userPasswordPath ? user[userProvider.userPasswordPath] : user.password;
13
+ if (mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.enabled) {
12
14
  // Validate the token against the user's saved secret
13
15
  const validated = speakeasy.totp.verify({
14
- secret: (_c = (_b = user.mfa) === null || _b === void 0 ? void 0 : _b.secret) === null || _c === void 0 ? void 0 : _c.actual,
16
+ secret: (_a = mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.secret) === null || _a === void 0 ? void 0 : _a.actual,
15
17
  encoding: 'base32',
16
18
  mfaToken,
17
19
  window: 1, // Adjust window size if tokens have a margin of error
@@ -19,7 +21,7 @@ const authenticate = async (login, password, mfaToken, impersonateEntity, userPr
19
21
  if (!validated)
20
22
  throw new Error(`Failed authentication attempt ${login}`);
21
23
  }
22
- if (md5(password || '') == user.password) {
24
+ if (md5(password || '') == userPassword) {
23
25
  // check if impersonate mode - this is not yet implemented fully just copy pasta from GRM project
24
26
  const target = impersonateEntity; // either target user login or @organizationId
25
27
  const originalUser = user;
@@ -31,14 +33,14 @@ const authenticate = async (login, password, mfaToken, impersonateEntity, userPr
31
33
  // only organization impersonation
32
34
  // check requesting user has global admin
33
35
  // mayImpersonate = mayImpersonate || user.roles.map(role=>role.toUpperCase()).includes(UserManager.CONST.ROLES.GRM_ADMIN);
34
- mayImpersonate = mayImpersonate || impersonateProvider.canImpersonate(user, target);
36
+ mayImpersonate = mayImpersonate || await impersonateProvider.canImpersonate(user, target);
35
37
  // mayImpersonate = true;
36
38
  // todo check org exists
37
39
  if (!mayImpersonate) {
38
40
  throw new Error(`Failed impersonate attempt. From: ${originalUser.id} into ${target}`);
39
41
  }
40
42
  // switch original user organization_id
41
- impersonateProvider.impersonate(user, target);
43
+ await impersonateProvider.impersonateOrg(user, target);
42
44
  // await userManager.impersonateOrganization(user, target.substring(1).trim());
43
45
  // const organization = await commons.dbApi.adminApi.organization();
44
46
  // user.organization_id = parseInt(target.substring(1).trim()); // skip "@" at the beginning
@@ -52,7 +54,7 @@ const authenticate = async (login, password, mfaToken, impersonateEntity, userPr
52
54
  // mayImpersonate = mayImpersonate || (user.organization_id == targetUser.organization_id && user.roles.map(role=>role.toUpperCase()).includes(UserManager.CONST.ROLES.ORG_ADMIN))
53
55
  // check requesting user has global admin
54
56
  // mayImpersonate = mayImpersonate || user.roles.map(role=>role.toUpperCase()).includes(UserManager.CONST.ROLES.GRM_ADMIN);
55
- mayImpersonate = mayImpersonate || impersonateProvider.canImpersonate(user, target);
57
+ mayImpersonate = mayImpersonate || await impersonateProvider.canImpersonate(user, target);
56
58
  if (!mayImpersonate) {
57
59
  throw new Error(`Failed impersonate attempt. From: ${originalUser.id} into ${target}`);
58
60
  }
@@ -80,19 +82,20 @@ const authenticate = async (login, password, mfaToken, impersonateEntity, userPr
80
82
  const mfaRegister = async (appName, login, userProvider) => {
81
83
  return new Promise(async (resolve, _reject) => {
82
84
  let user = await userProvider.getUser(login);
85
+ let mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
83
86
  const secret = speakeasy.generateSecret({
84
87
  name: `${appName} (${login})`,
85
88
  });
86
- if (!user.mfa)
87
- user.mfa = {
89
+ if (!mfaInfo)
90
+ mfaInfo = {
88
91
  secret: {
89
92
  temp: undefined,
90
- actual: undefined,
91
- enabled: true
92
- }
93
+ actual: undefined
94
+ },
95
+ enabled: false
93
96
  };
94
- user.mfa.secret.temp = secret.base32;
95
- user.mfa.secret.actual = undefined;
97
+ mfaInfo.secret.temp = secret.base32;
98
+ mfaInfo.secret.actual = undefined;
96
99
  await userProvider.putUser(user);
97
100
  qrcode.toDataURL(secret.otpauth_url, (err, data) => {
98
101
  if (err) {
@@ -112,18 +115,20 @@ const mfaRegister = async (appName, login, userProvider) => {
112
115
  * Will return true and fully initialize MFA for user when token verification was ok. Otherwise will result false;
113
116
  */
114
117
  const mfaVerify = async (login, mfaToken, userProvider) => {
115
- var _a, _b, _c, _d;
118
+ var _a, _b;
116
119
  const token = mfaToken;
117
120
  // load user
118
121
  let user = await userProvider.getUser(login);
122
+ const mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
119
123
  // Verify the token using the saved secret
120
124
  const verified = speakeasy.totp.verify({
121
- secret: (_b = (_a = user.mfa) === null || _a === void 0 ? void 0 : _a.secret) === null || _b === void 0 ? void 0 : _b.temp,
125
+ secret: (_a = mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.secret) === null || _a === void 0 ? void 0 : _a.temp,
122
126
  encoding: 'base32',
123
127
  token,
124
128
  });
125
129
  if (verified) {
126
- user.mfa.secret.actual = (_d = (_c = user.mfa) === null || _c === void 0 ? void 0 : _c.secret) === null || _d === void 0 ? void 0 : _d.temp;
130
+ mfaInfo.secret.actual = (_b = mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.secret) === null || _b === void 0 ? void 0 : _b.temp;
131
+ mfaInfo.enabled = true;
127
132
  await userProvider.putUser(user);
128
133
  return true;
129
134
  }
@@ -133,9 +138,9 @@ const mfaVerify = async (login, mfaToken, userProvider) => {
133
138
  }
134
139
  };
135
140
  const mfaEnabled = async (login, userProvider) => {
136
- var _a;
137
141
  let user = await userProvider.getUser(login);
138
- return (_a = user.mfa) === null || _a === void 0 ? void 0 : _a.enabled;
142
+ const mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
143
+ return mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.enabled;
139
144
  };
140
145
 
141
146
  export { authenticate, mfaEnabled, mfaRegister, mfaVerify };
@@ -1 +1 @@
1
- const speakeasy=require("speakeasy"),qrcode=require("qrcode"),md5=require("md5"),jwt=require("jsonwebtoken"),authenticate=async(e,t,a,r,o,i)=>{var n,s,c;let l=await o.getUser(e);if(null===(n=l.mfa)||void 0===n?void 0:n.enabled){if(!speakeasy.totp.verify({secret:null===(c=null===(s=l.mfa)||void 0===s?void 0:s.secret)||void 0===c?void 0:c.actual,encoding:"base32",mfaToken:a,window:1}))throw new Error(`Failed authentication attempt ${e}`)}if(md5(t||"")==l.password){const e=r,t=l;if(e){let a=!1;if(e.startsWith("@")){if(a=a||i.canImpersonate(l,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);i.impersonate(l,e)}else{const r=await o.getUser(e);if(a=a||i.canImpersonate(l,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);l=r}console.info(`Impersonate success. From: ${t.login} into ${e}`)}let a=process.env.JWT_SECRET_KEY,n={time:Date.now(),user:l};const s=jwt.sign(n,a,{expiresIn:process.env.JWT_EXPIRY_TIME});return console.log(`Successful login: ${l.id}`),s}throw new Error(`Failed authentication attempt ${e}`)},mfaRegister=async(e,t,a)=>new Promise((async(r,o)=>{let i=await a.getUser(t);const n=speakeasy.generateSecret({name:`${e} (${t})`});i.mfa||(i.mfa={secret:{temp:void 0,actual:void 0,enabled:!0}}),i.mfa.secret.temp=n.base32,i.mfa.secret.actual=void 0,await a.putUser(i),qrcode.toDataURL(n.otpauth_url,((e,t)=>{if(e)throw new Error("Error generating QR code");r({qr_code:t,secret:n.base32})}))})),mfaVerify=async(e,t,a)=>{var r,o,i,n;const s=t;let c=await a.getUser(e);return speakeasy.totp.verify({secret:null===(o=null===(r=c.mfa)||void 0===r?void 0:r.secret)||void 0===o?void 0:o.temp,encoding:"base32",token:s})?(c.mfa.secret.actual=null===(n=null===(i=c.mfa)||void 0===i?void 0:i.secret)||void 0===n?void 0:n.temp,await a.putUser(c),!0):(console.log(`Failed mfa verification for ${e}`),!1)},mfaEnabled=async(e,t)=>{var a;return null===(a=(await t.getUser(e)).mfa)||void 0===a?void 0:a.enabled};export{authenticate,mfaEnabled,mfaRegister,mfaVerify};
1
+ const speakeasy=require("speakeasy"),qrcode=require("qrcode"),md5=require("md5"),jwt=require("jsonwebtoken"),authenticate=async(e,t,a,r,s,o)=>{var n;let i=await s.getUser(e);const c=s.userSecretPath?i[s.userSecretPath]:i.mfa,l=s.userPasswordPath?i[s.userPasswordPath]:i.password;if(null==c?void 0:c.enabled){if(!speakeasy.totp.verify({secret:null===(n=null==c?void 0:c.secret)||void 0===n?void 0:n.actual,encoding:"base32",mfaToken:a,window:1}))throw new Error(`Failed authentication attempt ${e}`)}if(md5(t||"")==l){const e=r,t=i;if(e){let a=!1;if(e.startsWith("@")){if(a=a||await o.canImpersonate(i,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);await o.impersonateOrg(i,e)}else{const r=await s.getUser(e);if(a=a||await o.canImpersonate(i,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);i=r}console.info(`Impersonate success. From: ${t.login} into ${e}`)}let a=process.env.JWT_SECRET_KEY,n={time:Date.now(),user:i};const c=jwt.sign(n,a,{expiresIn:process.env.JWT_EXPIRY_TIME});return console.log(`Successful login: ${i.id}`),c}throw new Error(`Failed authentication attempt ${e}`)},mfaRegister=async(e,t,a)=>new Promise((async(r,s)=>{let o=await a.getUser(t),n=a.userSecretPath?o[a.userSecretPath]:o.mfa;const i=speakeasy.generateSecret({name:`${e} (${t})`});n||(n={secret:{temp:void 0,actual:void 0},enabled:!1}),n.secret.temp=i.base32,n.secret.actual=void 0,await a.putUser(o),qrcode.toDataURL(i.otpauth_url,((e,t)=>{if(e)throw new Error("Error generating QR code");r({qr_code:t,secret:i.base32})}))})),mfaVerify=async(e,t,a)=>{var r,s;const o=t;let n=await a.getUser(e);const i=a.userSecretPath?n[a.userSecretPath]:n.mfa;return speakeasy.totp.verify({secret:null===(r=null==i?void 0:i.secret)||void 0===r?void 0:r.temp,encoding:"base32",token:o})?(i.secret.actual=null===(s=null==i?void 0:i.secret)||void 0===s?void 0:s.temp,i.enabled=!0,await a.putUser(n),!0):(console.log(`Failed mfa verification for ${e}`),!1)},mfaEnabled=async(e,t)=>{let a=await t.getUser(e);const r=t.userSecretPath?a[t.userSecretPath]:a.mfa;return null==r?void 0:r.enabled};export{authenticate,mfaEnabled,mfaRegister,mfaVerify};
@@ -12,12 +12,14 @@
12
12
  * When mfaToken is provided
13
13
  */
14
14
  const authenticate = async (login, password, mfaToken, impersonateEntity, userProvider, impersonateProvider) => {
15
- var _a, _b, _c;
15
+ var _a;
16
16
  let user = await userProvider.getUser(login);
17
- if ((_a = user.mfa) === null || _a === void 0 ? void 0 : _a.enabled) {
17
+ const mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
18
+ const userPassword = userProvider.userPasswordPath ? user[userProvider.userPasswordPath] : user.password;
19
+ if (mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.enabled) {
18
20
  // Validate the token against the user's saved secret
19
21
  const validated = speakeasy.totp.verify({
20
- secret: (_c = (_b = user.mfa) === null || _b === void 0 ? void 0 : _b.secret) === null || _c === void 0 ? void 0 : _c.actual,
22
+ secret: (_a = mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.secret) === null || _a === void 0 ? void 0 : _a.actual,
21
23
  encoding: 'base32',
22
24
  mfaToken,
23
25
  window: 1, // Adjust window size if tokens have a margin of error
@@ -25,7 +27,7 @@
25
27
  if (!validated)
26
28
  throw new Error(`Failed authentication attempt ${login}`);
27
29
  }
28
- if (md5(password || '') == user.password) {
30
+ if (md5(password || '') == userPassword) {
29
31
  // check if impersonate mode - this is not yet implemented fully just copy pasta from GRM project
30
32
  const target = impersonateEntity; // either target user login or @organizationId
31
33
  const originalUser = user;
@@ -37,14 +39,14 @@
37
39
  // only organization impersonation
38
40
  // check requesting user has global admin
39
41
  // mayImpersonate = mayImpersonate || user.roles.map(role=>role.toUpperCase()).includes(UserManager.CONST.ROLES.GRM_ADMIN);
40
- mayImpersonate = mayImpersonate || impersonateProvider.canImpersonate(user, target);
42
+ mayImpersonate = mayImpersonate || await impersonateProvider.canImpersonate(user, target);
41
43
  // mayImpersonate = true;
42
44
  // todo check org exists
43
45
  if (!mayImpersonate) {
44
46
  throw new Error(`Failed impersonate attempt. From: ${originalUser.id} into ${target}`);
45
47
  }
46
48
  // switch original user organization_id
47
- impersonateProvider.impersonate(user, target);
49
+ await impersonateProvider.impersonateOrg(user, target);
48
50
  // await userManager.impersonateOrganization(user, target.substring(1).trim());
49
51
  // const organization = await commons.dbApi.adminApi.organization();
50
52
  // user.organization_id = parseInt(target.substring(1).trim()); // skip "@" at the beginning
@@ -58,7 +60,7 @@
58
60
  // mayImpersonate = mayImpersonate || (user.organization_id == targetUser.organization_id && user.roles.map(role=>role.toUpperCase()).includes(UserManager.CONST.ROLES.ORG_ADMIN))
59
61
  // check requesting user has global admin
60
62
  // mayImpersonate = mayImpersonate || user.roles.map(role=>role.toUpperCase()).includes(UserManager.CONST.ROLES.GRM_ADMIN);
61
- mayImpersonate = mayImpersonate || impersonateProvider.canImpersonate(user, target);
63
+ mayImpersonate = mayImpersonate || await impersonateProvider.canImpersonate(user, target);
62
64
  if (!mayImpersonate) {
63
65
  throw new Error(`Failed impersonate attempt. From: ${originalUser.id} into ${target}`);
64
66
  }
@@ -86,19 +88,20 @@
86
88
  const mfaRegister = async (appName, login, userProvider) => {
87
89
  return new Promise(async (resolve, _reject) => {
88
90
  let user = await userProvider.getUser(login);
91
+ let mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
89
92
  const secret = speakeasy.generateSecret({
90
93
  name: `${appName} (${login})`,
91
94
  });
92
- if (!user.mfa)
93
- user.mfa = {
95
+ if (!mfaInfo)
96
+ mfaInfo = {
94
97
  secret: {
95
98
  temp: undefined,
96
- actual: undefined,
97
- enabled: true
98
- }
99
+ actual: undefined
100
+ },
101
+ enabled: false
99
102
  };
100
- user.mfa.secret.temp = secret.base32;
101
- user.mfa.secret.actual = undefined;
103
+ mfaInfo.secret.temp = secret.base32;
104
+ mfaInfo.secret.actual = undefined;
102
105
  await userProvider.putUser(user);
103
106
  qrcode.toDataURL(secret.otpauth_url, (err, data) => {
104
107
  if (err) {
@@ -118,18 +121,20 @@
118
121
  * Will return true and fully initialize MFA for user when token verification was ok. Otherwise will result false;
119
122
  */
120
123
  const mfaVerify = async (login, mfaToken, userProvider) => {
121
- var _a, _b, _c, _d;
124
+ var _a, _b;
122
125
  const token = mfaToken;
123
126
  // load user
124
127
  let user = await userProvider.getUser(login);
128
+ const mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
125
129
  // Verify the token using the saved secret
126
130
  const verified = speakeasy.totp.verify({
127
- secret: (_b = (_a = user.mfa) === null || _a === void 0 ? void 0 : _a.secret) === null || _b === void 0 ? void 0 : _b.temp,
131
+ secret: (_a = mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.secret) === null || _a === void 0 ? void 0 : _a.temp,
128
132
  encoding: 'base32',
129
133
  token,
130
134
  });
131
135
  if (verified) {
132
- user.mfa.secret.actual = (_d = (_c = user.mfa) === null || _c === void 0 ? void 0 : _c.secret) === null || _d === void 0 ? void 0 : _d.temp;
136
+ mfaInfo.secret.actual = (_b = mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.secret) === null || _b === void 0 ? void 0 : _b.temp;
137
+ mfaInfo.enabled = true;
133
138
  await userProvider.putUser(user);
134
139
  return true;
135
140
  }
@@ -139,9 +144,9 @@
139
144
  }
140
145
  };
141
146
  const mfaEnabled = async (login, userProvider) => {
142
- var _a;
143
147
  let user = await userProvider.getUser(login);
144
- return (_a = user.mfa) === null || _a === void 0 ? void 0 : _a.enabled;
148
+ const mfaInfo = userProvider.userSecretPath ? user[userProvider.userSecretPath] : user.mfa;
149
+ return mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.enabled;
145
150
  };
146
151
 
147
152
  exports.authenticate = authenticate;
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).picoAuth={})}(this,(function(e){"use strict";const t=require("speakeasy"),o=require("qrcode"),a=require("md5"),r=require("jsonwebtoken");e.authenticate=async(e,o,i,n,s,c)=>{var l,d,f;let u=await s.getUser(e);if(null===(l=u.mfa)||void 0===l?void 0:l.enabled){if(!t.totp.verify({secret:null===(f=null===(d=u.mfa)||void 0===d?void 0:d.secret)||void 0===f?void 0:f.actual,encoding:"base32",mfaToken:i,window:1}))throw new Error(`Failed authentication attempt ${e}`)}if(a(o||"")==u.password){const e=n,t=u;if(e){let o=!1;if(e.startsWith("@")){if(o=o||c.canImpersonate(u,e),!o)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);c.impersonate(u,e)}else{const a=await s.getUser(e);if(o=o||c.canImpersonate(u,e),!o)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);u=a}console.info(`Impersonate success. From: ${t.login} into ${e}`)}let o=process.env.JWT_SECRET_KEY,a={time:Date.now(),user:u};const i=r.sign(a,o,{expiresIn:process.env.JWT_EXPIRY_TIME});return console.log(`Successful login: ${u.id}`),i}throw new Error(`Failed authentication attempt ${e}`)},e.mfaEnabled=async(e,t)=>{var o;return null===(o=(await t.getUser(e)).mfa)||void 0===o?void 0:o.enabled},e.mfaRegister=async(e,a,r)=>new Promise((async(i,n)=>{let s=await r.getUser(a);const c=t.generateSecret({name:`${e} (${a})`});s.mfa||(s.mfa={secret:{temp:void 0,actual:void 0,enabled:!0}}),s.mfa.secret.temp=c.base32,s.mfa.secret.actual=void 0,await r.putUser(s),o.toDataURL(c.otpauth_url,((e,t)=>{if(e)throw new Error("Error generating QR code");i({qr_code:t,secret:c.base32})}))})),e.mfaVerify=async(e,o,a)=>{var r,i,n,s;const c=o;let l=await a.getUser(e);return t.totp.verify({secret:null===(i=null===(r=l.mfa)||void 0===r?void 0:r.secret)||void 0===i?void 0:i.temp,encoding:"base32",token:c})?(l.mfa.secret.actual=null===(s=null===(n=l.mfa)||void 0===n?void 0:n.secret)||void 0===s?void 0:s.temp,await a.putUser(l),!0):(console.log(`Failed mfa verification for ${e}`),!1)},Object.defineProperty(e,"__esModule",{value:!0})}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).picoAuth={})}(this,(function(e){"use strict";const t=require("speakeasy"),r=require("qrcode"),a=require("md5"),o=require("jsonwebtoken");e.authenticate=async(e,r,n,s,i,c)=>{var l;let u=await i.getUser(e);const d=i.userSecretPath?u[i.userSecretPath]:u.mfa,f=i.userPasswordPath?u[i.userPasswordPath]:u.password;if(null==d?void 0:d.enabled){if(!t.totp.verify({secret:null===(l=null==d?void 0:d.secret)||void 0===l?void 0:l.actual,encoding:"base32",mfaToken:n,window:1}))throw new Error(`Failed authentication attempt ${e}`)}if(a(r||"")==f){const e=s,t=u;if(e){let r=!1;if(e.startsWith("@")){if(r=r||await c.canImpersonate(u,e),!r)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);await c.impersonateOrg(u,e)}else{const a=await i.getUser(e);if(r=r||await c.canImpersonate(u,e),!r)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);u=a}console.info(`Impersonate success. From: ${t.login} into ${e}`)}let r=process.env.JWT_SECRET_KEY,a={time:Date.now(),user:u};const n=o.sign(a,r,{expiresIn:process.env.JWT_EXPIRY_TIME});return console.log(`Successful login: ${u.id}`),n}throw new Error(`Failed authentication attempt ${e}`)},e.mfaEnabled=async(e,t)=>{let r=await t.getUser(e);const a=t.userSecretPath?r[t.userSecretPath]:r.mfa;return null==a?void 0:a.enabled},e.mfaRegister=async(e,a,o)=>new Promise((async(n,s)=>{let i=await o.getUser(a),c=o.userSecretPath?i[o.userSecretPath]:i.mfa;const l=t.generateSecret({name:`${e} (${a})`});c||(c={secret:{temp:void 0,actual:void 0},enabled:!1}),c.secret.temp=l.base32,c.secret.actual=void 0,await o.putUser(i),r.toDataURL(l.otpauth_url,((e,t)=>{if(e)throw new Error("Error generating QR code");n({qr_code:t,secret:l.base32})}))})),e.mfaVerify=async(e,r,a)=>{var o,n;const s=r;let i=await a.getUser(e);const c=a.userSecretPath?i[a.userSecretPath]:i.mfa;return t.totp.verify({secret:null===(o=null==c?void 0:c.secret)||void 0===o?void 0:o.temp,encoding:"base32",token:s})?(c.secret.actual=null===(n=null==c?void 0:c.secret)||void 0===n?void 0:n.temp,c.enabled=!0,await a.putUser(i),!0):(console.log(`Failed mfa verification for ${e}`),!1)},Object.defineProperty(e,"__esModule",{value:!0})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pico-auth",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Minimal auth with user/pass, impersonation and mfa authentication",
5
5
  "main": "dist/pico-auth.umd.js",
6
6
  "types": "dist/pico-auth.d.ts",