pico-auth 0.0.32 → 0.0.33

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.
@@ -2,6 +2,7 @@ declare module "core/auth" {
2
2
  export interface JWTSpecs {
3
3
  secretKey: string;
4
4
  expiryTimeMs: any;
5
+ refreshExpiryTimeMs?: any;
5
6
  }
6
7
  export interface UserProvider {
7
8
  getUser(login: string): Promise<BaseUser>;
@@ -26,7 +27,10 @@ declare module "core/auth" {
26
27
  /**
27
28
  * When mfaToken is provided
28
29
  */
29
- export const authenticate: (login: string, password: string, mfaToken: string, impersonateEntity: string, userProvider: UserProvider, impersonateProvider: any, jwtSpecs: JWTSpecs) => Promise<any>;
30
+ export const authenticate: (login: string, password: string, mfaToken: string, impersonateEntity: string, userProvider: UserProvider, impersonateProvider: any, jwtSpecs: JWTSpecs) => Promise<{
31
+ token: any;
32
+ refreshToken: any;
33
+ }>;
30
34
  /**
31
35
  * Allows to login using scratch card. As scratch card may provide a different user to log in to
32
36
  * it also allows to impersonate someone using scratch card.
@@ -41,6 +45,18 @@ declare module "core/auth" {
41
45
  token: any;
42
46
  user: any;
43
47
  }>;
48
+ /**
49
+ * When new short lived token is requested
50
+ * Provides longer lived refresh token to obtain new short lived token
51
+ * @param login
52
+ * @param refreshToken
53
+ * @param userProvider
54
+ * @param jwtSpecs
55
+ * @returns short lived token
56
+ */
57
+ export const refreshToken: (login: string, refreshToken: string, userProvider: UserProvider, jwtSpecs: JWTSpecs) => Promise<{
58
+ token: any;
59
+ }>;
44
60
  /**
45
61
  * Will prepare user for MFA activation. Next step is to call verify with token generated in MFA app by the user.
46
62
  */
@@ -52,6 +68,6 @@ declare module "core/auth" {
52
68
  export const mfaEnabled: (login: string, userProvider: UserProvider) => Promise<any>;
53
69
  }
54
70
  declare module "pico-auth" {
55
- export { mfaRegister, mfaVerify, mfaEnabled, authenticate, authenticateWithScratchCard } from "core/auth";
71
+ export { mfaRegister, mfaVerify, mfaEnabled, authenticate, authenticateWithScratchCard, refreshToken } from "core/auth";
56
72
  export type { UserProvider, ImpersonateProvider, JWTSpecs, ScratchCardProvider, BaseUser } from "core/auth";
57
73
  }
@@ -76,8 +76,14 @@ const authenticate = async (login, password, mfaToken, impersonateEntity, userPr
76
76
  };
77
77
  // const token = jwt.sign(data, jwtSecretKey, {expiresIn: process.env.JWT_EXPIRY_TIME});
78
78
  const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
79
+ let refreshToken;
80
+ if (jwtSpecs.refreshExpiryTimeMs)
81
+ refreshToken = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.refreshExpiryTimeMs });
79
82
  console.log(`Successful login: ${user.id}`);
80
- return token;
83
+ return {
84
+ token,
85
+ refreshToken
86
+ };
81
87
  }
82
88
  else {
83
89
  throw new Error(`Failed authentication attempt ${login}`);
@@ -135,6 +141,43 @@ const authenticateWithScratchCard = async (cardCode, userProvider, scratchCardPr
135
141
  throw new Error(`Failed card authentication attempt ${requesterLogin}`);
136
142
  }
137
143
  };
144
+ /**
145
+ * When new short lived token is requested
146
+ * Provides longer lived refresh token to obtain new short lived token
147
+ * @param login
148
+ * @param refreshToken
149
+ * @param userProvider
150
+ * @param jwtSpecs
151
+ * @returns short lived token
152
+ */
153
+ const refreshToken = async (login, refreshToken, userProvider, jwtSpecs) => {
154
+ let user = await userProvider.getUser(login);
155
+ if (user.blocked)
156
+ throw new Error(`Failed refresh token attempt ${login} (Blocked)`);
157
+ // validate refresh token
158
+ if (refreshToken) {
159
+ // let jwtSecretKey = process.env.JWT_SECRET_KEY;
160
+ let jwtSecretKey = jwtSpecs.secretKey;
161
+ var decoded = jwt.verify(refreshToken, jwtSecretKey);
162
+ // put decoded auth context into request
163
+ const refreshTokenUser = decoded.user;
164
+ if (!refreshTokenUser || refreshTokenUser.id != user.id) {
165
+ throw new Error(`Failed refresh token attempt ${login} (Invalid Token)`);
166
+ }
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
+ console.log(`Successful token refresh: ${user.id}`);
175
+ return { token: token };
176
+ }
177
+ else {
178
+ throw new Error(`Failed refresh token attempt ${login}`);
179
+ }
180
+ };
138
181
  /**
139
182
  * Will prepare user for MFA activation. Next step is to call verify with token generated in MFA app by the user.
140
183
  */
