diff --git a/package.json b/package.json index 770799f4..4af6491c 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "should": "^13.2.1", "sinon": "^5.0.7", "tmp": "0.0.33", + "tree-kill": "^1.2.1", "ts-node": "^6.0.1", "tslint": "^5.2.0", "typescript": "^2.9.2", diff --git a/scripts/authelia-scripts-start b/scripts/authelia-scripts-start index fa12d345..f28cc635 100755 --- a/scripts/authelia-scripts-start +++ b/scripts/authelia-scripts-start @@ -4,6 +4,7 @@ var program = require('commander'); var spawn = require('child_process').spawn; var chokidar = require('chokidar'); var fs = require('fs'); +var kill = require('tree-kill'); program .option('-s, --suite ', 'The suite to run Authelia for. This suite represents a configuration for Authelia and a set of tests for that configuration.') @@ -14,17 +15,18 @@ if (!program.suite) { } const ENVIRONMENT_FILENAME = '.suite'; +const AUTHELIA_INTERRUPT_FILENAME = '.authelia-interrupt'; -var tsWatcher = chokidar.watch(['server', 'shared/**/*.ts', 'node_modules'], { +var tsWatcher = chokidar.watch(['server', 'shared/**/*.ts', 'node_modules', AUTHELIA_INTERRUPT_FILENAME], { persistent: true, ignoreInitial: true, }); // Properly cleanup server and client if ctrl-c is hit process.on('SIGINT', function() { - killServer(() => {}); - killClient(() => {}); + killServer(); + killClient(); fs.unlinkSync(ENVIRONMENT_FILENAME); process.exit(); }); @@ -38,7 +40,11 @@ function reloadServer() { } function startServer() { - serverProcess = spawn('./scripts/run-dev-server.sh', [`test/suites/${program.suite}/config.yml`], {detached: true}); + if (fs.existsSync(AUTHELIA_INTERRUPT_FILENAME)) { + console.log('Authelia is interrupted. Consider removing ' + AUTHELIA_INTERRUPT_FILENAME + ' if it\'s not expected.'); + return; + } + serverProcess = spawn('./scripts/run-dev-server.sh', [`test/suites/${program.suite}/config.yml`]); serverProcess.stdout.pipe(process.stdout); serverProcess.stderr.pipe(process.stderr); } @@ -46,7 +52,6 @@ function startServer() { let clientProcess; function startClient() { clientProcess = spawn('npm', ['run', 'start'], { - detached: true, cwd: './client', env: { ...process.env, @@ -61,14 +66,16 @@ function killServer(onExit) { if (serverProcess) { serverProcess.on('exit', () => { serverProcess = undefined; - onExit(); + if (onExit) onExit(); }); try { - process.kill(-serverProcess.pid); + kill(serverProcess.pid, 'SIGKILL'); } catch (e) { console.error(e); - onExit(); + if (onExit) onExit(); } + } else { + if (onExit) onExit(); } } @@ -76,14 +83,16 @@ function killClient(onExit) { if (clientProcess) { clientProcess.on('exit', () => { clientProcess = undefined; - onExit(); + if (onExit) onExit(); }); try { - process.kill(-clientProcess.pid); + kill(clientProcess.pid, 'SIGKILL'); } catch (e) { console.error(e); - onExit(); + if (onExit) onExit(); } + } else { + if (onExit) onExit(); } } @@ -97,6 +106,16 @@ function reload(path) { console.log('Schema needs to be regenerated.'); generateConfigurationSchema(); } + else if (path === AUTHELIA_INTERRUPT_FILENAME) { + if (fs.existsSync(path)) { + console.log('Authelia is being interrupted.'); + killServer(); + } else { + console.log('Authelia is restarting.'); + startServer(); + } + return; + } reloadServer(); } @@ -128,7 +147,7 @@ async function main() { console.log('Start watching...'); tsWatcher.on('add', reload); - tsWatcher.on('remove', reload); + tsWatcher.on('unlink', reload); tsWatcher.on('change', reload); startServer(); diff --git a/server/src/lib/authentication/AuthenticationError.ts b/server/src/lib/authentication/AuthenticationError.ts new file mode 100644 index 00000000..8203b345 --- /dev/null +++ b/server/src/lib/authentication/AuthenticationError.ts @@ -0,0 +1,11 @@ + + +// Error thrown when the authentication failed when checking +// user/password. +class AuthenticationError extends Error { + constructor(msg: string) { + super(msg); + } +} + +export default AuthenticationError \ No newline at end of file diff --git a/server/src/lib/authentication/backends/file/FileUsersDatabase.ts b/server/src/lib/authentication/backends/file/FileUsersDatabase.ts index cf822540..32bbff85 100644 --- a/server/src/lib/authentication/backends/file/FileUsersDatabase.ts +++ b/server/src/lib/authentication/backends/file/FileUsersDatabase.ts @@ -8,6 +8,7 @@ import { GroupsAndEmails } from "../GroupsAndEmails"; import { IUsersDatabase } from "../IUsersDatabase"; import { HashGenerator } from "../../../utils/HashGenerator"; import { ReadWriteQueue } from "./ReadWriteQueue"; +import AuthenticationError from "../../AuthenticationError"; const loadAsync = Bluebird.promisify(Yaml.load); @@ -80,7 +81,7 @@ export class FileUsersDatabase implements IUsersDatabase { return HashGenerator.ssha512(password, rounds, salt) .then((hash: string) => { if (hash !== storedHash) { - return Bluebird.reject(new Error("Wrong username/password.")); + return Bluebird.reject(new AuthenticationError("Wrong username/password.")); } return Bluebird.resolve(); }); diff --git a/server/src/lib/authentication/backends/ldap/LdapUsersDatabase.ts b/server/src/lib/authentication/backends/ldap/LdapUsersDatabase.ts index edda62ec..d4174327 100644 --- a/server/src/lib/authentication/backends/ldap/LdapUsersDatabase.ts +++ b/server/src/lib/authentication/backends/ldap/LdapUsersDatabase.ts @@ -5,6 +5,7 @@ import { LdapConfiguration } from "../../../configuration/schema/LdapConfigurati import { ISession } from "./ISession"; import { GroupsAndEmails } from "../GroupsAndEmails"; import Exceptions = require("../../../Exceptions"); +import AuthenticationError from "../../AuthenticationError"; type SessionCallback = (session: ISession) => Bluebird; @@ -58,7 +59,7 @@ export class LdapUsersDatabase implements IUsersDatabase { .then(() => getInfo(session)); }) .catch((err) => - Bluebird.reject(new Exceptions.LdapError(err.message))); + Bluebird.reject(new AuthenticationError(err.message))); } getEmails(username: string): Bluebird { diff --git a/server/src/lib/routes/firstfactor/post.ts b/server/src/lib/routes/firstfactor/post.ts index e10a29f5..2a2671d4 100644 --- a/server/src/lib/routes/firstfactor/post.ts +++ b/server/src/lib/routes/firstfactor/post.ts @@ -15,6 +15,7 @@ import { BelongToDomain } from "../../../../../shared/BelongToDomain"; import { URLDecomposer } from "../..//utils/URLDecomposer"; import { Object } from "../../../lib/authorization/Object"; import { Subject } from "../../../lib/authorization/Subject"; +import AuthenticationError from "../../../lib/authentication/AuthenticationError"; export default function (vars: ServerVariables) { return function (req: express.Request, res: express.Response) @@ -95,7 +96,7 @@ export default function (vars: ServerVariables) { res.send(); return BluebirdPromise.resolve(); }) - .catch(Exceptions.LdapBindError, function (err: Error) { + .catch(AuthenticationError, function (err: Error) { vars.regulator.mark(username, false); return ErrorReplies.replyWithError200(req, res, vars.logger, UserMessages.AUTHENTICATION_FAILED)(err); }) diff --git a/test/features/regulation.feature b/test/features/regulation.feature deleted file mode 100644 index 39504d7e..00000000 --- a/test/features/regulation.feature +++ /dev/null @@ -1,39 +0,0 @@ -@needs-regulation-config -Feature: Authelia regulates authentication to avoid brute force - - @need-registered-user-blackhat - Scenario: Attacker tries too many authentication in a short period of time and get banned - Given I visit "https://login.example.com:8080/" - And I set field "username" to "blackhat" - And I set field "password" to "bad-password" - And I click on "Sign in" - And I get a notification of type "error" with message "Authentication failed. Please check your credentials." - And I set field "password" to "bad-password" - And I click on "Sign in" - And I get a notification of type "error" with message "Authentication failed. Please check your credentials." - And I set field "password" to "bad-password" - And I click on "Sign in" - And I get a notification of type "error" with message "Authentication failed. Please check your credentials." - When I set field "password" to "password" - And I click on "Sign in" - Then I get a notification of type "error" with message "Authentication failed. Please check your credentials." - - @need-registered-user-blackhat - Scenario: User is unbanned after a configured amount of time - Given I visit "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html" - And I set field "username" to "blackhat" - And I set field "password" to "bad-password" - And I click on "Sign in" - And I get a notification of type "error" with message "Authentication failed. Please check your credentials." - And I set field "password" to "bad-password" - And I click on "Sign in" - And I get a notification of type "error" with message "Authentication failed. Please check your credentials." - And I set field "password" to "bad-password" - And I click on "Sign in" - And I get a notification of type "error" with message "Authentication failed. Please check your credentials." - When I wait 6 seconds - And I set field "password" to "password" - And I click on "Sign in" - And I use "REGISTERED" as TOTP token handle - And I click on "Sign in" - Then I'm redirected to "https://public.example.com:8080/secret.html" diff --git a/test/features/resilience.feature b/test/features/resilience.feature deleted file mode 100644 index a110d4f8..00000000 --- a/test/features/resilience.feature +++ /dev/null @@ -1,15 +0,0 @@ -Feature: Authelia keeps user sessions despite the application restart - - @need-authenticated-user-john - Scenario: Session is still valid after Authelia restarts - When the application restarts - Then I have access to "https://admin.example.com:8080/secret.html" - - @need-registered-user-john - Scenario: Secrets are stored even when Authelia restarts - When the application restarts - And I visit "https://admin.example.com:8080/secret.html" and get redirected "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html" - And I login with user "john" and password "password" - And I use "REGISTERED" as TOTP token handle - And I click on "Sign in" - Then I'm redirected to "https://admin.example.com:8080/secret.html" diff --git a/test/features/single-factor-domain.feature b/test/features/single-factor-domain.feature deleted file mode 100644 index 9fee7be9..00000000 --- a/test/features/single-factor-domain.feature +++ /dev/null @@ -1,16 +0,0 @@ -Feature: User can access certain subdomains with single factor - - Scenario: User is redirected to service after first factor if allowed - When I visit "https://login.example.com:8080/?rd=https://single_factor.example.com:8080/secret.html" - And I login with user "john" and password "password" - Then I'm redirected to "https://single_factor.example.com:8080/secret.html" - - Scenario: Redirection after first factor fails if single_factor not allowed. It redirects user to first factor. - When I visit "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html" - And I login with user "john" and password "password" - Then I'm redirected to "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html" - - Scenario: User can login using basic authentication - When I request "https://single_factor.example.com:8080/secret.html" with username "john" and password "password" using basic authentication - Then I receive the secret page - diff --git a/test/helpers/SeeNotification.ts b/test/helpers/SeeNotification.ts index 2288ecc8..97865331 100644 --- a/test/helpers/SeeNotification.ts +++ b/test/helpers/SeeNotification.ts @@ -1,7 +1,7 @@ import SeleniumWebdriver, { WebDriver } from "selenium-webdriver"; import Assert = require("assert"); -export default async function(driver: WebDriver, type: string, message: string) { +export default async function(driver: WebDriver, message: string) { await driver.wait(SeleniumWebdriver.until.elementLocated(SeleniumWebdriver.By.className("notification")), 5000) const notificationEl = driver.findElement(SeleniumWebdriver.By.className("notification")); const txt = await notificationEl.getText(); diff --git a/test/helpers/assertions/VerifyNotificationDisplayed.ts b/test/helpers/assertions/VerifyNotificationDisplayed.ts new file mode 100644 index 00000000..97865331 --- /dev/null +++ b/test/helpers/assertions/VerifyNotificationDisplayed.ts @@ -0,0 +1,9 @@ +import SeleniumWebdriver, { WebDriver } from "selenium-webdriver"; +import Assert = require("assert"); + +export default async function(driver: WebDriver, message: string) { + await driver.wait(SeleniumWebdriver.until.elementLocated(SeleniumWebdriver.By.className("notification")), 5000) + const notificationEl = driver.findElement(SeleniumWebdriver.By.className("notification")); + const txt = await notificationEl.getText(); + Assert.equal(message, txt); +} \ No newline at end of file diff --git a/test/helpers/utils/Requests.ts b/test/helpers/utils/Requests.ts index 41d76b01..5b5a1e61 100644 --- a/test/helpers/utils/Requests.ts +++ b/test/helpers/utils/Requests.ts @@ -5,8 +5,7 @@ import { StatusCodeError } from 'request-promise/errors'; process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; -// Sent a GET request to the url and expect a 401 -export async function GET_Expect401(url: string) { +export async function GET_ExpectError(url: string, statusCode: number) { try { await Request.get(url, { json: true, @@ -15,13 +14,22 @@ export async function GET_Expect401(url: string) { throw new Error('No response'); } catch (e) { if (e instanceof StatusCodeError) { - Assert.equal(e.statusCode, 401); + Assert.equal(e.statusCode, statusCode); return; } } return; } +// Sent a GET request to the url and expect a 401 +export async function GET_Expect401(url: string) { + return await GET_ExpectError(url, 401); +} + +export async function GET_Expect502(url: string) { + return await GET_ExpectError(url, 502); +} + export async function POST_Expect401(url: string, body?: any) { try { await Request.post(url, { diff --git a/test/suites/complete/config.yml b/test/suites/complete/config.yml index b4a0a66a..6cbf82a1 100644 --- a/test/suites/complete/config.yml +++ b/test/suites/complete/config.yml @@ -213,10 +213,10 @@ regulation: # The time range during which the user can attempt login before being banned. # The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window. - find_time: 120 + find_time: 15 # The length of time before a banned user can login again. - ban_time: 300 + ban_time: 5 # Configuration of the storage backend used to store data and secrets. # diff --git a/test/suites/complete/index.ts b/test/suites/complete/index.ts index 46a97e07..ca73046d 100644 --- a/test/suites/complete/index.ts +++ b/test/suites/complete/index.ts @@ -5,6 +5,8 @@ import AccessControl from "./scenarii/AccessControl"; import CustomHeadersForwarded from "./scenarii/CustomHeadersForwarded"; import SingleFactorAuthentication from "./scenarii/SingleFactorAuthentication"; import BasicAuthentication from "./scenarii/BasicAuthentication"; +import AutheliaRestart from "./scenarii/AutheliaRestart"; +import AuthenticationRegulation from "./scenarii/AuthenticationRegulation"; AutheliaSuite('Complete configuration', __dirname + '/config.yml', function() { this.timeout(10000); @@ -16,4 +18,6 @@ AutheliaSuite('Complete configuration', __dirname + '/config.yml', function() { describe('Enforce internal redirections only', EnforceInternalRedirectionsOnly); describe('Single factor authentication', SingleFactorAuthentication); describe('Basic authentication', BasicAuthentication); + describe('Authelia restart', AutheliaRestart); + describe('Authentication regulation', AuthenticationRegulation); }); \ No newline at end of file diff --git a/test/suites/complete/scenarii/AutheliaRestart.ts b/test/suites/complete/scenarii/AutheliaRestart.ts new file mode 100644 index 00000000..6f119d21 --- /dev/null +++ b/test/suites/complete/scenarii/AutheliaRestart.ts @@ -0,0 +1,72 @@ +import Logout from "../../../helpers/Logout"; +import ChildProcess from 'child_process'; +import { StartDriver, StopDriver } from "../../../helpers/context/WithDriver"; +import VerifySecretObserved from "../../../helpers/assertions/VerifySecretObserved"; +import RegisterAndLoginTwoFactor from "../../../helpers/behaviors/RegisterAndLoginTwoFactor"; +import VisitPageAndWaitUrlIs from "../../../helpers/behaviors/VisitPageAndWaitUrlIs"; +import { GET_Expect502 } from "../../../helpers/utils/Requests"; +import LoginAndRegisterTotp from "../../../helpers/LoginAndRegisterTotp"; +import FullLogin from "../../../helpers/FullLogin"; + +export default function() { + describe('Session is still valid after Authelia restarts', function() { + before(async function() { + // Be sure to start fresh + ChildProcess.execSync('rm -f .authelia-interrupt'); + + this.driver = await StartDriver(); + await RegisterAndLoginTwoFactor(this.driver, 'john', true, 'https://admin.example.com:8080/secret.html'); + await VisitPageAndWaitUrlIs(this.driver, 'https://home.example.com:8080/'); + }); + + after(async function() { + await Logout(this.driver); + await StopDriver(this.driver); + + // Be sure to cleanup + ChildProcess.execSync('rm -f .authelia-interrupt'); + }); + + it("should still access the secret after Authelia restarted", async function() { + ChildProcess.execSync('touch .authelia-interrupt'); + await GET_Expect502('https://login.example.com:8080/api/state'); + await this.driver.sleep(1000); + ChildProcess.execSync('rm .authelia-interrupt'); + await this.driver.sleep(1000); + + + await VisitPageAndWaitUrlIs(this.driver, 'https://admin.example.com:8080/secret.html'); + await VerifySecretObserved(this.driver); + }); + }); + + describe('Secrets are persisted even if Authelia restarts', function() { + before(async function() { + // Be sure to start fresh + ChildProcess.execSync('rm -f .authelia-interrupt'); + + this.driver = await StartDriver(); + this.secret = await LoginAndRegisterTotp(this.driver, 'john', true); + await Logout(this.driver); + }); + + after(async function() { + await Logout(this.driver); + await StopDriver(this.driver); + + // Be sure to cleanup + ChildProcess.execSync('rm -f .authelia-interrupt'); + }); + + it("should still access the secret after Authelia restarted", async function() { + ChildProcess.execSync('touch .authelia-interrupt'); + await GET_Expect502('https://login.example.com:8080/api/state'); + await this.driver.sleep(1000); + ChildProcess.execSync('rm .authelia-interrupt'); + await this.driver.sleep(1000); + + // The user can re-authenticate with the secret. + await FullLogin(this.driver, 'john', this.secret, 'https://admin.example.com:8080/secret.html') + }); + }); +} \ No newline at end of file diff --git a/test/suites/complete/scenarii/AuthenticationRegulation.ts b/test/suites/complete/scenarii/AuthenticationRegulation.ts new file mode 100644 index 00000000..d7ac0164 --- /dev/null +++ b/test/suites/complete/scenarii/AuthenticationRegulation.ts @@ -0,0 +1,53 @@ +import { StartDriver, StopDriver } from "../../../helpers/context/WithDriver"; +import LoginAs from "../../../helpers/LoginAs"; +import VerifyNotificationDisplayed from "../../../helpers/assertions/VerifyNotificationDisplayed"; +import VerifyIsSecondFactorStage from "../../../helpers/assertions/VerifyIsSecondFactorStage"; + +/* +Given I visit "https://login.example.com:8080/" + And I set field "username" to "blackhat" + And I set field "password" to "bad-password" + And I click on "Sign in" + And I get a notification of type "error" with message "Authentication failed. Please check your credentials." + And I set field "password" to "bad-password" + And I click on "Sign in" + And I get a notification of type "error" with message "Authentication failed. Please check your credentials." + And I set field "password" to "bad-password" + And I click on "Sign in" + And I get a notification of type "error" with message "Authentication failed. Please check your credentials." + When I set field "password" to "password" + And I click on "Sign in" + Then I get a notification of type "error" with message "Authentication failed. Please check your credentials." +*/ + +export default function() { + describe('Authelia regulates authentications when a hacker is brute forcing', function() { + this.timeout(15000); + before(async function() { + this.driver = await StartDriver(); + }); + + after(async function() { + await StopDriver(this.driver); + }); + + it("should return an error message when providing correct credentials the 4th time.", async function() { + await LoginAs(this.driver, "blackhat", "bad-password"); + await VerifyNotificationDisplayed(this.driver, "Authentication failed. Please check your credentials."); + await LoginAs(this.driver, "blackhat", "bad-password"); + await VerifyNotificationDisplayed(this.driver, "Authentication failed. Please check your credentials."); + await LoginAs(this.driver, "blackhat", "bad-password"); + await VerifyNotificationDisplayed(this.driver, "Authentication failed. Please check your credentials."); + + // when providing good credentials, the hacker is regulated and see same message as previously. + await LoginAs(this.driver, "blackhat", "password"); + await VerifyNotificationDisplayed(this.driver, "Authentication failed. Please check your credentials."); + + // Wait the regulation ban time before retrying with correct credentials. + // It should authenticate normally. + await this.driver.sleep(6000); + await LoginAs(this.driver, "blackhat", "password"); + await VerifyIsSecondFactorStage(this.driver); + }); + }); +} \ No newline at end of file diff --git a/test/suites/complete/scenarii/SingleFactorAuthentication.ts b/test/suites/complete/scenarii/SingleFactorAuthentication.ts index 463bea0b..a31887a5 100644 --- a/test/suites/complete/scenarii/SingleFactorAuthentication.ts +++ b/test/suites/complete/scenarii/SingleFactorAuthentication.ts @@ -6,6 +6,9 @@ import VisitPage from "../../../helpers/VisitPage"; import VerifyUrlIs from "../../../helpers/assertions/VerifyUrlIs"; import VerifyIsSecondFactorStage from "../../../helpers/assertions/VerifyIsSecondFactorStage"; +/* + * Those tests are related to single factor protected resources. + */ export default function() { beforeEach(async function() { this.driver = await StartDriver(); diff --git a/test/suites/minimal/config.yml b/test/suites/minimal/config.yml index a1d13552..e401b2ae 100644 --- a/test/suites/minimal/config.yml +++ b/test/suites/minimal/config.yml @@ -73,10 +73,10 @@ regulation: max_retries: 3 # The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window. - find_time: 120 + find_time: 10 # The length of time before a banned user can login again. - ban_time: 300 + ban_time: 5 # Default redirection URL # diff --git a/test/suites/minimal/scenarii/BadPassword.ts b/test/suites/minimal/scenarii/BadPassword.ts index 47be13f4..56165b5c 100644 --- a/test/suites/minimal/scenarii/BadPassword.ts +++ b/test/suites/minimal/scenarii/BadPassword.ts @@ -17,7 +17,7 @@ export default function() { it('should get a notification message', async function () { this.timeout(10000); - await SeeNotification(this.driver, "error", AUTHENTICATION_FAILED); + await SeeNotification(this.driver, AUTHENTICATION_FAILED); }); }); } diff --git a/test/suites/minimal/scenarii/Inactivity.ts b/test/suites/minimal/scenarii/Inactivity.ts index 5d3bdb12..943e9c0b 100644 --- a/test/suites/minimal/scenarii/Inactivity.ts +++ b/test/suites/minimal/scenarii/Inactivity.ts @@ -4,6 +4,8 @@ import ValidateTotp from "../../../helpers/ValidateTotp"; import WaitRedirected from "../../../helpers/WaitRedirected"; import { WebDriver } from "selenium-webdriver"; import VisitPageAndWaitUrlIs from "../../../helpers/behaviors/VisitPageAndWaitUrlIs"; +import VisitPage from "../../../helpers/VisitPage"; +import VerifyUrlIs from "../../../helpers/assertions/VerifyUrlIs"; export default function(this: Mocha.ISuiteCallbackContext) { this.timeout(20000); @@ -52,8 +54,8 @@ export default function(this: Mocha.ISuiteCallbackContext) { await WaitRedirected(driver, "https://admin.example.com:8080/secret.html"); await VisitPageAndWaitUrlIs(driver, "https://home.example.com:8080/"); await driver.sleep(6000); - await driver.get("https://admin.example.com:8080/secret.html"); - await WaitRedirected(driver, "https://admin.example.com:8080/secret.html"); + await VisitPage(driver, "https://admin.example.com:8080/secret.html"); + await VerifyUrlIs(driver, "https://admin.example.com:8080/secret.html"); }); }); } \ No newline at end of file diff --git a/test/suites/minimal/scenarii/RegisterTotp.ts b/test/suites/minimal/scenarii/RegisterTotp.ts index 96dbc5f1..d65fea11 100644 --- a/test/suites/minimal/scenarii/RegisterTotp.ts +++ b/test/suites/minimal/scenarii/RegisterTotp.ts @@ -29,7 +29,6 @@ export default function() { }); it("should have user and issuer in otp url", async function() { - // this.timeout(100000); const el = await (this.driver as WebDriver).wait( SeleniumWebdriver.until.elementLocated( SeleniumWebdriver.By.className('otpauth-secret')), 5000); diff --git a/test/suites/minimal/scenarii/ResetPassword.ts b/test/suites/minimal/scenarii/ResetPassword.ts index d83054fd..8d471aac 100644 --- a/test/suites/minimal/scenarii/ResetPassword.ts +++ b/test/suites/minimal/scenarii/ResetPassword.ts @@ -57,6 +57,6 @@ export default function() { await FillField(this.driver, "password1", "newpass"); await FillField(this.driver, "password2", "badpass"); await ClickOn(this.driver, SeleniumWebDriver.By.id('reset-button')); - await SeeNotification(this.driver, "error", "The passwords are different."); + await SeeNotification(this.driver, "The passwords are different."); }); } diff --git a/test/suites/minimal/scenarii/TOTPValidation.ts b/test/suites/minimal/scenarii/TOTPValidation.ts index 371da046..60e508a9 100644 --- a/test/suites/minimal/scenarii/TOTPValidation.ts +++ b/test/suites/minimal/scenarii/TOTPValidation.ts @@ -45,7 +45,7 @@ export default function() { }); it("get a notification message", async function() { - await SeeNotification(this.driver, "error", AUTHENTICATION_TOTP_FAILED); + await SeeNotification(this.driver, AUTHENTICATION_TOTP_FAILED); }); }); }