pico-auth 0.0.33 → 0.0.34

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.
@@ -24,6 +24,10 @@ declare module "core/auth" {
24
24
  blocked?: boolean;
25
25
  [key: string]: any;
26
26
  }
27
+ export const issueJwtToken: (user: BaseUser, userProvider: UserProvider, jwtSpecs: JWTSpecs, issueRefreshToken: boolean) => Promise<{
28
+ token: any;
29
+ clearedUser: BaseUser;
30
+ }>;
27
31
  /**
28
32
  * When mfaToken is provided
29
33
  */
@@ -43,6 +47,7 @@ declare module "core/auth" {
43
47
  */
44
48
  export const authenticateWithScratchCard: (cardCode: string, userProvider: UserProvider, scratchCardProvider: ScratchCardProvider, jwtSpecs: JWTSpecs, requesterLogin?: string) => Promise<{
45
49
  token: any;
50
+ refreshToken: any;
46
51
  user: any;
47
52
  }>;
48
53
  /**
@@ -68,6 +73,6 @@ declare module "core/auth" {
68
73
  export const mfaEnabled: (login: string, userProvider: UserProvider) => Promise<any>;
69
74
  }
70
75
  declare module "pico-auth" {
71
- export { mfaRegister, mfaVerify, mfaEnabled, authenticate, authenticateWithScratchCard, refreshToken } from "core/auth";
76
+ export { mfaRegister, mfaVerify, mfaEnabled, authenticate, authenticateWithScratchCard, refreshToken, issueJwtToken } from "core/auth";
72
77
  export type { UserProvider, ImpersonateProvider, JWTSpecs, ScratchCardProvider, BaseUser } from "core/auth";
73
78
  }
@@ -2,6 +2,26 @@ const speakeasy = require('speakeasy');
2
2
  const qrcode = require('qrcode');
3
3
  const md5 = require("md5");
4
4
  const jwt = require('jsonwebtoken');
5
+ const issueJwtToken = async (user, userProvider, jwtSpecs, issueRefreshToken) => {
6
+ let jwtSecretKey = jwtSpecs.secretKey;
7
+ let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(user) : user;
8
+ clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
9
+ let data = {
10
+ time: Date.now(),
11
+ user: clearedUser
12
+ };
13
+ let token;
14
+ if (issueRefreshToken && jwtSpecs.refreshExpiryTimeMs) {
15
+ token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.refreshExpiryTimeMs });
16
+ }
17
+ else if (jwtSpecs.expiryTimeMs) {
18
+ token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
19
+ }
20
+ return {
21
+ token,
22
+ clearedUser
23
+ };
24
+ };
5
25
  /**
6
26
  * When mfaToken is provided
7
27
  */
@@ -66,19 +86,10 @@ const authenticate = async (login, password, mfaToken, impersonateEntity, userPr
66
86
  }
67
87
  console.info(`Impersonate success. From: ${originalUser.login} into ${target}`);
68
88
  }
69
- // let jwtSecretKey = process.env.JWT_SECRET_KEY;
70
- let jwtSecretKey = jwtSpecs.secretKey;
71
- let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(user) : user;
72
- clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
73
- let data = {
74
- time: Date.now(),
75
- user: clearedUser
76
- };
77
- // const token = jwt.sign(data, jwtSecretKey, {expiresIn: process.env.JWT_EXPIRY_TIME});
78
- const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
89
+ const token = (await issueJwtToken(user, userProvider, jwtSpecs, false)).token;
79
90
  let refreshToken;
80
91
  if (jwtSpecs.refreshExpiryTimeMs)
81
- refreshToken = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.refreshExpiryTimeMs });
92
+ refreshToken = (await issueJwtToken(user, userProvider, jwtSpecs, true)).token;
82
93
  console.log(`Successful login: ${user.id}`);