@@ -209,4 +252,4 @@ const mfaEnabled = async (login, userProvider) => {
209
252
  return (mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.enabled) || false;
210
253
  };
211
254
 
212
- export { authenticate, authenticateWithScratchCard, mfaEnabled, mfaRegister, mfaVerify };
255
+ export { authenticate, authenticateWithScratchCard, mfaEnabled, mfaRegister, mfaVerify, refreshToken };
@@ -1 +1 @@
1
- const speakeasy=require("speakeasy"),qrcode=require("qrcode"),md5=require("md5"),jwt=require("jsonwebtoken"),authenticate=async(e,t,a,r,i,o,s)=>{var n;let c=await i.getUser(e);const d=i.userSecretPath?c[i.userSecretPath]:c.mfa,l=i.userPasswordPath?c[i.userPasswordPath]:c.password;if(null==d?void 0:d.enabled){if(!speakeasy.totp.verify({secret:null===(n=null==d?void 0:d.secret)||void 0===n?void 0:n.actual,encoding:"base32",token:a,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||"")==l){const e=r,t=c;if(e){let a=!1;if(e.startsWith("@")){if(a=a||await o.canImpersonate(c,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);await o.impersonateOrg(c,e)}else{const r=await i.getUser(e);if(a=a||await o.canImpersonate(c,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);c=r}console.info(`Impersonate success. From: ${t.login} into ${e}`)}let a=s.secretKey,n=i.getSafeUser?await i.getSafeUser(c):c;n=i.getUserPostAuthenticate?await i.getUserPostAuthenticate(n):n;let d={time:Date.now(),user:n};const l=jwt.sign(d,a,{expiresIn:s.expiryTimeMs});return console.log(`Successful login: ${c.id}`),l}throw new Error(`Failed authentication attempt ${e}`)},authenticateWithScratchCard=async(e,t,a,r,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 a.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)`);let e=t.getSafeUser?await t.getSafeUser(o):o;e=t.getUserPostAuthenticate?await t.getUserPostAuthenticate(e):e;let a=r.secretKey,s={time:Date.now(),user:e};const n=jwt.sign(s,a,{expiresIn:r.expiryTimeMs});return console.info(`Card authentication success. Requester:${i} Target:${o.id}`),{token:n,user:e}}catch(e){throw new Error(`Failed card authentication attempt ${i}`)}},mfaRegister=async(e,t,a)=>new Promise(async(r,i)=>{let o=await a.getUser(t),s=a.userSecretPath?o[a.userSecretPath]:o.mfa;const n=speakeasy.generateSecret({name:`${e}: ${t}`});if(!s){s={secret:{temp:void 0,actual:void 0},enabled:!1};o[a.userSecretPath?a.userSecretPath:"mfa"]=s}s.secret.temp=n.base32,s.secret.actual=void 0,await a.putUser(o),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,i;const o=t;let s=await a.getUser(e);const n=a.userSecretPath?s[a.userSecretPath]:s.mfa;return speakeasy.totp.verify({secret:null===(r=null==n?void 0:n.secret)||void 0===r?void 0:r.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 a.putUser(s),!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)||!1};export{authenticate,authenticateWithScratchCard,mfaEnabled,mfaRegister,mfaVerify};
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};
@@ -82,8 +82,14 @@
82
82
  };
83
83
  // const token = jwt.sign(data, jwtSecretKey, {expiresIn: process.env.JWT_EXPIRY_TIME});
84
84
  const token = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.expiryTimeMs });
85
+ let refreshToken;
86
+ if (jwtSpecs.refreshExpiryTimeMs)
87
+ refreshToken = jwt.sign(data, jwtSecretKey, { expiresIn: jwtSpecs.refreshExpiryTimeMs });
85
88
  console.log(`Successful login: ${user.id}`);
86
- return token;
89
+ return {
90
+ token,
91
+ refreshToken
92
+ };
87
93
  }
88
94
  else {
89
95
  throw new Error(`Failed authentication attempt ${login}`);
@@ -141,6 +147,43 @@
141
147
  throw new Error(`Failed card authentication attempt ${requesterLogin}`);
142
148
  }
143
149
  };
150
+ /**
151
+ * When new short lived token is requested
152
+ * Provides longer lived refresh token to obtain new short lived token
153
+ * @param login
154
+ * @param refreshToken
155
+ * @param userProvider
156
+ * @param jwtSpecs
157
+ * @returns short lived token
158
+ */
159
+ const refreshToken = async (login, refreshToken, userProvider, jwtSpecs) => {
160
+ let user = await userProvider.getUser(login);
161
+ if (user.blocked)
162
+ throw new Error(`Failed refresh token attempt ${login} (Blocked)`);
163
+ // validate refresh token
164
+ if (refreshToken) {
165
+ // let jwtSecretKey = process.env.JWT_SECRET_KEY;
166
+ let jwtSecretKey = jwtSpecs.secretKey;
167
+ var decoded = jwt.verify(refreshToken, jwtSecretKey);
168
+ // put decoded auth context into request
169
+ const refreshTokenUser = decoded.user;
170
+ if (!refreshTokenUser || refreshTokenUser.id != user.id) {
171
+ throw new Error(`Failed refresh token attempt ${login} (Invalid Token)`);
172
+ }
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
+ console.log(`Successful token refresh: ${user.id}`);
181
+ return { token: token };
182
+ }
183
+ else {
184
+ throw new Error(`Failed refresh token attempt ${login}`);
185
+ }
186
+ };
144
187
  /**
145
188
  * Will prepare user for MFA activation. Next step is to call verify with token generated in MFA app by the user.
146
189
  */
@@ -220,6 +263,7 @@
220
263
  exports.mfaEnabled = mfaEnabled;
221
264
  exports.mfaRegister = mfaRegister;
222
265
  exports.mfaVerify = mfaVerify;
266
+ exports.refreshToken = refreshToken;
223
267
 
224
268
  Object.defineProperty(exports, '__esModule', { value: true });
225
269
 
@@ -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"),a=require("qrcode"),r=require("md5"),i=require("jsonwebtoken");e.authenticate=async(e,a,o,n,s,c,l)=>{var d;let u=await s.getUser(e);const h=s.userSecretPath?u[s.userSecretPath]:u.mfa,f=s.userPasswordPath?u[s.userPasswordPath]:u.password;if(null==h?void 0:h.enabled){if(!t.totp.verify({secret:null===(d=null==h?void 0:h.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(r(a||"")==f){const e=n,t=u;if(e){let a=!1;if(e.startsWith("@")){if(a=a||await c.canImpersonate(u,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);await c.impersonateOrg(u,e)}else{const r=await s.getUser(e);if(a=a||await c.canImpersonate(u,e),!a)throw new Error(`Failed impersonate attempt. From: ${t.id} into ${e}`);u=r}console.info(`Impersonate success. From: ${t.login} into ${e}`)}let a=l.secretKey,r=s.getSafeUser?await s.getSafeUser(u):u;r=s.getUserPostAuthenticate?await s.getUserPostAuthenticate(r):r;let o={time:Date.now(),user:r};const d=i.sign(o,a,{expiresIn:l.expiryTimeMs});return console.log(`Successful login: ${u.id}`),d}throw new Error(`Failed authentication attempt ${e}`)},e.authenticateWithScratchCard=async(e,t,a,r,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 a.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 a=r.secretKey,s={time:Date.now(),user:e};const c=i.sign(s,a,{expiresIn:r.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 a=await t.getUser(e);const r=t.userSecretPath?a[t.userSecretPath]:a.mfa;return(null==r?void 0:r.enabled)||!1},e.mfaRegister=async(e,r,i)=>new Promise(async(o,n)=>{let s=await i.getUser(r),c=i.userSecretPath?s[i.userSecretPath]:s.mfa;const l=t.generateSecret({name:`${e}: ${r}`});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),a.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,a,r)=>{var i,o;const n=a;let s=await r.getUser(e);const c=r.userSecretPath?s[r.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 r.putUser(s),!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"),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})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pico-auth",
3
- "version": "0.0.32",
3
+ "version": "0.0.33",
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
@@ -19,7 +19,7 @@ Authenticates a user with login, password, and optionally an MFA token and imper
19
19
  ```ts
20
20
  import { authenticate } from 'pico-auth';
21
21
 
22
- const token = await authenticate(login, password, mfaToken, impersonateEntity, userProvider, impersonateProvider, jwtSpecs);
22
+ const tokens = await authenticate(login, password, mfaToken, impersonateEntity, userProvider, impersonateProvider, jwtSpecs);
23
23
  ```
24
24
 
25
25
  - `login`: The user's login.
@@ -29,6 +29,22 @@ const token = await authenticate(login, password, mfaToken, impersonateEntity, u
29
29
  - `userProvider`: An object implementing the `UserProvider` interface.
30
30
  - `impersonateProvider`: An object implementing the `ImpersonateProvider` interface.
31
31
  - `jwtSpecs`: An object containing JWT specifications.
32
+ - `tokens`: An returned object containing fields: short lived `token` and long lived `refreshToken`
33
+
34
+ #### `refreshToken`
35
+
36
+ Refresh token when new short lived token is requested
37
+
38
+ ```ts
39
+ import { refreshToken } from 'pico-auth';
40
+
41
+ const token = await refreshToken(login, refreshToken, userProvider, jwtSpecs);
42
+ ```
43
+
44
+ - `login`: The user's login.
45
+ - `userProvider`: An object implementing the `UserProvider` interface.
46
+ - `jwtSpecs`: An object containing JWT specifications.
47
+ - `token`: An returned object containing field: short lived `token`
32
48
 
33
49
  #### `mfaRegister`
34
50