added test for two factor authentication

This commit is contained in:
courage173
2021-06-09 15:45:25 +01:00
parent 2eb9240897
commit 7ce81ca715
4 changed files with 281 additions and 16 deletions

View File

@@ -23,7 +23,7 @@ class TwoFactorAuthModal extends Component {
profileSettings: { data },
generateTwoFactorQRCode,
} = this.props;
generateTwoFactorQRCode(data.id);
generateTwoFactorQRCode(data.id || data._id);
window.addEventListener('keydown', this.handleKeyBoard);
}
@@ -72,7 +72,7 @@ class TwoFactorAuthModal extends Component {
verifyTwoFactorAuthToken,
profileSettings,
} = this.props;
values.userId = profileSettings.data.id;
values.userId = profileSettings.data.id || profileSettings.data._id;
verifyTwoFactorAuthToken(values).then(response => {
setTwoFactorAuth(response.data.twoFactorAuthEnabled);
this.props.closeThisDialog();
@@ -221,19 +221,73 @@ class TwoFactorAuthModal extends Component {
</div>
{qrCode.data
.otpauth_url ? (
<QRCode
size={
230
}
value={`${qrCode.data.otpauth_url}`}
style={{
display:
'block',
margin:
'0 auto',
}}
id="qr-code"
/>
<>
<QRCode
size={
230
}
value={`${qrCode.data.otpauth_url}`}
style={{
display:
'block',
margin:
'0 auto',
}}
id="qr-code"
/>
<div
style={{
marginTop:
'20px',
}}
>
<span>
You
can
also
add
the
QR
code
below
directly
on
Google
Auhenticator
app
or
Authy
</span>
</div>
<div
style={{
marginTop:
'14px',
textAlign:
'center',
}}
>
<span>
QR
Code:
</span>
<span
style={{
textDecoration:
'underline',
}}
id="otpath-url"
>
{' '}
{
qrCode.data.otpauth_url.split(
'secret='
)[1]
}
</span>
</div>
</>
) : (
<ListLoader />
)}

View File

@@ -1272,6 +1272,7 @@ export class ProfileSetting extends Component {
style={{
marginTop: '10px',
}}
id="twoFactorLabel"
>
<input
className="btn-toggler"

View File

@@ -27,6 +27,7 @@
]
},
"dependencies": {
"axios": "^0.21.1"
"axios": "^0.21.1",
"speakeasy": "^2.0.0"
}
}

View File

@@ -0,0 +1,209 @@
const puppeteer = require('puppeteer');
const utils = require('../../test-utils');
const init = require('../../test-init');
const speakeasy = require('speakeasy');
const { expect } = require('chai');
require('should');
const projectName = 'project';
let browser, page;
// user credentials
const email = utils.generateRandomBusinessEmail();
const password = '1234567890';
let token;
const generateOtp = () => {
const otp = speakeasy.totp({
secret: token.trim(),
encoding: 'base32',
});
return otp;
};
describe('TwoFactor Authentication API', () => {
const operationTimeOut = init.timeout;
beforeAll(async done => {
jest.setTimeout(360000);
browser = await puppeteer.launch(utils.puppeteerLaunchConfig);
page = await browser.newPage();
await page.setUserAgent(utils.agent);
const user = {
email: email,
password: password,
};
//user login
await init.registerUser(user, page);
await init.addProject(page, projectName);
done();
});
afterAll(async done => {
browser.close();
done();
});
test(
'Should throw an error when invalid otp token is passed',
async done => {
await page.goto(utils.DASHBOARD_URL, {
waitUntil: ['networkidle2'],
});
await init.pageWaitForSelector(page, '#profile-menu');
await init.pageClick(page, '#profile-menu');
await init.pageWaitForSelector(page, '#userProfile');
await init.pageClick(page, '#userProfile');
await init.pageWaitForSelector(page, '#profileSettings', {
visible: true,
timeout: init.timeout,
});
await init.pageWaitForSelector(page, '#twoFactorLabel');
await init.pageClick(page, '#twoFactorLabel');
await init.pageWaitForSelector(page, '#nextFormButton');
await init.pageClick(page, '#nextFormButton');
await init.pageWaitForSelector(page, '#token');
await init.pageType(page, '#token', '432424');
await init.pageWaitForSelector(page, '#enableTwoFactorAuthButton');
await init.pageClick(page, '#enableTwoFactorAuthButton');
const message = await init.page$Eval(
page,
'#modal-message',
element => element.innerHTML
);
expect(message).equal('Invalid token.');
done();
},
operationTimeOut
);
test(
'Should enable twoFactor authentication',
async done => {
await page.goto(utils.DASHBOARD_URL, {
waitUntil: ['networkidle2'],
});
await init.pageWaitForSelector(page, '#profile-menu');
await init.pageClick(page, '#profile-menu');
await init.pageWaitForSelector(page, '#userProfile');
await init.pageClick(page, '#userProfile');
await init.pageWaitForSelector(page, '#profileSettings', {
visible: true,
timeout: init.timeout,
});
await init.pageWaitForSelector(page, '#twoFactorLabel');
await init.pageClick(page, '#twoFactorLabel');
await init.pageWaitForSelector(page, '#otpath-url');
token = await init.page$Eval(
page,
'#otpath-url',
element => element.innerHTML
);
const otp = await generateOtp(token);
await init.pageWaitForSelector(page, '#nextFormButton');
await init.pageClick(page, '#nextFormButton');
await init.pageWaitForSelector(page, '#token');
await init.pageType(page, '#token', otp.toString());
await init.pageWaitForSelector(page, '#enableTwoFactorAuthButton');
await init.pageClick(page, '#enableTwoFactorAuthButton');
const isVisible = await init.isElementOnPage(
page,
'#modal-message'
);
expect(isVisible).equal(false);
await init.saasLogout(page);
done();
},
operationTimeOut
);
test(
'Should ask a user with two factor enabled when they are about to login again',
async done => {
await page.goto(utils.ACCOUNTS_URL + '/login', {
waitUntil: 'networkidle2',
});
await init.pageWaitForSelector(page, '#login-button');
await init.pageClick(page, 'input[name=email]');
await init.pageType(page, 'input[name=email]', email);
await init.pageClick(page, 'input[name=password]');
await init.pageType(page, 'input[name=password]', password);
await init.pageClick(page, 'button[type=submit]');
await init.pageWaitForSelector(page, '.message', {
visible: true,
timeout: init.timeout,
});
const message = await init.page$Eval(
page,
'.message',
element => element.innerHTML
);
expect(message).equal('Enter your auth token below to login.');
done();
},
operationTimeOut
);
test(
'Should throw an error when invalid otp token is passed during login',
async done => {
await page.goto(utils.ACCOUNTS_URL + '/login', {
waitUntil: 'networkidle2',
});
await init.pageWaitForSelector(page, '#login-button');
await init.pageClick(page, 'input[name=email]');
await init.pageType(page, 'input[name=email]', email);
await init.pageClick(page, 'input[name=password]');
await init.pageType(page, 'input[name=password]', password);
await init.pageClick(page, 'button[type=submit]');
await init.pageWaitForSelector(page, '#token');
await init.pageType(page, '#token', '432224');
await init.pageWaitForSelector(page, 'button[type=submit]');
await init.pageClick(page, 'button[type=submit]');
const message = await init.page$Eval(
page,
'.title span',
element => element.innerHTML
);
expect(message).equal('Invalid token.');
done();
},
operationTimeOut
);
test(
'Should successfully login when valid otp token is passed during login',
async done => {
await page.goto(utils.ACCOUNTS_URL + '/login', {
waitUntil: 'networkidle2',
});
await init.pageWaitForSelector(page, '#login-button');
await init.pageClick(page, 'input[name=email]');
await init.pageType(page, 'input[name=email]', email);
await init.pageClick(page, 'input[name=password]');
await init.pageType(page, 'input[name=password]', password);
await init.pageClick(page, 'button[type=submit]');
const otp = generateOtp();
await init.pageWaitForSelector(page, '#token');
await init.pageType(page, '#token', otp.toString());
await init.pageWaitForSelector(page, 'button[type=submit]');
await init.pageClick(page, 'button[type=submit]');
await init.pageWaitForSelector(page, '#home', {
visible: true,
timeout: init.timeout,
});
done();
},
operationTimeOut
);
});