Adds TOTP setup with QR code, login challenge, recovery codes and trusted devices that let a browser skip the second factor for 30 days. Admins can reset another user's second factor by confirming with their own password.
59 lines
1.6 KiB
JavaScript
59 lines
1.6 KiB
JavaScript
/*!
|
|
* Copyright (c) 2024 PLANKA Software GmbH
|
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
|
*/
|
|
|
|
const bcrypt = require('bcrypt');
|
|
const crypto = require('crypto');
|
|
|
|
const { TRUST_DEVICE_EXPIRES_IN_DAYS } = require('../../../constants');
|
|
|
|
const TOKEN_BYTES = 32;
|
|
const BCRYPT_ROUNDS = 10;
|
|
|
|
const buildUserAgentSummary = (userAgent) => {
|
|
if (!userAgent) return null;
|
|
return userAgent.length > 200 ? userAgent.slice(0, 200) : userAgent;
|
|
};
|
|
|
|
module.exports = {
|
|
inputs: {
|
|
userId: {
|
|
type: 'string',
|
|
required: true,
|
|
},
|
|
userAgent: {
|
|
type: 'string',
|
|
allowNull: true,
|
|
},
|
|
},
|
|
|
|
async fn(inputs) {
|
|
const plainToken = crypto.randomBytes(TOKEN_BYTES).toString('base64url');
|
|
const tokenHash = await bcrypt.hash(plainToken, BCRYPT_ROUNDS);
|
|
|
|
const expiresAt = new Date(
|
|
Date.now() + TRUST_DEVICE_EXPIRES_IN_DAYS * 24 * 60 * 60 * 1000,
|
|
).toISOString();
|
|
|
|
const fingerprint = sails.helpers.utils.parseUserAgent.with({ userAgent: inputs.userAgent });
|
|
|
|
const record = await TrustedDevice.qm.createOne({
|
|
userId: inputs.userId,
|
|
tokenHash,
|
|
userAgentSummary: buildUserAgentSummary(inputs.userAgent),
|
|
browserName: fingerprint.browserName,
|
|
browserVersion: fingerprint.browserVersion,
|
|
osName: fingerprint.osName,
|
|
osVersion: fingerprint.osVersion,
|
|
deviceType: fingerprint.deviceType,
|
|
deviceVendor: fingerprint.deviceVendor,
|
|
deviceModel: fingerprint.deviceModel,
|
|
expiresAt,
|
|
lastUsedAt: new Date().toISOString(),
|
|
});
|
|
|
|
return { record, plainToken };
|
|
},
|
|
};
|