83
94
  return {
84
95
  token,
@@ -121,19 +132,15 @@ const authenticateWithScratchCard = async (cardCode, userProvider, scratchCardPr
121
132
  throw new Error(`Failed card authentication attempt ${requesterLogin} (Blocked as Target)`);
122
133
  // ok so we will use targetUser as a user that will be actually logged in
123
134
  // in impersonation scenario targetUser may be different then the user.
124
- let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(targetUser) : targetUser;
125
- clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
126
- let jwtSecretKey = jwtSpecs.secretKey;
127
- let data = {
128
- time: Date.now(),
129
- user: clearedUser
130
- };
131
- // const token = jwt.sign(data, jwtSecretKey, {expiresIn: process.env.JWT_EXPIRY_TIME});
132
- const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
135
+ const token = (await issueJwtToken(targetUser, userProvider, jwtSpecs, false)).token;
136
+ let refreshToken;
137
+ if (jwtSpecs.refreshExpiryTimeMs)
138
+ refreshToken = (await issueJwtToken(targetUser, userProvider, jwtSpecs, true)).token;
133
139
  console.info(`Card authentication success. Requester:${requesterLogin} Target:${targetUser.id}`);
134
140
  return {
135
141
  token,
136
- user: clearedUser // just in case its impersonation so the actual resultin user will be different that the requester login user
142
+ refreshToken,
143
+ user: token.clearedUser // just in case its impersonation so the actual resulting user will be different that the requester login user
137
144
  };
138
145
  }
139
146
  catch (error) {
@@ -164,15 +171,9 @@ const refreshToken = async (login, refreshToken, userProvider, jwtSpecs) => {
164
171
  if (!refreshTokenUser || refreshTokenUser.id != user.id) {
165
172
  throw new Error(`Failed refresh token attempt ${login} (Invalid Token)`);
166
173
  }
167
- let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(user) : user;
168
- clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
169
- let data = {
170
- time: Date.now(),
171
- user: clearedUser
172
- };
173
- const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
174
+ const token = (await issueJwtToken(user, userProvider, jwtSpecs, false)).token;
174
175
  console.log(`Successful token refresh: ${user.id}`);
175
- return { token: token };
176
+ return { token };
176
177
  }
177
178
  else {
178
179
  throw new Error(`Failed refresh token attempt ${login}`);
@@ -252,4 +253,4 @@ const mfaEnabled = async (login, userProvider) => {
252
253
  return (mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.enabled) || false;
253
254
  };
254
255
 
255
- export { authenticate, authenticateWithScratchCard, mfaEnabled, mfaRegister, mfaVerify, refreshToken };
256
+ export { authenticate, authenticateWithScratchCard, issueJwtToken, mfaEnabled, mfaRegister, mfaVerify, refreshToken };
@@ -1 +1 @@
1
- const speakeasy=require("speakeasy"),qrcode=require("qrcode"),md5=require("md5"),jwt=require("jsonwebtoken"),authenticate=async(e,t,r,a,i,s,o)=>{var n;let c=await i.getUser(e);const l=i.userSecretPath?c[i.userSecretPath]:c.mfa,d=i.userPasswordPath?c[i.userPasswordPath]:c.password;if(null==l?void 0:l.enabled){if(!speakeasy.totp.verify({secret:null===(n=null==l?void 0:l.secret)||void 0===n?void 0:n.actual,encoding:"base32",token:r,window:1}))throw new Error(`Failed authentication attempt ${e} (MFA Enabled)`)}if(c.blocked)throw new Error(`Failed authentication attempt ${e} (Blocked)`);if(md5(t||"")==d){const e=a,t=c;if(e){let r=!1;if(e.startsWith("@")){if(r=r||await s.canImpersonate(c,e),!r)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);await s.impersonateOrg(c,e)}else{const a=await i.getUser(e);if(r=r||await s.canImpersonate(c,e),!r)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);c=a}console.info(`Impersonate success. From: ${t.login} into ${e}`)}let r=o.secretKey,n=i.getSafeUser?await i.getSafeUser(c):c;n=i.getUserPostAuthenticate?await i.getUserPostAuthenticate(n):n;let l={time:Date.now(),user:n};const d=jwt.sign(l,r,{expiresIn:o.expiryTimeMs});let u;return o.refreshExpiryTimeMs&&(u=jwt.sign(l,r,{expiresIn:o.refreshExpiryTimeMs})),console.log(`Successful login: ${c.id}`),{token:d,refreshToken:u}}throw new Error(`Failed authentication attempt ${e}`)},authenticateWithScratchCard=async(e,t,r,a,i)=>{let s,o=i?await t.getUser(i):void 0;if(o&&o.blocked)throw new Error(`Failed card authentication attempt ${i} (Blocked)`);if(i&&!o)throw new Error(`Failed card authentication attempt ${i} (Missing user)`);try{s=await r.consume(e,o)}catch(e){throw new Error(`Failed card authentication attempt ${i} (Consume Failed)`)}try{if(!s)throw new Error(`Failed card authentication attempt ${i} (Consume Failed)`);if(s.blocked)throw new Error(`Failed card authentication attempt ${i} (Blocked as Target)`);let e=t.getSafeUser?await t.getSafeUser(s):s;e=t.getUserPostAuthenticate?await t.getUserPostAuthenticate(e):e;let r=a.secretKey,o={time:Date.now(),user:e};const n=jwt.sign(o,r,{expiresIn:a.expiryTimeMs});return console.info(`Card authentication success. Requester:${i} Target:${s.id}`),{token:n,user:e}}catch(e){throw new Error(`Failed card authentication attempt ${i}`)}},refreshToken=async(e,t,r,a)=>{let i=await r.getUser(e);if(i.blocked)throw new Error(`Failed refresh token attempt ${e} (Blocked)`);if(t){let s=a.secretKey;const o=jwt.verify(t,s).user;if(!o||o.id!=i.id)throw new Error(`Failed refresh token attempt ${e} (Invalid Token)`);let n=r.getSafeUser?await r.getSafeUser(i):i;n=r.getUserPostAuthenticate?await r.getUserPostAuthenticate(n):n;let c={time:Date.now(),user:n};const l=jwt.sign(c,s,{expiresIn:a.expiryTimeMs});return console.log(`Successful token refresh: ${i.id}`),{token:l}}throw new Error(`Failed refresh token attempt ${e}`)},mfaRegister=async(e,t,r)=>new Promise(async(a,i)=>{let s=await r.getUser(t),o=r.userSecretPath?s[r.userSecretPath]:s.mfa;const n=speakeasy.generateSecret({name:`${e}: ${t}`});if(!o){o={secret:{temp:void 0,actual:void 0},enabled:!1};s[r.userSecretPath?r.userSecretPath:"mfa"]=o}o.secret.temp=n.base32,o.secret.actual=void 0,await r.putUser(s),qrcode.toDataURL(n.otpauth_url,(e,t)=>{if(e)throw new Error("Error generating QR code");a({qr_code:t,secret:n.base32})})}),mfaVerify=async(e,t,r)=>{var a,i;const s=t;let o=await r.getUser(e);const n=r.userSecretPath?o[r.userSecretPath]:o.mfa;return speakeasy.totp.verify({secret:null===(a=null==n?void 0:n.secret)||void 0===a?void 0:a.temp,encoding:"base32",token:s})?(n.secret.actual=null===(i=null==n?void 0:n.secret)||void 0===i?void 0:i.temp,n.enabled=!0,await r.putUser(o),!0):(console.log(`Failed mfa verification for ${e}`),!1)},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)||!1};export{authenticate,authenticateWithScratchCard,mfaEnabled,mfaRegister,mfaVerify,refreshToken};
1
+ const speakeasy=require("speakeasy"),qrcode=require("qrcode"),md5=require("md5"),jwt=require("jsonwebtoken"),issueJwtToken=async(e,t,r,a)=>{let i=r.secretKey,o=t.getSafeUser?await t.getSafeUser(e):e;o=t.getUserPostAuthenticate?await t.getUserPostAuthenticate(o):o;let s,n={time:Date.now(),user:o};return a&&r.refreshExpiryTimeMs?s=jwt.sign(n,i,{expiresIn:r.refreshExpiryTimeMs}):r.expiryTimeMs&&(s=jwt.sign(n,i,{expiresIn:r.expiryTimeMs})),{token:s,clearedUser:o}},authenticate=async(e,t,r,a,i,o,s)=>{var n;let c=await i.getUser(e);const l=i.userSecretPath?c[i.userSecretPath]:c.mfa,d=i.userPasswordPath?c[i.userPasswordPath]:c.password;if(null==l?void 0:l.enabled){if(!speakeasy.totp.verify({secret:null===(n=null==l?void 0:l.secret)||void 0===n?void 0:n.actual,encoding:"base32",token:r,window:1}))throw new Error(`Failed authentication attempt ${e} (MFA Enabled)`)}if(c.blocked)throw new Error(`Failed authentication attempt ${e} (Blocked)`);if(md5(t||"")==d){const e=a,t=c;if(e){let r=!1;if(e.startsWith("@")){if(r=r||await o.canImpersonate(c,e),!r)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);await o.impersonateOrg(c,e)}else{const a=await i.getUser(e);if(r=r||await o.canImpersonate(c,e),!r)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);c=a}console.info(`Impersonate success. From: ${t.login} into ${e}`)}const r=(await issueJwtToken(c,i,s,!1)).token;let n;return s.refreshExpiryTimeMs&&(n=(await issueJwtToken(c,i,s,!0)).token),console.log(`Successful login: ${c.id}`),{token:r,refreshToken:n}}throw new Error(`Failed authentication attempt ${e}`)},authenticateWithScratchCard=async(e,t,r,a,i)=>{let o,s=i?await t.getUser(i):void 0;if(s&&s.blocked)throw new Error(`Failed card authentication attempt ${i} (Blocked)`);if(i&&!s)throw new Error(`Failed card authentication attempt ${i} (Missing user)`);try{o=await r.consume(e,s)}catch(e){throw new Error(`Failed card authentication attempt ${i} (Consume Failed)`)}try{if(!o)throw new Error(`Failed card authentication attempt ${i} (Consume Failed)`);if(o.blocked)throw new Error(`Failed card authentication attempt ${i} (Blocked as Target)`);const e=(await issueJwtToken(o,t,a,!1)).token;let r;return a.refreshExpiryTimeMs&&(r=(await issueJwtToken(o,t,a,!0)).token),console.info(`Card authentication success. Requester:${i} Target:${o.id}`),{token:e,refreshToken:r,user:e.clearedUser}}catch(e){throw new Error(`Failed card authentication attempt ${i}`)}},refreshToken=async(e,t,r,a)=>{let i=await r.getUser(e);if(i.blocked)throw new Error(`Failed refresh token attempt ${e} (Blocked)`);if(t){let o=a.secretKey;const s=jwt.verify(t,o).user;if(!s||s.id!=i.id)throw new Error(`Failed refresh token attempt ${e} (Invalid Token)`);const n=(await issueJwtToken(i,r,a,!1)).token;return console.log(`Successful token refresh: ${i.id}`),{token:n}}throw new Error(`Failed refresh token attempt ${e}`)},mfaRegister=async(e,t,r)=>new Promise(async(a,i)=>{let o=await r.getUser(t),s=r.userSecretPath?o[r.userSecretPath]:o.mfa;const n=speakeasy.generateSecret({name:`${e}: ${t}`});if(!s){s={secret:{temp:void 0,actual:void 0},enabled:!1};o[r.userSecretPath?r.userSecretPath:"mfa"]=s}s.secret.temp=n.base32,s.secret.actual=void 0,await r.putUser(o),qrcode.toDataURL(n.otpauth_url,(e,t)=>{if(e)throw new Error("Error generating QR code");a({qr_code:t,secret:n.base32})})}),mfaVerify=async(e,t,r)=>{var a,i;const o=t;let s=await r.getUser(e);const n=r.userSecretPath?s[r.userSecretPath]:s.mfa;return speakeasy.totp.verify({secret:null===(a=null==n?void 0:n.secret)||void 0===a?void 0:a.temp,encoding:"base32",token:o})?(n.secret.actual=null===(i=null==n?void 0:n.secret)||void 0===i?void 0:i.temp,n.enabled=!0,await r.putUser(s),!0):(console.log(`Failed mfa verification for ${e}`),!1)},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)||!1};export{authenticate,authenticateWithScratchCard,issueJwtToken,mfaEnabled,mfaRegister,mfaVerify,refreshToken};
@@ -8,6 +8,26 @@
8
8
  const qrcode = require('qrcode');
