Skip to content

Commit

Permalink
Add tests for enterprise AD captcha
Browse files Browse the repository at this point in the history
  • Loading branch information
stevehobbsdev committed Feb 6, 2022
1 parent adf1008 commit 7c97f36
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 44 deletions.
24 changes: 16 additions & 8 deletions src/connection/enterprise/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getFieldValue, hideInvalidFields } from '../../field/index';
import { emailLocalPart } from '../../field/email';
import { logIn as coreLogIn } from '../../core/actions';
import * as l from '../../core/index';
import { setCaptchaParams, showMissingCaptcha } from '../captcha';
import { setCaptchaParams, showMissingCaptcha, swapCaptcha } from '../captcha';

// TODO: enterprise connections should not depend on database
// connections. However, we now allow a username input to contain also
Expand Down Expand Up @@ -73,13 +73,21 @@ function logInActiveFlow(id, params) {
? emailLocalPart(originalUsername)
: originalUsername;

coreLogIn(id, ['password', usernameField], {
...params,
connection: connection ? connection.get('name') : null,
username: username,
password: getFieldValue(m, 'password'),
login_hint: username
});
coreLogIn(
id,
['password', usernameField],
{
...params,
connection: connection ? connection.get('name') : null,
username: username,
password: getFieldValue(m, 'password'),
login_hint: username
},
(id, error, fields, next) => {
const wasCaptchaInvalid = error && error.code === 'invalid captcha';
swapCaptcha(id, wasCaptchaInvalid, next);
}
);
}

