@adminforth/two-factors-auth 1.0.20 → 1.0.21
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/package.json +1 -1
- package/index.js +0 -148
- package/types.js +0 -2
package/package.json
CHANGED
package/index.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const adminforth_1 = require("adminforth");
|
|
16
|
-
const node_2fa_1 = __importDefault(require("node-2fa"));
|
|
17
|
-
class TwoFactorsAuthPlugin extends adminforth_1.AdminForthPlugin {
|
|
18
|
-
constructor(options) {
|
|
19
|
-
super(options, import.meta.url);
|
|
20
|
-
this.options = options;
|
|
21
|
-
}
|
|
22
|
-
instanceUniqueRepresentation(pluginOptions) {
|
|
23
|
-
return `single`;
|
|
24
|
-
}
|
|
25
|
-
modifyResourceConfig(adminforth, resourceConfig) {
|
|
26
|
-
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
27
|
-
this.adminforth = adminforth;
|
|
28
|
-
this.adminForthAuth = adminforth.auth;
|
|
29
|
-
const customPages = this.adminforth.config.customization.customPages;
|
|
30
|
-
customPages.push({
|
|
31
|
-
path: '/confirm2fa',
|
|
32
|
-
component: { file: this.componentPath('TwoFactorsConfirmation.vue'), meta: { customLayout: true } }
|
|
33
|
-
});
|
|
34
|
-
customPages.push({
|
|
35
|
-
path: '/setup2fa',
|
|
36
|
-
component: { file: this.componentPath('TwoFactorsSetup.vue'), meta: { title: 'Setup 2FA', customLayout: true } }
|
|
37
|
-
});
|
|
38
|
-
this.activate(resourceConfig, adminforth);
|
|
39
|
-
}
|
|
40
|
-
activate(resourceConfig, adminforth) {
|
|
41
|
-
if (!this.options.twoFaSecretFieldName) {
|
|
42
|
-
throw new Error('twoFaSecretFieldName is required');
|
|
43
|
-
}
|
|
44
|
-
if (typeof this.options.twoFaSecretFieldName !== 'string') {
|
|
45
|
-
throw new Error('twoFaSecretFieldName must be a string');
|
|
46
|
-
}
|
|
47
|
-
this.authResource = resourceConfig;
|
|
48
|
-
if (!this.authResource.columns.some((col) => col.name === this.options.twoFaSecretFieldName)) {
|
|
49
|
-
throw new Error(`Column ${this.options.twoFaSecretFieldName} not found in ${this.authResource.label}`);
|
|
50
|
-
}
|
|
51
|
-
this.adminforth.config.auth.beforeLoginConfirmation.push((_a) => __awaiter(this, [_a], void 0, function* ({ adminUser, response }) {
|
|
52
|
-
const secret = adminUser.dbUser[this.options.twoFaSecretFieldName];
|
|
53
|
-
const userName = adminUser.dbUser[adminforth.config.auth.usernameField];
|
|
54
|
-
const brandName = adminforth.config.customization.brandName;
|
|
55
|
-
const authResource = adminforth.config.resources.find((res) => res.resourceId === adminforth.config.auth.usersResourceId);
|
|
56
|
-
const authPk = authResource.columns.find((col) => col.primaryKey).name;
|
|
57
|
-
const userPk = adminUser.dbUser[authPk];
|
|
58
|
-
let newSecret = null;
|
|
59
|
-
const userNeeds2FA = this.options.usersFilterToApply ? this.options.usersFilterToApply(adminUser) : true;
|
|
60
|
-
if (!userNeeds2FA) {
|
|
61
|
-
return { body: { loginAllowed: true }, ok: true };
|
|
62
|
-
}
|
|
63
|
-
if (!secret) {
|
|
64
|
-
const tempSecret = node_2fa_1.default.generateSecret({ name: brandName, account: userName });
|
|
65
|
-
newSecret = tempSecret.secret;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
const value = this.adminforth.auth.issueJWT({ userName, issuer: brandName, pk: userPk }, 'tempTotp', '2h');
|
|
69
|
-
response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; max-age=3600; `);
|
|
70
|
-
return {
|
|
71
|
-
body: {
|
|
72
|
-
loginAllowed: false,
|
|
73
|
-
redirectTo: '/confirm2fa',
|
|
74
|
-
},
|
|
75
|
-
ok: true
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
const totpTemporaryJWT = this.adminforth.auth.issueJWT({ userName, newSecret, issuer: brandName, pk: userPk }, 'tempTotp', '2h');
|
|
79
|
-
response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${totpTemporaryJWT}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + '1h').toUTCString()} `);
|
|
80
|
-
return {
|
|
81
|
-
body: {
|
|
82
|
-
loginAllowed: false,
|
|
83
|
-
redirectTo: secret ? '/confirm2fa' : '/setup2fa',
|
|
84
|
-
},
|
|
85
|
-
ok: true
|
|
86
|
-
};
|
|
87
|
-
}));
|
|
88
|
-
}
|
|
89
|
-
setupEndpoints(server) {
|
|
90
|
-
server.endpoint({
|
|
91
|
-
method: 'POST',
|
|
92
|
-
path: `/plugin/twofa/initSetup`,
|
|
93
|
-
noAuth: true,
|
|
94
|
-
handler: (server) => __awaiter(this, void 0, void 0, function* () {
|
|
95
|
-
var _a;
|
|
96
|
-
const toReturn = { totpJWT: null, status: 'ok', };
|
|
97
|
-
const totpTemporaryJWT = (_a = server.cookies.find((cookie) => cookie.key === 'adminforth_totpTemporaryJWT')) === null || _a === void 0 ? void 0 : _a.value;
|
|
98
|
-
if (totpTemporaryJWT) {
|
|
99
|
-
toReturn.totpJWT = totpTemporaryJWT;
|
|
100
|
-
}
|
|
101
|
-
return toReturn;
|
|
102
|
-
})
|
|
103
|
-
});
|
|
104
|
-
server.endpoint({
|
|
105
|
-
method: 'POST',
|
|
106
|
-
path: `/plugin/twofa/confirmSetup`,
|
|
107
|
-
noAuth: true,
|
|
108
|
-
handler: (_b) => __awaiter(this, [_b], void 0, function* ({ body, adminUser, response, cookies }) {
|
|
109
|
-
var _c;
|
|
110
|
-
const totpTemporaryJWT = (_c = cookies.find((cookie) => cookie.key === 'adminforth_totpTemporaryJWT')) === null || _c === void 0 ? void 0 : _c.value;
|
|
111
|
-
const decoded = yield this.adminforth.auth.verify(totpTemporaryJWT, 'tempTotp');
|
|
112
|
-
if (!decoded) {
|
|
113
|
-
return { status: 'error', message: 'Invalid token' };
|
|
114
|
-
}
|
|
115
|
-
if (decoded.newSecret) {
|
|
116
|
-
const verified = node_2fa_1.default.verifyToken(decoded.newSecret, body.code);
|
|
117
|
-
if (verified) {
|
|
118
|
-
this.connectors = this.adminforth.connectors;
|
|
119
|
-
const connector = this.connectors[this.authResource.dataSource];
|
|
120
|
-
yield connector.updateRecord({ resource: this.authResource, recordId: decoded.pk, newValues: { [this.options.twoFaSecretFieldName]: decoded.newSecret } });
|
|
121
|
-
this.adminforth.auth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
|
|
122
|
-
this.adminforth.auth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
|
|
123
|
-
return { status: 'ok', allowedLogin: true };
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
return { error: 'Wrong or expired OTP code' };
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
// user already has secret, get it
|
|
131
|
-
this.connectors = this.adminforth.connectors;
|
|
132
|
-
const connector = this.connectors[this.authResource.dataSource];
|
|
133
|
-
const user = yield connector.getRecordByPrimaryKey(this.authResource, decoded.pk);
|
|
134
|
-
const verified = node_2fa_1.default.verifyToken(user[this.options.twoFaSecretFieldName], body.code);
|
|
135
|
-
if (verified) {
|
|
136
|
-
this.adminforth.auth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
|
|
137
|
-
this.adminforth.auth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
|
|
138
|
-
return { status: 'ok', allowedLogin: true };
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
return { error: 'Wrong or expired OTP code' };
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
exports.default = TwoFactorsAuthPlugin;
|
package/types.js
DELETED