9
9
  const md5 = require("md5");
10
10
  const jwt = require('jsonwebtoken');
11
+ const issueJwtToken = async (user, userProvider, jwtSpecs, issueRefreshToken) => {
12
+ let jwtSecretKey = jwtSpecs.secretKey;
13
+ let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(user) : user;
14
+ clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
15
+ let data = {
16
+ time: Date.now(),
17
+ user: clearedUser
18
+ };
19
+ let token;
20
+ if (issueRefreshToken && jwtSpecs.refreshExpiryTimeMs) {
21
+ token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.refreshExpiryTimeMs });
22
+ }
23
+ else if (jwtSpecs.expiryTimeMs) {
24
+ token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
25
+ }
26
+ return {
27
+ token,
28
+ clearedUser
29
+ };
30
+ };
11
31
  /**
12
32
  * When mfaToken is provided
13
33
  */
@@ -72,19 +92,10 @@
72
92
  }
73
93
  console.info(`Impersonate success. From: ${originalUser.login} into ${target}`);
74
94
  }
75
- // let jwtSecretKey = process.env.JWT_SECRET_KEY;
76
- let jwtSecretKey = jwtSpecs.secretKey;
77
- let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(user) : user;
78
- clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
79
- let data = {
80
- time: Date.now(),
81
- user: clearedUser
82
- };
83
- // const token = jwt.sign(data, jwtSecretKey, {expiresIn: process.env.JWT_EXPIRY_TIME});
84
- const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
95
+ const token = (await issueJwtToken(user, userProvider, jwtSpecs, false)).token;
85
96
  let refreshToken;
