feat: Add two-factor authentication via TOTP
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.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
const { AccessTokenSteps } = require('../../../constants');
|
||||
const { AccessTokenSteps, TRUST_DEVICE_COOKIE_NAME } = require('../../../constants');
|
||||
|
||||
const Errors = {
|
||||
ADMIN_LOGIN_REQUIRED_TO_INITIALIZE_INSTANCE: {
|
||||
@@ -39,6 +39,7 @@ module.exports = {
|
||||
exits: {
|
||||
adminLoginRequiredToInitializeInstance: {},
|
||||
termsAcceptanceRequired: {},
|
||||
totpVerificationRequired: {},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
@@ -91,6 +92,53 @@ module.exports = {
|
||||
};
|
||||
}
|
||||
|
||||
if (inputs.user.isTotpEnabled) {
|
||||
const trustCookie =
|
||||
inputs.request.cookies && inputs.request.cookies[TRUST_DEVICE_COOKIE_NAME];
|
||||
|
||||
const isDeviceTrusted = trustCookie
|
||||
? await sails.helpers.trustedDevices.checkToken.with({
|
||||
userId: inputs.user.id,
|
||||
plainToken: trustCookie,
|
||||
})
|
||||
: false;
|
||||
|
||||
if (!isDeviceTrusted) {
|
||||
const { token: pendingToken, payload: pendingTokenPayload } =
|
||||
sails.helpers.utils.createJwtToken(
|
||||
AccessTokenSteps.VERIFY_TOTP,
|
||||
undefined,
|
||||
PENDING_TOKEN_EXPIRES_IN,
|
||||
);
|
||||
|
||||
const session = await sails.helpers.sessions.createOne.with({
|
||||
values: {
|
||||
pendingToken,
|
||||
userId: inputs.user.id,
|
||||
remoteAddress: inputs.remoteAddress,
|
||||
userAgent: inputs.request.headers['user-agent'],
|
||||
},
|
||||
withHttpOnlyToken: inputs.withHttpOnlyToken,
|
||||
});
|
||||
|
||||
if (session.httpOnlyToken && !inputs.request.isSocket) {
|
||||
sails.helpers.utils.setHttpOnlyTokenCookie(
|
||||
session.httpOnlyToken,
|
||||
pendingTokenPayload,
|
||||
inputs.response,
|
||||
);
|
||||
}
|
||||
|
||||
throw {
|
||||
totpVerificationRequired: {
|
||||
pendingToken,
|
||||
message: 'TOTP verification required',
|
||||
step: AccessTokenSteps.VERIFY_TOTP,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const { token: accessToken, payload: accessTokenPayload } = sails.helpers.utils.createJwtToken(
|
||||
inputs.user.id,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user