pico-auth 0.0.32 → 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.
- package/dist/pico-auth.d.ts +23 -2
- package/dist/pico-auth.esm.js +66 -22
- package/dist/pico-auth.esm.min.js +1 -1
- package/dist/pico-auth.umd.js +67 -21
- package/dist/pico-auth.umd.min.js +1 -1
- package/package.json +1 -1
- package/readme.MD +32 -1
package/dist/pico-auth.d.ts
CHANGED
|
@@ -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>;
|
|
@@ -23,10 +24,17 @@ declare module "core/auth" {
|
|
|
23
24
|
blocked?: boolean;
|
|
24
25
|
[key: string]: any;
|
|
25
26
|
}
|
|
27
|
+
export const issueJwtToken: (user: BaseUser, userProvider: UserProvider, jwtSpecs: JWTSpecs, issueRefreshToken: boolean) => Promise<{
|
|
28
|
+
token: any;
|
|
29
|
+
clearedUser: BaseUser;
|
|
30
|
+
}>;
|
|
26
31
|
/**
|
|
27
32
|
* When mfaToken is provided
|
|
28
33
|
*/
|
|
29
|
-
export const authenticate: (login: string, password: string, mfaToken: string, impersonateEntity: string, userProvider: UserProvider, impersonateProvider: any, jwtSpecs: JWTSpecs) => Promise<
|
|
34
|
+
export const authenticate: (login: string, password: string, mfaToken: string, impersonateEntity: string, userProvider: UserProvider, impersonateProvider: any, jwtSpecs: JWTSpecs) => Promise<{
|
|
35
|
+
token: any;
|
|
36
|
+
refreshToken: any;
|
|
37
|
+
}>;
|
|
30
38
|
/**
|
|
31
39
|
* Allows to login using scratch card. As scratch card may provide a different user to log in to
|
|
32
40
|
* it also allows to impersonate someone using scratch card.
|
|
@@ -39,8 +47,21 @@ declare module "core/auth" {
|
|
|
39
47
|
*/
|
|
40
48
|
export const authenticateWithScratchCard: (cardCode: string, userProvider: UserProvider, scratchCardProvider: ScratchCardProvider, jwtSpecs: JWTSpecs, requesterLogin?: string) => Promise<{
|
|
41
49
|
token: any;
|
|
50
|
+
refreshToken: any;
|
|
42
51
|
user: any;
|
|
43
52
|
}>;
|
|
53
|
+
/**
|
|
54
|
+
* When new short lived token is requested
|
|
55
|
+
* Provides longer lived refresh token to obtain new short lived token
|
|
56
|
+
* @param login
|
|
57
|
+
* @param refreshToken
|
|
58
|
+
* @param userProvider
|
|
59
|
+
* @param jwtSpecs
|
|
60
|
+
* @returns short lived token
|
|
61
|
+
*/
|
|
62
|
+
export const refreshToken: (login: string, refreshToken: string, userProvider: UserProvider, jwtSpecs: JWTSpecs) => Promise<{
|
|
63
|
+
token: any;
|
|
64
|
+
}>;
|
|
44
65
|
/**
|
|
45
66
|
* Will prepare user for MFA activation. Next step is to call verify with token generated in MFA app by the user.
|
|
46
67
|
*/
|
|
@@ -52,6 +73,6 @@ declare module "core/auth" {
|
|
|
52
73
|
export const mfaEnabled: (login: string, userProvider: UserProvider) => Promise<any>;
|
|
53
74
|
}
|
|
54
75
|
declare module "pico-auth" {
|
|
55
|
-
export { mfaRegister, mfaVerify, mfaEnabled, authenticate, authenticateWithScratchCard } from "core/auth";
|
|
76
|
+
export { mfaRegister, mfaVerify, mfaEnabled, authenticate, authenticateWithScratchCard, refreshToken, issueJwtToken } from "core/auth";
|
|
56
77
|
export type { UserProvider, ImpersonateProvider, JWTSpecs, ScratchCardProvider, BaseUser } from "core/auth";
|
|
57
78
|
}
|
package/dist/pico-auth.esm.js
CHANGED
|
@@ -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,18 +86,15 @@ const authenticate = async (login, password, mfaToken, impersonateEntity, userPr
|
|
|
66
86
|
}
|
|
67
87
|
console.info(`Impersonate success. From: ${originalUser.login} into ${target}`);
|
|
68
88
|
}
|
|
69
|
-
|
|
70
|
-
let
|
|
71
|
-
|
|
72
|
-
|
|
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;
|
|
90
|
+
let refreshToken;
|
|
91
|
+
if (jwtSpecs.refreshExpiryTimeMs)
|
|
92
|
+
refreshToken = (await issueJwtToken(user, userProvider, jwtSpecs, true)).token;
|
|
79
93
|
console.log(`Successful login: ${user.id}`);
|
|
80
|
-
return
|
|
94
|
+
return {
|
|
95
|
+
token,
|
|
96
|
+
refreshToken
|
|
97
|
+
};
|
|
81
98
|
}
|
|
82
99
|
else {
|
|
83
100
|
throw new Error(`Failed authentication attempt ${login}`);
|
|
@@ -115,19 +132,15 @@ const authenticateWithScratchCard = async (cardCode, userProvider, scratchCardPr
|
|
|
115
132
|
throw new Error(`Failed card authentication attempt ${requesterLogin} (Blocked as Target)`);
|
|
116
133
|
// ok so we will use targetUser as a user that will be actually logged in
|
|
117
134
|
// in impersonation scenario targetUser may be different then the user.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
time: Date.now(),
|
|
123
|
-
user: clearedUser
|
|
124
|
-
};
|
|
125
|
-
// const token = jwt.sign(data, jwtSecretKey, {expiresIn: process.env.JWT_EXPIRY_TIME});
|
|
126
|
-
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;
|
|
127
139
|
console.info(`Card authentication success. Requester:${requesterLogin} Target:${targetUser.id}`);
|
|
128
140
|
return {
|
|
129
141
|
token,
|
|
130
|
-
|
|
142
|
+
refreshToken,
|
|
143
|
+
user: token.clearedUser // just in case its impersonation so the actual resulting user will be different that the requester login user
|
|
131
144
|
};
|
|
132
145
|
}
|
|
133
146
|
catch (error) {
|
|
@@ -135,6 +148,37 @@ const authenticateWithScratchCard = async (cardCode, userProvider, scratchCardPr
|
|
|
135
148
|
throw new Error(`Failed card authentication attempt ${requesterLogin}`);
|
|
136
149
|
}
|
|
137
150
|
};
|
|
151
|
+
/**
|
|
152
|
+
* When new short lived token is requested
|
|
153
|
+
* Provides longer lived refresh token to obtain new short lived token
|
|
154
|
+
* @param login
|
|
155
|
+
* @param refreshToken
|
|
156
|
+
* @param userProvider
|
|
157
|
+
* @param jwtSpecs
|
|
158
|
+
* @returns short lived token
|
|
159
|
+
*/
|
|
160
|
+
const refreshToken = async (login, refreshToken, userProvider, jwtSpecs) => {
|
|
161
|
+
let user = await userProvider.getUser(login);
|
|
162
|
+
if (user.blocked)
|
|
163
|
+
throw new Error(`Failed refresh token attempt ${login} (Blocked)`);
|
|
164
|
+
// validate refresh token
|
|
165
|
+
if (refreshToken) {
|
|
166
|
+
// let jwtSecretKey = process.env.JWT_SECRET_KEY;
|
|
167
|
+
let jwtSecretKey = jwtSpecs.secretKey;
|
|
168
|
+
var decoded = jwt.verify(refreshToken, jwtSecretKey);
|
|
169
|
+
// put decoded auth context into request
|
|
170
|
+
const refreshTokenUser = decoded.user;
|
|
171
|
+
if (!refreshTokenUser || refreshTokenUser.id != user.id) {
|
|
172
|
+
throw new Error(`Failed refresh token attempt ${login} (Invalid Token)`);
|
|
173
|
+
}
|
|
174
|
+
const token = (await issueJwtToken(user, userProvider, jwtSpecs, false)).token;
|
|
175
|
+
console.log(`Successful token refresh: ${user.id}`);
|
|
176
|
+
return { token };
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
throw new Error(`Failed refresh token attempt ${login}`);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
138
182
|
/**
|
|
139
183
|
* Will prepare user for MFA activation. Next step is to call verify with token generated in MFA app by the user.
|
|
140
184
|
*/
|
|
@@ -209,4 +253,4 @@ const mfaEnabled = async (login, userProvider) => {
|
|
|
209
253
|
return (mfaInfo === null || mfaInfo === void 0 ? void 0 : mfaInfo.enabled) || false;
|
|
210
254
|
};
|
|
211
255
|
|
|
212
|
-
export { authenticate, authenticateWithScratchCard, mfaEnabled, mfaRegister, mfaVerify };
|
|
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"),
|
|
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};
|
package/dist/pico-auth.umd.js
CHANGED
|
@@ -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,18 +92,15 @@
|
|
|
72
92
|
}
|
|
73
93
|
console.info(`Impersonate success. From: ${originalUser.login} into ${target}`);
|
|
74
94
|
}
|
|
75
|
-
|
|
76
|
-
let
|
|
77
|
-
|
|
78
|
-
|
|
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;
|
|
96
|
+
let refreshToken;
|
|
97
|
+
if (jwtSpecs.refreshExpiryTimeMs)
|
|
98
|
+
refreshToken = (await issueJwtToken(user, userProvider, jwtSpecs, true)).token;
|
|
85
99
|
console.log(`Successful login: ${user.id}`);
|
|
86
|
-
return
|
|
100
|
+
return {
|
|
101
|
+
token,
|
|
102
|
+
refreshToken
|
|
103
|
+
};
|
|
87
104
|
}
|
|
88
105
|
else {
|
|
89
106
|
throw new Error(`Failed authentication attempt ${login}`);
|
|
@@ -121,19 +138,15 @@
|
|
|
121
138
|
throw new Error(`Failed card authentication attempt ${requesterLogin} (Blocked as Target)`);
|
|
122
139
|
// ok so we will use targetUser as a user that will be actually logged in
|
|
123
140
|
// in impersonation scenario targetUser may be different then the user.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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 });
|
|
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;
|
|
133
145
|
console.info(`Card authentication success. Requester:${requesterLogin} Target:${targetUser.id}`);
|
|
134
146
|
return {
|
|
135
147
|
token,
|
|
136
|
-
|
|
148
|
+
refreshToken,
|
|
149
|
+
user: token.clearedUser // just in case its impersonation so the actual resulting user will be different that the requester login user
|
|
137
150
|
};
|
|
138
151
|
}
|
|
139
152
|
catch (error) {
|
|
@@ -141,6 +154,37 @@
|
|
|
141
154
|
throw new Error(`Failed card authentication attempt ${requesterLogin}`);
|
|
142
155
|
}
|
|
143
156
|
};
|
|
157
|
+
/**
|
|
158
|
+
* When new short lived token is requested
|
|
159
|
+
* Provides longer lived refresh token to obtain new short lived token
|
|
160
|
+
* @param login
|
|
161
|
+
* @param refreshToken
|
|
162
|
+
* @param userProvider
|
|
163
|
+
* @param jwtSpecs
|
|
164
|
+
* @returns short lived token
|
|
165
|
+
*/
|
|
166
|
+
const refreshToken = async (login, refreshToken, userProvider, jwtSpecs) => {
|
|
167
|
+
let user = await userProvider.getUser(login);
|
|
168
|
+
if (user.blocked)
|
|
169
|
+
throw new Error(`Failed refresh token attempt ${login} (Blocked)`);
|
|
170
|
+
// validate refresh token
|
|
171
|
+
if (refreshToken) {
|
|
172
|
+
// let jwtSecretKey = process.env.JWT_SECRET_KEY;
|
|
173
|
+
let jwtSecretKey = jwtSpecs.secretKey;
|
|
174
|
+
var decoded = jwt.verify(refreshToken, jwtSecretKey);
|
|
175
|
+
// put decoded auth context into request
|
|
176
|
+
const refreshTokenUser = decoded.user;
|
|
177
|
+
if (!refreshTokenUser || refreshTokenUser.id != user.id) {
|
|
178
|
+
throw new Error(`Failed refresh token attempt ${login} (Invalid Token)`);
|
|
179
|
+
}
|
|
180
|
+
const token = (await issueJwtToken(user, userProvider, jwtSpecs, false)).token;
|
|
181
|
+
console.log(`Successful token refresh: ${user.id}`);
|
|
182
|
+
return { token };
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
throw new Error(`Failed refresh token attempt ${login}`);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
144
188
|
/**
|
|
145
189
|
* Will prepare user for MFA activation. Next step is to call verify with token generated in MFA app by the user.
|
|
146
190
|
*/
|
|
@@ -217,9 +261,11 @@
|
|
|
217
261
|
|
|
218
262
|
exports.authenticate = authenticate;
|
|
219
263
|
exports.authenticateWithScratchCard = authenticateWithScratchCard;
|
|
264
|
+
exports.issueJwtToken = issueJwtToken;
|
|
220
265
|
exports.mfaEnabled = mfaEnabled;
|
|
221
266
|
exports.mfaRegister = mfaRegister;
|
|
222
267
|
exports.mfaVerify = mfaVerify;
|
|
268
|
+
exports.refreshToken = refreshToken;
|
|
223
269
|
|
|
224
270
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
225
271
|
|
|
@@ -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"),
|
|
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
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
|
|
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
|
|
|
@@ -71,6 +87,21 @@ const isEnabled = await mfaEnabled(login, userProvider);
|
|
|
71
87
|
- `login`: The user's login.
|
|
72
88
|
- `userProvider`: An object implementing the `UserProvider` interface.
|
|
73
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
|
+
|
|
74
105
|
### Types
|
|
75
106
|
|
|
76
107
|
#### `UserProvider`
|