86
97
  if (jwtSpecs.refreshExpiryTimeMs)
87
- refreshToken = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.refreshExpiryTimeMs });
98
+ refreshToken = (await issueJwtToken(user, userProvider, jwtSpecs, true)).token;
88
99
  console.log(`Successful login: ${user.id}`);
89
100
  return {
90
101
  token,
@@ -127,19 +138,15 @@
127
138
  throw new Error(`Failed card authentication attempt ${requesterLogin} (Blocked as Target)`);
128
139
  // ok so we will use targetUser as a user that will be actually logged in
129
140
  // in impersonation scenario targetUser may be different then the user.
130
- let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(targetUser) : targetUser;
131
- clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
132
- let jwtSecretKey = jwtSpecs.secretKey;
133
- let data = {
134
- time: Date.now(),
135
- user: clearedUser
136
- };
137
- // const token = jwt.sign(data, jwtSecretKey, {expiresIn: process.env.JWT_EXPIRY_TIME});
138
- const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
141
+ const token = (await issueJwtToken(targetUser, userProvider, jwtSpecs, false)).token;
142
+ let refreshToken;
143
+ if (jwtSpecs.refreshExpiryTimeMs)
144
+ refreshToken = (await issueJwtToken(targetUser, userProvider, jwtSpecs, true)).token;
139
145
  console.info(`Card authentication success. Requester:${requesterLogin} Target:${targetUser.id}`);
140
146
  return {
141
147
  token,
142
- user: clearedUser // just in case its impersonation so the actual resultin user will be different that the requester login user
148
+ refreshToken,
149
+ user: token.clearedUser // just in case its impersonation so the actual resulting user will be different that the requester login user
143
150
  };
144
151
  }