function logInSSO(id, connection, params) {
Expand Down
186 changes: 186 additions & 0 deletions test/captcha.corporate.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
'use strict';

import expect from 'expect.js';
import * as h from './helper/ui';
import en from '../src/i18n/en';

const lockOpts = {
allowedConnections: ['db'],
rememberLastLogin: false
};

const svgCaptchaRequiredResponse1 = {
required: true,
image: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
type: 'code'
};

const svgCaptchaRequiredResponse2 = {
required: true,
image: 'data:image/gif;base64,blibli',
type: 'code'
};

const recaptchav2Response = {
required: true,
provider: 'recaptcha_v2',
siteKey: 'my_site_key'
};

const lockConfigName = 'single corporate';

describe('captcha (corporate connection)', function () {
before(h.stubWebApis);
after(h.restoreWebApis);

describe('svg-captcha', () => {
describe('when the api returns a new challenge', function () {
beforeEach(function (done) {
this.stub = h.stubGetChallenge([svgCaptchaRequiredResponse1, svgCaptchaRequiredResponse2]);
this.lock = h.displayLock(lockConfigName, lockOpts, done);
});

afterEach(function () {
this.lock.hide();
});

it('should show the captcha input', function (done) {
setTimeout(() => {
expect(h.qInput(this.lock, 'captcha', false)).to.be.ok();
done();
}, 500);
});

it('should require another challenge when clicking the refresh button', function (done) {
h.clickRefreshCaptchaButton(this.lock);

setTimeout(() => {
expect(h.q(this.lock, '.auth0-lock-captcha-image').style.backgroundImage).to.equal(
`url("${svgCaptchaRequiredResponse2.image}")`
);
done();
}, 200);
});

it('should submit the captcha provided by the user', function (done) {
h.logInWithUsernamePasswordAndCaptcha(this.lock, () => {
expect(h.wasLoginAttemptedWith({ captcha: 'captchaValue' })).to.be.ok();
done();
});
});

it('should not submit the form if the captcha is not provided', function (done) {
h.logInWithUsernameAndPassword(this.lock, () => {
expect(h.wasLoginAttemptedWith({})).to.not.be.ok();
expect(h.hasErrorMessage(this.lock, en.error.login.invalid_captcha)).to.be.ok();
done();
});
});
});

describe('when the challenge api returns required: false', function () {
beforeEach(function (done) {
h.stubGetChallenge({
required: false
});

this.lock = h.displayLock(lockConfigName, lockOpts, done);
});

afterEach(function () {
this.lock.hide();
});

it('should not show the captcha input', function () {
expect(h.qInput(this.lock, 'captcha', false)).to.not.be.ok();
});

describe('when the form submission fails and the transaction starts requiring a challenge', function () {
beforeEach(function (done) {
h.assertAuthorizeRedirection((lockID, options, authParams, cb) => {
cb(new Error('bad request'));
setTimeout(done, 300);
});

h.stubGetChallenge(svgCaptchaRequiredResponse1);
h.fillUsernameInput(this.lock, 'someone');
h.fillPasswordInput(this.lock, 'mypass');
h.submitForm(this.lock);
});

it('should call the challenge api again and show the input', function () {
expect(h.qInput(this.lock, 'captcha', false)).to.be.ok();
});
});
});
});

describe('recaptchav2', () => {
describe('when the api returns a new challenge', function () {
beforeEach(function (done) {
this.stub = h.stubGetChallenge([recaptchav2Response]);
this.lock = h.displayLock(lockConfigName, lockOpts, done);
});

afterEach(function () {
this.lock.hide();
});

it('should load the captcha script', function () {
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.be.ok();
});

it('should show the captcha input', function () {
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.be.ok();
});

it('should not submit the form if the captcha is not provided', function (done) {
h.logInWithUsernameAndPassword(this.lock, () => {
expect(h.wasLoginAttemptedWith({})).to.not.be.ok();
expect(h.hasErrorMessage(this.lock, en.error.login.invalid_recaptcha)).to.be.ok();
done();
});
});
});

describe('when the challenge api returns required: false', function () {
let notRequiredStub;
beforeEach(function (done) {
notRequiredStub = h.stubGetChallenge({
required: false
});
this.lock = h.displayLock('', lockOpts, done);
});

afterEach(function () {
this.lock.hide();
});

it('should not show the captcha input', function () {
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.not.be.ok();
});

describe('when the form submission fails and the transaction starts requiring a challenge', function () {
let challengeStub;
beforeEach(function (done) {
h.assertAuthorizeRedirection((lockID, options, authParams, cb) => {
cb(new Error('bad request'));
// We wait 250ms to display errors
setTimeout(done, 260);
});

challengeStub = h.stubGetChallenge(recaptchav2Response);
h.fillUsernameInput(this.lock, '[email protected]');
h.fillPasswordInput(this.lock, 'mypass');
h.submitForm(this.lock);
});

it('should call the challenge api again and show the input', function () {
expect(notRequiredStub.calledOnce).to.be.true;
expect(challengeStub.calledOnce).to.be.true;
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.be.ok();
});
});
});
});
});
57 changes: 29 additions & 28 deletions test/captcha.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,29 @@ const recaptchav2Response = {
siteKey: 'my_site_key'
};

describe('captcha', function() {
describe('captcha', function () {
before(h.stubWebApis);
after(h.restoreWebApis);

describe('svg-captcha', () => {
describe('when the api returns a new challenge', function() {
beforeEach(function(done) {
describe('when the api returns a new challenge', function () {
beforeEach(function (done) {
this.stub = h.stubGetChallenge([svgCaptchaRequiredResponse1, svgCaptchaRequiredResponse2]);
this.lock = h.displayLock('', lockOpts, done);
});

afterEach(function() {
afterEach(function () {
this.lock.hide();
});

it('should show the captcha input', function(done) {
it('should show the captcha input', function (done) {
setTimeout(() => {
expect(h.qInput(this.lock, 'captcha', false)).to.be.ok();
done();
}, 500);
});

it('should require another challenge when clicking the refresh button', function(done) {
it('should require another challenge when clicking the refresh button', function (done) {
h.clickRefreshCaptchaButton(this.lock);
setTimeout(() => {
expect(h.q(this.lock, '.auth0-lock-captcha-image').style.backgroundImage).to.equal(
Expand All @@ -59,13 +59,13 @@ describe('captcha', function() {
}, 200);
});

it('should submit the captcha provided by the user', function() {
it('should submit the captcha provided by the user', function () {
h.logInWithEmailPasswordAndCaptcha(this.lock, () => {
expect(h.wasLoginAttemptedWith({ captcha: 'captchaValue' })).to.be.ok();
});
});

it('should not submit the form if the captcha is not provided', function(done) {
it('should not submit the form if the captcha is not provided', function (done) {
h.logInWithEmailAndPassword(this.lock, () => {
expect(h.wasLoginAttemptedWith({})).to.not.be.ok();
expect(h.hasErrorMessage(this.lock, en.error.login.invalid_captcha)).to.be.ok();
Expand All @@ -74,61 +74,62 @@ describe('captcha', function() {
});
});

describe('when the challenge api returns required: false', function() {
beforeEach(function(done) {
describe('when the challenge api returns required: false', function () {
beforeEach(function (done) {
h.stubGetChallenge({
required: false
});
this.lock = h.displayLock('', lockOpts, done);
});

afterEach(function() {
afterEach(function () {
this.lock.hide();
});

it('should not show the captcha input', function() {
it('should not show the captcha input', function () {
expect(h.qInput(this.lock, 'captcha', false)).to.not.be.ok();
});

describe('when the form submission fails and the transaction starts requiring a challenge', function() {
beforeEach(function(done) {
describe('when the form submission fails and the transaction starts requiring a challenge', function () {
beforeEach(function (done) {
h.assertAuthorizeRedirection((lockID, options, authParams, cb) => {
cb(new Error('bad request'));
setTimeout(done, 300);
});

h.stubGetChallenge(svgCaptchaRequiredResponse1);
h.fillEmailInput(this.lock, '[email protected]');
h.fillPasswordInput(this.lock, 'mypass');
h.submitForm(this.lock);
});

it('should call the challenge api again and show the input', function() {
it('should call the challenge api again and show the input', function () {
expect(h.qInput(this.lock, 'captcha', false)).to.be.ok();
});
});
});
});

describe('recaptchav2', () => {
describe('when the api returns a new challenge', function() {
beforeEach(function(done) {
describe('when the api returns a new challenge', function () {
beforeEach(function (done) {
this.stub = h.stubGetChallenge([recaptchav2Response]);
this.lock = h.displayLock('', lockOpts, done);
});

afterEach(function() {
afterEach(function () {
this.lock.hide();
});

it('should load the captcha script', function() {
it('should load the captcha script', function () {
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.be.ok();
});

it('should show the captcha input', function() {
it('should show the captcha input', function () {
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.be.ok();
});

it('should not submit the form if the captcha is not provided', function(done) {
it('should not submit the form if the captcha is not provided', function (done) {
h.logInWithEmailAndPassword(this.lock, () => {
expect(h.wasLoginAttemptedWith({})).to.not.be.ok();
expect(h.hasErrorMessage(this.lock, en.error.login.invalid_recaptcha)).to.be.ok();
Expand All @@ -137,26 +138,26 @@ describe('captcha', function() {
});
});

describe('when the challenge api returns required: false', function() {
describe('when the challenge api returns required: false', function () {
let notRequiredStub;
beforeEach(function(done) {
beforeEach(function (done) {
notRequiredStub = h.stubGetChallenge({
required: false
});
this.lock = h.displayLock('', lockOpts, done);
});

afterEach(function() {
afterEach(function () {
this.lock.hide();
});

it('should not show the captcha input', function() {
it('should not show the captcha input', function () {
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.not.be.ok();
});

describe('when the form submission fails and the transaction starts requiring a challenge', function() {
describe('when the form submission fails and the transaction starts requiring a challenge', function () {
let challengeStub;
beforeEach(function(done) {
beforeEach(function (done) {
h.assertAuthorizeRedirection((lockID, options, authParams, cb) => {
cb(new Error('bad request'));
// We wait 250ms to display errors
Expand All @@ -169,7 +170,7 @@ describe('captcha', function() {
h.submitForm(this.lock);
});

it('should call the challenge api again and show the input', function() {
it('should call the challenge api again and show the input', function () {
expect(notRequiredStub.calledOnce).to.be.true;
expect(challengeStub.calledOnce).to.be.true;
expect(h.q(this.lock, '.auth0-lock-recaptchav2')).to.be.ok();
Expand Down
Loading

0 comments on commit 7c97f36

Please sign in to comment.