145
152
  catch (error) {
@@ -170,15 +177,9 @@
170
177
  if (!refreshTokenUser || refreshTokenUser.id != user.id) {
171
178
  throw new Error(`Failed refresh token attempt ${login} (Invalid Token)`);
172
179
  }
173
- let clearedUser = userProvider.getSafeUser ? await userProvider.getSafeUser(user) : user;
174
- clearedUser = userProvider.getUserPostAuthenticate ? await userProvider.getUserPostAuthenticate(clearedUser) : clearedUser;
175
- let data = {
176
- time: Date.now(),
177
- user: clearedUser
178
- };
179
- const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
180
+ const token = (await issueJwtToken(user, userProvider, jwtSpecs, false)).token;
180
181
  console.log(`Successful token refresh: ${user.id}`);
181
- return { token: token };
182
+ return { token };
182
183
  }
183
184
  else {
184
185
  throw new Error(`Failed refresh token attempt ${login}`);
@@ -260,6 +261,7 @@
260
261
 
261
262
  exports.authenticate = authenticate;
262
263
  exports.authenticateWithScratchCard = authenticateWithScratchCard;
264
+ exports.issueJwtToken = issueJwtToken;
263
265
  exports.mfaEnabled = mfaEnabled;
264
266
  exports.mfaRegister = mfaRegister;
265
267
  exports.mfaVerify = mfaVerify;
@@ -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"),r=require("qrcode"),a=require("md5"),i=require("jsonwebtoken");e.authenticate=async(e,r,o,n,s,c,l)=>{var d;let u=await s.getUser(e);const f=s.userSecretPath?u[s.userSecretPath]:u.mfa,h=s.userPasswordPath?u[s.userPasswordPath]:u.password;if(null==f?void 0:f.enabled){if(!t.totp.verify({secret:null===(d=null==f?void 0:f.secret)||void 0===d?void 0:d.actual,encoding:"base32",token:o,window:1}))throw new Error(`Failed authentication attempt ${e} (MFA Enabled)`)}if(u.blocked)throw new Error(`Failed authentication attempt ${e} (Blocked)`);if(a(r||"")==h){const e=n,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 s.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=l.secretKey,a=s.getSafeUser?await s.getSafeUser(u):u;a=s.getUserPostAuthenticate?await s.getUserPostAuthenticate(a):a;let o={time:Date.now(),user:a};const d=i.sign(o,r,{expiresIn:l.expiryTimeMs});let f;return l.refreshExpiryTimeMs&&(f=i.sign(o,r,{expiresIn:l.refreshExpiryTimeMs})),console.log(`Successful login: ${u.id}`),{token:d,refreshToken:f}}throw new Error(`Failed authentication attempt ${e}`)},e.authenticateWithScratchCard=async(e,t,r,a,o)=>{let n,s=o?await t.getUser(o):void 0;if(s&&s.blocked)throw new Error(`Failed card authentication attempt ${o} (Blocked)`);if(o&&!s)throw new Error(`Failed card authentication attempt ${o} (Missing user)`);try{n=await r.consume(e,s)}catch(e){throw new Error(`Failed card authentication attempt ${o} (Consume Failed)`)}try{if(!n)throw new Error(`Failed card authentication attempt ${o} (Consume Failed)`);if(n.blocked)throw new Error(`Failed card authentication attempt ${o} (Blocked as Target)`);let e=t.getSafeUser?await t.getSafeUser(n):n;e=t.getUserPostAuthenticate?await t.getUserPostAuthenticate(e):e;let r=a.secretKey,s={time:Date.now(),user:e};const c=i.sign(s,r,{expiresIn:a.expiryTimeMs});return console.info(`Card authentication success. Requester:${o} Target:${n.id}`),{token:c,user:e}}catch(e){throw new Error(`Failed card authentication attempt ${o}`)}},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)||!1},e.mfaRegister=async(e,a,i)=>new Promise(async(o,n)=>{let s=await i.getUser(a),c=i.userSecretPath?s[i.userSecretPath]:s.mfa;const l=t.generateSecret({name:`${e}: ${a}`});if(!c){c={secret:{temp:void 0,actual:void 0},enabled:!1};s[i.userSecretPath?i.userSecretPath:"mfa"]=c}c.secret.temp=l.base32,c.secret.actual=void 0,await i.putUser(s),r.toDataURL(l.otpauth_url,(e,t)=>{if(e)throw new Error("Error generating QR code");o({qr_code:t,secret:l.base32})})}),e.mfaVerify=async(e,r,a)=>{var i,o;const n=r;let s=await a.getUser(e);const c=a.userSecretPath?s[a.userSecretPath]:s.mfa;return t.totp.verify({secret:null===(i=null==c?void 0:c.secret)||void 0===i?void 0:i.temp,encoding:"base32",token:n})?(c.secret.actual=null===(o=null==c?void 0:c.secret)||void 0===o?void 0:o.temp,c.enabled=!0,await a.putUser(s),!0):(console.log(`Failed mfa verification for ${e}`),!1)},e.refreshToken=async(e,t,r,a)=>{let o=await r.getUser(e);if(o.blocked)throw new Error(`Failed refresh token attempt ${e} (Blocked)`);if(t){let n=a.secretKey;const s=i.verify(t,n).user;if(!s||s.id!=o.id)throw new Error(`Failed refresh token attempt ${e} (Invalid Token)`);let c=r.getSafeUser?await r.getSafeUser(o):o;c=r.getUserPostAuthenticate?await r.getUserPostAuthenticate(c):c;let l={time:Date.now(),user:c};const d=i.sign(l,n,{expiresIn:a.expiryTimeMs});return console.log(`Successful token refresh: ${o.id}`),{token:d}}throw new Error(`Failed refresh token attempt ${e}`)},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"),i=async(e,t,r,a)=>{let i=r.secretKey,n=t.getSafeUser?await t.getSafeUser(e):e;n=t.getUserPostAuthenticate?await t.getUserPostAuthenticate(n):n;let s,c={time:Date.now(),user:n};return a&&r.refreshExpiryTimeMs?s=o.sign(c,i,{expiresIn:r.refreshExpiryTimeMs}):r.expiryTimeMs&&(s=o.sign(c,i,{expiresIn:r.expiryTimeMs})),{token:s,clearedUser:n}};e.authenticate=async(e,r,o,n,s,c,l)=>{var d;let u=await s.getUser(e);const f=s.userSecretPath?u[s.userSecretPath]:u.mfa,h=s.userPasswordPath?u[s.userPasswordPath]:u.password;if(null==f?void 0:f.enabled){if(!t.totp.verify({secret:null===(d=null==f?void 0:f.secret)||void 0===d?void 0:d.actual,encoding:"base32",token:o,window:1}))throw new Error(`Failed authentication attempt ${e} (MFA Enabled)`)}if(u.blocked)throw new Error(`Failed authentication attempt ${e} (Blocked)`);if(a(r||"")==h){const e=n,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 s.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}`)}const r=(await i(u,s,l,!1)).token;let a;return l.refreshExpiryTimeMs&&(a=(await i(u,s,l,!0)).token),console.log(`Successful login: ${u.id}`),{token:r,refreshToken:a}}throw new Error(`Failed authentication attempt ${e}`)},e.authenticateWithScratchCard=async(e,t,r,a,o)=>{let n,s=o?await t.getUser(o):void 0;if(s&&s.blocked)throw new Error(`Failed card authentication attempt ${o} (Blocked)`);if(o&&!s)throw new Error(`Failed card authentication attempt ${o} (Missing user)`);try{n=await r.consume(e,s)}catch(e){throw new Error(`Failed card authentication attempt ${o} (Consume Failed)`)}try{if(!n)throw new Error(`Failed card authentication attempt ${o} (Consume Failed)`);if(n.blocked)throw new Error(`Failed card authentication attempt ${o} (Blocked as Target)`);const e=(await i(n,t,a,!1)).token;let r;return a.refreshExpiryTimeMs&&(r=(await i(n,t,a,!0)).token),console.info(`Card authentication success. Requester:${o} Target:${n.id}`),{token:e,refreshToken:r,user:e.clearedUser}}catch(e){throw new Error(`Failed card authentication attempt ${o}`)}},e.issueJwtToken=i,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)||!1},e.mfaRegister=async(e,a,o)=>new Promise(async(i,n)=>{let s=await o.getUser(a),c=o.userSecretPath?s[o.userSecretPath]:s.mfa;const l=t.generateSecret({name:`${e}: ${a}`});if(!c){c={secret:{temp:void 0,actual:void 0},enabled:!1};s[o.userSecretPath?o.userSecretPath:"mfa"]=c}c.secret.temp=l.base32,c.secret.actual=void 0,await o.putUser(s),r.toDataURL(l.otpauth_url,(e,t)=>{if(e)throw new Error("Error generating QR code");i({qr_code:t,secret:l.base32})})}),e.mfaVerify=async(e,r,a)=>{var o,i;const n=r;let s=await a.getUser(e);const c=a.userSecretPath?s[a.userSecretPath]:s.mfa;return t.totp.verify({secret:null===(o=null==c?void 0:c.secret)||void 0===o?void 0:o.temp,encoding:"base32",token:n})?(c.secret.actual=null===(i=null==c?void 0:c.secret)||void 0===i?void 0:i.temp,c.enabled=!0,await a.putUser(s),!0):(console.log(`Failed mfa verification for ${e}`),!1)},e.refreshToken=async(e,t,r,a)=>{let n=await r.getUser(e);if(n.blocked)throw new Error(`Failed refresh token attempt ${e} (Blocked)`);if(t){let s=a.secretKey;const c=o.verify(t,s).user;if(!c||c.id!=n.id)throw new Error(`Failed refresh token attempt ${e} (Invalid Token)`);const l=(await i(n,r,a,!1)).token;return console.log(`Successful token refresh: ${n.id}`),{token:l}}throw new Error(`Failed refresh token attempt ${e}`)},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.33",
3
+ "version": "0.0.34",
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",
package/readme.MD CHANGED
@@ -87,6 +87,21 @@ const isEnabled = await mfaEnabled(login, userProvider);
87
87
  - `login`: The user's login.
88
88
  - `userProvider`: An object implementing the `UserProvider` interface.
89
89
 
90
+ #### `issueJwtToken`
91
+
92
+ Issues JWT token (access-token or refresh-token) for given user under provided specs.
93
+ ```ts
94
+ import { issueJwtToken } from 'pico-auth';
95
+
96
+ const token = await issueJwtToken(user, userProvider, jwtSpecs, issueRefreshToken);
97
+ ```
98
+
99
+ - `user`: The user object.
100
+ - `userProvider`: An object implementing the `UserProvider` interface.
101
+ - `jwtSpecs`: An object containing JWT specifications.
102
+ - `issueRefreshToken`: Boolean value that controls wheter returned token should be created using base specs (false) or refresh specs (true).
103
+ - `token`: An returned object containing short lived `token` or long lived `refreshToken`
104
+
90
105
  ### Types
91
106
 
92
107
  #### `UserProvider`