diff --git a/client-react/docker-compose.yml b/client-react/docker-compose.yml deleted file mode 100644 index 3e8ecb1e..00000000 --- a/client-react/docker-compose.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: '2' -services: - authelia-frontend-dev: - build: - context: client-react - restart: always - volumes: - - ./client-react/tsconfig.json:/usr/app/client/tsconfig.json - - ./client-react/public:/usr/app/client/public - - ./client-react/src:/usr/app/client/src - - ./shared:/usr/app/shared - networks: - example-network: - aliases: - - authelia-frontend diff --git a/client-react/tsconfig.json b/client-react/tsconfig.json deleted file mode 100644 index c5d6f230..00000000 --- a/client-react/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "allowJs": true, - "skipLibCheck": false, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ] - }, - "include": [ - "src" - ] -} diff --git a/client-react/.gitignore b/client/.gitignore similarity index 100% rename from client-react/.gitignore rename to client/.gitignore diff --git a/client-react/Dockerfile b/client/Dockerfile similarity index 100% rename from client-react/Dockerfile rename to client/Dockerfile diff --git a/client-react/README.md b/client/README.md similarity index 100% rename from client-react/README.md rename to client/README.md diff --git a/client/docker-compose.yml b/client/docker-compose.yml new file mode 100644 index 00000000..9c2abfb4 --- /dev/null +++ b/client/docker-compose.yml @@ -0,0 +1,14 @@ +version: '2' +services: + authelia-frontend-dev: + build: + context: client + restart: always + volumes: + - ./client/tsconfig.json:/usr/app/client/tsconfig.json + - ./client/public:/usr/app/client/public + - ./client/src:/usr/app/client/src + networks: + example-network: + aliases: + - authelia-frontend diff --git a/client-react/package-lock.json b/client/package-lock.json similarity index 100% rename from client-react/package-lock.json rename to client/package-lock.json diff --git a/client-react/package.json b/client/package.json similarity index 100% rename from client-react/package.json rename to client/package.json diff --git a/client-react/public/favicon.ico b/client/public/favicon.ico similarity index 100% rename from client-react/public/favicon.ico rename to client/public/favicon.ico diff --git a/client-react/public/index.html b/client/public/index.html similarity index 95% rename from client-react/public/index.html rename to client/public/index.html index 23881654..5d323692 100644 --- a/client-react/public/index.html +++ b/client/public/index.html @@ -4,6 +4,7 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/src/img/stores/googleplay-badge.svg b/client/src/img/stores/googleplay-badge.svg deleted file mode 100644 index 9e33e3aa..00000000 --- a/client/src/img/stores/googleplay-badge.svg +++ /dev/null @@ -1,429 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/client/src/img/success.png b/client/src/img/success.png deleted file mode 100644 index ee9d6841..00000000 Binary files a/client/src/img/success.png and /dev/null differ diff --git a/client/src/img/user.png b/client/src/img/user.png deleted file mode 100644 index 00941399..00000000 Binary files a/client/src/img/user.png and /dev/null differ diff --git a/client/src/img/warning.png b/client/src/img/warning.png deleted file mode 100644 index c6acd953..00000000 Binary files a/client/src/img/warning.png and /dev/null differ diff --git a/client-react/src/index.css b/client/src/index.css similarity index 100% rename from client-react/src/index.css rename to client/src/index.css diff --git a/client/src/index.ts b/client/src/index.ts deleted file mode 100644 index 6c22d17c..00000000 --- a/client/src/index.ts +++ /dev/null @@ -1,34 +0,0 @@ - -import FirstFactorValidator = require("./lib/firstfactor/FirstFactorValidator"); - -import FirstFactor from "./lib/firstfactor/index"; -import SecondFactor from "./lib/secondfactor/index"; -import TOTPRegister from "./lib/totp-register/totp-register"; -import U2fRegister from "./lib/u2f-register/u2f-register"; -import ResetPasswordRequest from "./lib/reset-password/reset-password-request"; -import ResetPasswordForm from "./lib/reset-password/reset-password-form"; -import jslogger = require("js-logger"); -import jQuery = require("jquery"); -import Endpoints = require("../../shared/api"); - -jslogger.useDefaults(); -jslogger.setLevel(jslogger.INFO); - -(function () { - (window).jQuery = jQuery; - require("bootstrap"); - - jQuery('[data-toggle="tooltip"]').tooltip(); - if (window.location.pathname == Endpoints.FIRST_FACTOR_GET) - FirstFactor(window, jQuery, FirstFactorValidator, jslogger); - else if (window.location.pathname == Endpoints.SECOND_FACTOR_GET) - SecondFactor(window, jQuery); - else if (window.location.pathname == Endpoints.SECOND_FACTOR_TOTP_IDENTITY_FINISH_GET) - TOTPRegister(window, jQuery); - else if (window.location.pathname == Endpoints.SECOND_FACTOR_U2F_IDENTITY_FINISH_GET) - U2fRegister(window, jQuery); - else if (window.location.pathname == Endpoints.RESET_PASSWORD_IDENTITY_FINISH_GET) - ResetPasswordForm(window, jQuery); - else if (window.location.pathname == Endpoints.RESET_PASSWORD_REQUEST_GET) - ResetPasswordRequest(window, jQuery); -})(); diff --git a/client-react/src/index.tsx b/client/src/index.tsx similarity index 100% rename from client-react/src/index.tsx rename to client/src/index.tsx diff --git a/client-react/src/layouts/PortalLayout/PortalLayout.tsx b/client/src/layouts/PortalLayout/PortalLayout.tsx similarity index 100% rename from client-react/src/layouts/PortalLayout/PortalLayout.tsx rename to client/src/layouts/PortalLayout/PortalLayout.tsx diff --git a/client/src/lib/GetPromised.ts b/client/src/lib/GetPromised.ts deleted file mode 100644 index 77913965..00000000 --- a/client/src/lib/GetPromised.ts +++ /dev/null @@ -1,14 +0,0 @@ -import BluebirdPromise = require("bluebird"); - -export default function ($: JQueryStatic, url: string, data: Object, fn: any, - dataType: string): BluebirdPromise { - return new BluebirdPromise((resolve, reject) => { - $.get(url, {}, undefined, dataType) - .done((data: any) => { - resolve(data); - }) - .fail((xhr: JQueryXHR, textStatus: string) => { - reject(textStatus); - }); - }); -} \ No newline at end of file diff --git a/client/src/lib/INotifier.ts b/client/src/lib/INotifier.ts deleted file mode 100644 index df947538..00000000 --- a/client/src/lib/INotifier.ts +++ /dev/null @@ -1,14 +0,0 @@ - -declare type Handler = () => void; - -export interface Handlers { - onFadedIn: Handler; - onFadedOut: Handler; -} - -export interface INotifier { - success(msg: string, handlers?: Handlers): void; - error(msg: string, handlers?: Handlers): void; - warning(msg: string, handlers?: Handlers): void; - info(msg: string, handlers?: Handlers): void; -} \ No newline at end of file diff --git a/client/src/lib/Notifier.ts b/client/src/lib/Notifier.ts deleted file mode 100644 index c0252b9b..00000000 --- a/client/src/lib/Notifier.ts +++ /dev/null @@ -1,83 +0,0 @@ - - -import util = require("util"); -import { INotifier, Handlers } from "./INotifier"; - -class NotificationEvent { - private element: JQuery; - private message: string; - private statusType: string; - private timeoutId: any; - - constructor(element: JQuery, msg: string, statusType: string) { - this.message = msg; - this.statusType = statusType; - this.element = element; - } - - private clearNotification() { - this.element.removeClass(this.statusType); - this.element.html(""); - } - - start(handlers?: Handlers) { - const that = this; - const FADE_TIME = 500; - const html = util.format('status %s\ - %s', this.statusType, this.statusType, this.message); - this.element.html(html); - this.element.addClass(this.statusType); - this.element.fadeIn(FADE_TIME, function () { - if (handlers) - handlers.onFadedIn(); - }); - - this.timeoutId = setTimeout(function () { - that.element.fadeOut(FADE_TIME, function () { - that.clearNotification(); - if (handlers) - handlers.onFadedOut(); - }); - }, 4000); - } - - interrupt() { - this.clearNotification(); - this.element.hide(); - clearTimeout(this.timeoutId); - } -} - -export class Notifier implements INotifier { - private element: JQuery; - private onGoingEvent: NotificationEvent; - - constructor(selector: string, $: JQueryStatic) { - this.element = $(selector); - this.onGoingEvent = undefined; - } - - private displayAndFadeout(msg: string, statusType: string, handlers?: Handlers): void { - if (this.onGoingEvent) - this.onGoingEvent.interrupt(); - - this.onGoingEvent = new NotificationEvent(this.element, msg, statusType); - this.onGoingEvent.start(handlers); - } - - success(msg: string, handlers?: Handlers) { - this.displayAndFadeout(msg, "success", handlers); - } - - error(msg: string, handlers?: Handlers) { - this.displayAndFadeout(msg, "error", handlers); - } - - warning(msg: string, handlers?: Handlers) { - this.displayAndFadeout(msg, "warning", handlers); - } - - info(msg: string, handlers?: Handlers) { - this.displayAndFadeout(msg, "info", handlers); - } -} \ No newline at end of file diff --git a/client/src/lib/QueryParametersRetriever.ts b/client/src/lib/QueryParametersRetriever.ts deleted file mode 100644 index a529adb6..00000000 --- a/client/src/lib/QueryParametersRetriever.ts +++ /dev/null @@ -1,12 +0,0 @@ - -export class QueryParametersRetriever { - static get(name: string, url?: string): string { - if (!url) url = window.location.href; - name = name.replace(/[\[\]]/g, "\\$&"); - const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), - results = regex.exec(url); - if (!results) return undefined; - if (!results[2]) return ""; - return decodeURIComponent(results[2].replace(/\+/g, " ")); - } -} \ No newline at end of file diff --git a/client/src/lib/SafeRedirect.ts b/client/src/lib/SafeRedirect.ts deleted file mode 100644 index 7e7684b8..00000000 --- a/client/src/lib/SafeRedirect.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { BelongToDomain } from "../../../shared/BelongToDomain"; - -export function SafeRedirect(url: string, cb: () => void): void { - const domain = window.location.hostname.split(".").slice(-2).join("."); - if (url.startsWith("/") || BelongToDomain(url, domain)) { - window.location.href = url; - return; - } - cb(); -} \ No newline at end of file diff --git a/client/src/lib/firstfactor/FirstFactorValidator.ts b/client/src/lib/firstfactor/FirstFactorValidator.ts deleted file mode 100644 index eaa496fd..00000000 --- a/client/src/lib/firstfactor/FirstFactorValidator.ts +++ /dev/null @@ -1,46 +0,0 @@ - -import BluebirdPromise = require("bluebird"); -import Endpoints = require("../../../../shared/api"); -import Constants = require("../../../../shared/constants"); -import Util = require("util"); -import UserMessages = require("../../../../shared/UserMessages"); - -export function validate(username: string, password: string, - keepMeLoggedIn: boolean, redirectUrl: string, $: JQueryStatic) - : BluebirdPromise { - return new BluebirdPromise(function (resolve, reject) { - let url: string; - if (redirectUrl != undefined) { - const redirectParam = Util.format("%s=%s", Constants.REDIRECT_QUERY_PARAM, redirectUrl); - url = Util.format("%s?%s", Endpoints.FIRST_FACTOR_POST, redirectParam); - } - else { - url = Util.format("%s", Endpoints.FIRST_FACTOR_POST); - } - - const data: any = { - username: username, - password: password, - }; - - if (keepMeLoggedIn) { - data.keepMeLoggedIn = "true"; - } - - $.ajax({ - method: "POST", - url: url, - data: data - }) - .done(function (body: any) { - if (body && body.error) { - reject(new Error(body.error)); - return; - } - resolve(body.redirect); - }) - .fail(function (xhr: JQueryXHR, textStatus: string) { - reject(new Error(UserMessages.AUTHENTICATION_FAILED)); - }); - }); -} diff --git a/client/src/lib/firstfactor/UISelectors.ts b/client/src/lib/firstfactor/UISelectors.ts deleted file mode 100644 index 0e971b3c..00000000 --- a/client/src/lib/firstfactor/UISelectors.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export const USERNAME_FIELD_ID = "#username"; -export const PASSWORD_FIELD_ID = "#password"; -export const SIGN_IN_BUTTON_ID = "#signin"; -export const KEEP_ME_LOGGED_IN_ID = "#keep_me_logged_in"; diff --git a/client/src/lib/firstfactor/index.ts b/client/src/lib/firstfactor/index.ts deleted file mode 100644 index 24affee2..00000000 --- a/client/src/lib/firstfactor/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import FirstFactorValidator = require("./FirstFactorValidator"); -import JSLogger = require("js-logger"); -import UISelectors = require("./UISelectors"); -import { Notifier } from "../Notifier"; -import { QueryParametersRetriever } from "../QueryParametersRetriever"; -import Constants = require("../../../../shared/constants"); -import Endpoints = require("../../../../shared/api"); -import UserMessages = require("../../../../shared/UserMessages"); -import { SafeRedirect } from "../SafeRedirect"; - -export default function (window: Window, $: JQueryStatic, - firstFactorValidator: typeof FirstFactorValidator, jslogger: typeof JSLogger) { - - const notifier = new Notifier(".notification", $); - - function onFormSubmitted() { - const username: string = $(UISelectors.USERNAME_FIELD_ID).val() as string; - const password: string = $(UISelectors.PASSWORD_FIELD_ID).val() as string; - const keepMeLoggedIn: boolean = $(UISelectors.KEEP_ME_LOGGED_IN_ID).is(":checked"); - - $("form").css("opacity", 0.5); - $("input,button").attr("disabled", "true"); - $(UISelectors.SIGN_IN_BUTTON_ID).text("Please wait..."); - - const redirectUrl = QueryParametersRetriever.get(Constants.REDIRECT_QUERY_PARAM); - firstFactorValidator.validate(username, password, keepMeLoggedIn, redirectUrl, $) - .then(onFirstFactorSuccess, onFirstFactorFailure); - return false; - } - - function onFirstFactorSuccess(redirectUrl: string) { - SafeRedirect(redirectUrl, () => { - notifier.error("Cannot redirect to an external domain."); - }); - } - - function onFirstFactorFailure(err: Error) { - $("input,button").removeAttr("disabled"); - $("form").css("opacity", 1); - notifier.error(UserMessages.AUTHENTICATION_FAILED); - $(UISelectors.PASSWORD_FIELD_ID).select(); - $(UISelectors.SIGN_IN_BUTTON_ID).text("Sign in"); - } - - $(window.document).ready(function () { - $("form").on("submit", onFormSubmitted); - }); -} - diff --git a/client/src/lib/reset-password/constants.ts b/client/src/lib/reset-password/constants.ts deleted file mode 100644 index d48d4e67..00000000 --- a/client/src/lib/reset-password/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ - -export const FORM_SELECTOR = ".form-signin"; \ No newline at end of file diff --git a/client/src/lib/reset-password/reset-password-form.ts b/client/src/lib/reset-password/reset-password-form.ts deleted file mode 100644 index b94279cd..00000000 --- a/client/src/lib/reset-password/reset-password-form.ts +++ /dev/null @@ -1,57 +0,0 @@ -import BluebirdPromise = require("bluebird"); - -import Endpoints = require("../../../../shared/api"); -import UserMessages = require("../../../../shared/UserMessages"); - -import Constants = require("./constants"); -import { Notifier } from "../Notifier"; - -export default function (window: Window, $: JQueryStatic) { - const notifier = new Notifier(".notification", $); - - function modifyPassword(newPassword: string) { - return new BluebirdPromise(function (resolve, reject) { - $.post(Endpoints.RESET_PASSWORD_FORM_POST, { - password: newPassword, - }) - .done(function (body: any) { - if (body && body.error) { - reject(new Error(body.error)); - return; - } - resolve(body); - }) - .fail(function (xhr, status) { - reject(status); - }); - }); - } - - function onFormSubmitted() { - const password1 = $("#password1").val() as string; - const password2 = $("#password2").val() as string; - - if (!password1 || !password2) { - notifier.warning(UserMessages.MISSING_PASSWORD); - return false; - } - - if (password1 != password2) { - notifier.warning(UserMessages.DIFFERENT_PASSWORDS); - return false; - } - - modifyPassword(password1) - .then(function () { - window.location.href = Endpoints.FIRST_FACTOR_GET; - }) - .error(function () { - notifier.error(UserMessages.RESET_PASSWORD_FAILED); - }); - return false; - } - - $(document).ready(function () { - $(Constants.FORM_SELECTOR).on("submit", onFormSubmitted); - }); -} diff --git a/client/src/lib/reset-password/reset-password-request.ts b/client/src/lib/reset-password/reset-password-request.ts deleted file mode 100644 index 846226d7..00000000 --- a/client/src/lib/reset-password/reset-password-request.ts +++ /dev/null @@ -1,56 +0,0 @@ - -import BluebirdPromise = require("bluebird"); - -import Endpoints = require("../../../../shared/api"); -import UserMessages = require("../../../../shared/UserMessages"); -import Constants = require("./constants"); -import jslogger = require("js-logger"); -import { Notifier } from "../Notifier"; - -export default function (window: Window, $: JQueryStatic) { - const notifier = new Notifier(".notification", $); - - function requestPasswordReset(username: string) { - return new BluebirdPromise(function (resolve, reject) { - $.get(Endpoints.RESET_PASSWORD_IDENTITY_START_GET, { - userid: username, - }) - .done(function (body: any) { - if (body && body.error) { - reject(new Error(body.error)); - return; - } - resolve(); - }) - .fail(function (xhr: JQueryXHR, textStatus: string) { - reject(new Error(textStatus)); - }); - }); - } - - function onFormSubmitted() { - const username = $("#username").val() as string; - - if (!username) { - notifier.warning(UserMessages.MISSING_USERNAME); - return; - } - - requestPasswordReset(username) - .then(function () { - notifier.success(UserMessages.MAIL_SENT); - setTimeout(function () { - window.location.replace(Endpoints.FIRST_FACTOR_GET); - }, 1000); - }) - .error(function () { - notifier.error(UserMessages.MAIL_NOT_SENT); - }); - return false; - } - - $(document).ready(function () { - $(Constants.FORM_SELECTOR).on("submit", onFormSubmitted); - }); -} - diff --git a/client/src/lib/secondfactor/TOTPValidator.ts b/client/src/lib/secondfactor/TOTPValidator.ts deleted file mode 100644 index 5394139a..00000000 --- a/client/src/lib/secondfactor/TOTPValidator.ts +++ /dev/null @@ -1,28 +0,0 @@ - -import BluebirdPromise = require("bluebird"); -import Endpoints = require("../../../../shared/api"); -import { RedirectionMessage } from "../../../../shared/RedirectionMessage"; -import { ErrorMessage } from "../../../../shared/ErrorMessage"; - -export function validate(token: string, $: JQueryStatic): BluebirdPromise { - return new BluebirdPromise(function (resolve, reject) { - $.ajax({ - url: Endpoints.SECOND_FACTOR_TOTP_POST, - data: { - token: token, - }, - method: "POST", - dataType: "json" - } as JQueryAjaxSettings) - .done(function (body: RedirectionMessage | ErrorMessage) { - if (body && "error" in body) { - reject(new Error((body as ErrorMessage).error)); - return; - } - resolve((body as RedirectionMessage).redirect); - }) - .fail(function (xhr: JQueryXHR, textStatus: string) { - reject(new Error(textStatus)); - }); - }); -} \ No newline at end of file diff --git a/client/src/lib/secondfactor/U2FValidator.ts b/client/src/lib/secondfactor/U2FValidator.ts deleted file mode 100644 index 5812922f..00000000 --- a/client/src/lib/secondfactor/U2FValidator.ts +++ /dev/null @@ -1,42 +0,0 @@ -import U2f = require("u2f"); -import U2fApi from "u2f-api"; -import BluebirdPromise = require("bluebird"); -import Endpoints = require("../../../../shared/api"); -import UserMessages = require("../../../../shared/UserMessages"); -import { INotifier } from "../INotifier"; -import { RedirectionMessage } from "../../../../shared/RedirectionMessage"; -import { ErrorMessage } from "../../../../shared/ErrorMessage"; -import GetPromised from "../GetPromised"; - -function finishU2fAuthentication(responseData: U2fApi.SignResponse, - $: JQueryStatic): BluebirdPromise { - return new BluebirdPromise(function (resolve, reject) { - $.ajax({ - url: Endpoints.SECOND_FACTOR_U2F_SIGN_POST, - data: responseData, - method: "POST", - dataType: "json" - } as JQueryAjaxSettings) - .done(function (body: RedirectionMessage | ErrorMessage) { - if (body && "error" in body) { - reject(new Error((body as ErrorMessage).error)); - return; - } - resolve((body as RedirectionMessage).redirect); - }) - .fail(function (xhr: JQueryXHR, textStatus: string) { - reject(new Error(textStatus)); - }); - }); -} - -export function validate($: JQueryStatic): BluebirdPromise { - return GetPromised($, Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, {}, - undefined, "json") - .then(function (signRequest: U2f.Request) { - return U2fApi.sign(signRequest, 60); - }) - .then(function (signResponse: U2fApi.SignResponse) { - return finishU2fAuthentication(signResponse, $); - }); -} diff --git a/client/src/lib/secondfactor/constants.ts b/client/src/lib/secondfactor/constants.ts deleted file mode 100644 index 50bba757..00000000 --- a/client/src/lib/secondfactor/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export const TOTP_FORM_SELECTOR = ".form-signin.totp"; -export const TOTP_TOKEN_SELECTOR = ".form-signin #token"; diff --git a/client/src/lib/secondfactor/index.ts b/client/src/lib/secondfactor/index.ts deleted file mode 100644 index 279723dc..00000000 --- a/client/src/lib/secondfactor/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import TOTPValidator = require("./TOTPValidator"); -import U2FValidator = require("./U2FValidator"); -import ClientConstants = require("./constants"); -import { Notifier } from "../Notifier"; -import { QueryParametersRetriever } from "../QueryParametersRetriever"; -import UserMessages = require("../../../../shared/UserMessages"); -import SharedConstants = require("../../../../shared/constants"); -import { SafeRedirect } from "../SafeRedirect"; - -export default function (window: Window, $: JQueryStatic) { - const notifier = new Notifier(".notification", $); - - function onAuthenticationSuccess(serverRedirectUrl: string) { - const queryRedirectUrl = QueryParametersRetriever.get(SharedConstants.REDIRECT_QUERY_PARAM); - if (queryRedirectUrl) { - SafeRedirect(queryRedirectUrl, () => { - notifier.error(UserMessages.CANNOT_REDIRECT_TO_EXTERNAL_DOMAIN); - }); - } else if (serverRedirectUrl) { - SafeRedirect(serverRedirectUrl, () => { - notifier.error(UserMessages.CANNOT_REDIRECT_TO_EXTERNAL_DOMAIN); - }); - } else { - notifier.success(UserMessages.AUTHENTICATION_SUCCEEDED); - } - } - - function onSecondFactorTotpSuccess(redirectUrl: string) { - onAuthenticationSuccess(redirectUrl); - } - - function onSecondFactorTotpFailure(err: Error) { - notifier.error(UserMessages.AUTHENTICATION_TOTP_FAILED); - } - - function onU2fAuthenticationSuccess(redirectUrl: string) { - onAuthenticationSuccess(redirectUrl); - } - - function onU2fAuthenticationFailure() { - // TODO(clems4ever): we should not display this error message until a device - // is registered. - // notifier.error(UserMessages.AUTHENTICATION_U2F_FAILED); - } - - function onTOTPFormSubmitted(): boolean { - const token = $(ClientConstants.TOTP_TOKEN_SELECTOR).val() as string; - TOTPValidator.validate(token, $) - .then(onSecondFactorTotpSuccess) - .catch(onSecondFactorTotpFailure); - return false; - } - - $(window.document).ready(function () { - $(ClientConstants.TOTP_FORM_SELECTOR).on("submit", onTOTPFormSubmitted); - U2FValidator.validate($) - .then(onU2fAuthenticationSuccess, onU2fAuthenticationFailure); - }); -} \ No newline at end of file diff --git a/client/src/lib/totp-register/totp-register.ts b/client/src/lib/totp-register/totp-register.ts deleted file mode 100644 index 6a9aa7ee..00000000 --- a/client/src/lib/totp-register/totp-register.ts +++ /dev/null @@ -1,11 +0,0 @@ - -import jslogger = require("js-logger"); -import UISelector = require("./ui-selector"); - -export default function(window: Window, $: JQueryStatic) { - jslogger.debug("Creating QRCode from OTPAuth url"); - const qrcode = $(UISelector.QRCODE_ID_SELECTOR); - const val = qrcode.text(); - qrcode.empty(); - new (window as any).QRCode(qrcode.get(0), val); -} diff --git a/client/src/lib/totp-register/ui-selector.ts b/client/src/lib/totp-register/ui-selector.ts deleted file mode 100644 index 9d43fabe..00000000 --- a/client/src/lib/totp-register/ui-selector.ts +++ /dev/null @@ -1,2 +0,0 @@ - -export const QRCODE_ID_SELECTOR = "#qrcode"; \ No newline at end of file diff --git a/client/src/lib/u2f-register/u2f-register.ts b/client/src/lib/u2f-register/u2f-register.ts deleted file mode 100644 index abf40ee0..00000000 --- a/client/src/lib/u2f-register/u2f-register.ts +++ /dev/null @@ -1,56 +0,0 @@ - -import BluebirdPromise = require("bluebird"); -import U2f = require("u2f"); -import * as U2fApi from "u2f-api"; -import { Notifier } from "../Notifier"; -import GetPromised from "../GetPromised"; -import Endpoints = require("../../../../shared/api"); -import UserMessages = require("../../../../shared/UserMessages"); -import { RedirectionMessage } from "../../../../shared/RedirectionMessage"; -import { ErrorMessage } from "../../../../shared/ErrorMessage"; -import { SafeRedirect } from "../SafeRedirect"; - -export default function (window: Window, $: JQueryStatic) { - const notifier = new Notifier(".notification", $); - - function checkRegistration(regResponse: U2fApi.RegisterResponse): BluebirdPromise { - return new BluebirdPromise(function (resolve, reject) { - $.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, regResponse, undefined, "json") - .done((body: RedirectionMessage | ErrorMessage) => { - if (body && "error" in body) { - reject(new Error((body as ErrorMessage).error)); - return; - } - resolve((body as RedirectionMessage).redirect); - }) - .fail((xhr, status) => { - reject(new Error("Failed to register device.")); - }); - }); - } - - function requestRegistration(): BluebirdPromise { - return GetPromised($, Endpoints.SECOND_FACTOR_U2F_REGISTER_REQUEST_GET, {}, - undefined, "json") - .then((registrationRequest: U2f.Request) => { - return U2fApi.register(registrationRequest, [], 60); - }) - .then((res) => checkRegistration(res)); - } - - function onRegisterFailure(err: Error) { - notifier.error(UserMessages.REGISTRATION_U2F_FAILED); - } - - $(document).ready(function () { - requestRegistration() - .then((redirectionUrl: string) => { - SafeRedirect(redirectionUrl, () => { - notifier.error(UserMessages.CANNOT_REDIRECT_TO_EXTERNAL_DOMAIN); - }); - }) - .catch((err) => { - onRegisterFailure(err); - }); - }); -} diff --git a/client-react/src/react-app-env.d.ts b/client/src/react-app-env.d.ts similarity index 100% rename from client-react/src/react-app-env.d.ts rename to client/src/react-app-env.d.ts diff --git a/client-react/src/reducers/Portal/Authentication/actions.ts b/client/src/reducers/Portal/Authentication/actions.ts similarity index 100% rename from client-react/src/reducers/Portal/Authentication/actions.ts rename to client/src/reducers/Portal/Authentication/actions.ts diff --git a/client-react/src/reducers/Portal/Authentication/reducer.ts b/client/src/reducers/Portal/Authentication/reducer.ts similarity index 100% rename from client-react/src/reducers/Portal/Authentication/reducer.ts rename to client/src/reducers/Portal/Authentication/reducer.ts diff --git a/client-react/src/reducers/Portal/FirstFactor/actions.ts b/client/src/reducers/Portal/FirstFactor/actions.ts similarity index 100% rename from client-react/src/reducers/Portal/FirstFactor/actions.ts rename to client/src/reducers/Portal/FirstFactor/actions.ts diff --git a/client-react/src/reducers/Portal/FirstFactor/reducer.ts b/client/src/reducers/Portal/FirstFactor/reducer.ts similarity index 100% rename from client-react/src/reducers/Portal/FirstFactor/reducer.ts rename to client/src/reducers/Portal/FirstFactor/reducer.ts diff --git a/client-react/src/reducers/Portal/ForgotPassword/actions.ts b/client/src/reducers/Portal/ForgotPassword/actions.ts similarity index 100% rename from client-react/src/reducers/Portal/ForgotPassword/actions.ts rename to client/src/reducers/Portal/ForgotPassword/actions.ts diff --git a/client-react/src/reducers/Portal/ForgotPassword/reducer.ts b/client/src/reducers/Portal/ForgotPassword/reducer.ts similarity index 100% rename from client-react/src/reducers/Portal/ForgotPassword/reducer.ts rename to client/src/reducers/Portal/ForgotPassword/reducer.ts diff --git a/client-react/src/reducers/Portal/OneTimePasswordRegistration/actions.ts b/client/src/reducers/Portal/OneTimePasswordRegistration/actions.ts similarity index 100% rename from client-react/src/reducers/Portal/OneTimePasswordRegistration/actions.ts rename to client/src/reducers/Portal/OneTimePasswordRegistration/actions.ts diff --git a/client-react/src/reducers/Portal/OneTimePasswordRegistration/reducer.ts b/client/src/reducers/Portal/OneTimePasswordRegistration/reducer.ts similarity index 100% rename from client-react/src/reducers/Portal/OneTimePasswordRegistration/reducer.ts rename to client/src/reducers/Portal/OneTimePasswordRegistration/reducer.ts diff --git a/client-react/src/reducers/Portal/ResetPassword/actions.ts b/client/src/reducers/Portal/ResetPassword/actions.ts similarity index 100% rename from client-react/src/reducers/Portal/ResetPassword/actions.ts rename to client/src/reducers/Portal/ResetPassword/actions.ts diff --git a/client-react/src/reducers/Portal/ResetPassword/reducer.ts b/client/src/reducers/Portal/ResetPassword/reducer.ts similarity index 100% rename from client-react/src/reducers/Portal/ResetPassword/reducer.ts rename to client/src/reducers/Portal/ResetPassword/reducer.ts diff --git a/client-react/src/reducers/Portal/SecondFactor/actions.ts b/client/src/reducers/Portal/SecondFactor/actions.ts similarity index 100% rename from client-react/src/reducers/Portal/SecondFactor/actions.ts rename to client/src/reducers/Portal/SecondFactor/actions.ts diff --git a/client-react/src/reducers/Portal/SecondFactor/reducer.ts b/client/src/reducers/Portal/SecondFactor/reducer.ts similarity index 100% rename from client-react/src/reducers/Portal/SecondFactor/reducer.ts rename to client/src/reducers/Portal/SecondFactor/reducer.ts diff --git a/client-react/src/reducers/Portal/SecurityKeyRegistration/actions.ts b/client/src/reducers/Portal/SecurityKeyRegistration/actions.ts similarity index 100% rename from client-react/src/reducers/Portal/SecurityKeyRegistration/actions.ts rename to client/src/reducers/Portal/SecurityKeyRegistration/actions.ts diff --git a/client-react/src/reducers/Portal/SecurityKeyRegistration/reducer.ts b/client/src/reducers/Portal/SecurityKeyRegistration/reducer.ts similarity index 100% rename from client-react/src/reducers/Portal/SecurityKeyRegistration/reducer.ts rename to client/src/reducers/Portal/SecurityKeyRegistration/reducer.ts diff --git a/client-react/src/reducers/Portal/index.ts b/client/src/reducers/Portal/index.ts similarity index 100% rename from client-react/src/reducers/Portal/index.ts rename to client/src/reducers/Portal/index.ts diff --git a/client-react/src/reducers/constants.ts b/client/src/reducers/constants.ts similarity index 100% rename from client-react/src/reducers/constants.ts rename to client/src/reducers/constants.ts diff --git a/client-react/src/reducers/index.ts b/client/src/reducers/index.ts similarity index 100% rename from client-react/src/reducers/index.ts rename to client/src/reducers/index.ts diff --git a/client-react/src/routes/index.ts b/client/src/routes/index.ts similarity index 100% rename from client-react/src/routes/index.ts rename to client/src/routes/index.ts diff --git a/client-react/src/routes/routes.ts b/client/src/routes/routes.ts similarity index 100% rename from client-react/src/routes/routes.ts rename to client/src/routes/routes.ts diff --git a/client-react/src/serviceWorker.ts b/client/src/serviceWorker.ts similarity index 100% rename from client-react/src/serviceWorker.ts rename to client/src/serviceWorker.ts diff --git a/client-react/src/services/AutheliaService.ts b/client/src/services/AutheliaService.ts similarity index 100% rename from client-react/src/services/AutheliaService.ts rename to client/src/services/AutheliaService.ts diff --git a/client/src/thirdparties/qrcode.min.js b/client/src/thirdparties/qrcode.min.js deleted file mode 100644 index 993e88f3..00000000 --- a/client/src/thirdparties/qrcode.min.js +++ /dev/null @@ -1 +0,0 @@ -var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j=0?p.get(q):0}}for(var r=0,m=0;mm;m++)for(var j=0;jm;m++)for(var j=0;j=0;)b^=f.G15<=0;)b^=f.G18<>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;cf;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=[''],h=0;d>h;h++){g.push("");for(var i=0;d>i;i++)g.push('');g.push("")}g.push("
"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); \ No newline at end of file diff --git a/client-react/src/types/AuthenticationLevel.ts b/client/src/types/AuthenticationLevel.ts similarity index 100% rename from client-react/src/types/AuthenticationLevel.ts rename to client/src/types/AuthenticationLevel.ts diff --git a/client-react/src/views/AuthenticationView/AuthenticationView.tsx b/client/src/views/AuthenticationView/AuthenticationView.tsx similarity index 100% rename from client-react/src/views/AuthenticationView/AuthenticationView.tsx rename to client/src/views/AuthenticationView/AuthenticationView.tsx diff --git a/client-react/src/views/AuthenticationView/RemoteState.ts b/client/src/views/AuthenticationView/RemoteState.ts similarity index 100% rename from client-react/src/views/AuthenticationView/RemoteState.ts rename to client/src/views/AuthenticationView/RemoteState.ts diff --git a/client-react/src/views/ConfirmationSentView/ConfirmationSentView.module.css b/client/src/views/ConfirmationSentView/ConfirmationSentView.module.css similarity index 100% rename from client-react/src/views/ConfirmationSentView/ConfirmationSentView.module.css rename to client/src/views/ConfirmationSentView/ConfirmationSentView.module.css diff --git a/client-react/src/views/ConfirmationSentView/ConfirmationSentView.tsx b/client/src/views/ConfirmationSentView/ConfirmationSentView.tsx similarity index 100% rename from client-react/src/views/ConfirmationSentView/ConfirmationSentView.tsx rename to client/src/views/ConfirmationSentView/ConfirmationSentView.tsx diff --git a/client-react/src/views/ForgotPasswordView/ForgotPasswordView.tsx b/client/src/views/ForgotPasswordView/ForgotPasswordView.tsx similarity index 100% rename from client-react/src/views/ForgotPasswordView/ForgotPasswordView.tsx rename to client/src/views/ForgotPasswordView/ForgotPasswordView.tsx diff --git a/client-react/src/views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView.tsx b/client/src/views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView.tsx similarity index 100% rename from client-react/src/views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView.tsx rename to client/src/views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView.tsx diff --git a/client-react/src/views/OneTimePasswordRegistrationView/Secret.ts b/client/src/views/OneTimePasswordRegistrationView/Secret.ts similarity index 100% rename from client-react/src/views/OneTimePasswordRegistrationView/Secret.ts rename to client/src/views/OneTimePasswordRegistrationView/Secret.ts diff --git a/client-react/src/views/ResetPasswordView/ResetPasswordView.tsx b/client/src/views/ResetPasswordView/ResetPasswordView.tsx similarity index 100% rename from client-react/src/views/ResetPasswordView/ResetPasswordView.tsx rename to client/src/views/ResetPasswordView/ResetPasswordView.tsx diff --git a/client-react/src/views/SecurityKeyRegistrationView/SecurityKeyRegistrationView.tsx b/client/src/views/SecurityKeyRegistrationView/SecurityKeyRegistrationView.tsx similarity index 100% rename from client-react/src/views/SecurityKeyRegistrationView/SecurityKeyRegistrationView.tsx rename to client/src/views/SecurityKeyRegistrationView/SecurityKeyRegistrationView.tsx diff --git a/client/test/Notifier.test.ts b/client/test/Notifier.test.ts deleted file mode 100644 index 70bfea14..00000000 --- a/client/test/Notifier.test.ts +++ /dev/null @@ -1,71 +0,0 @@ - -import Assert = require("assert"); -import Sinon = require("sinon"); -import JQueryMock = require("./mocks/jquery"); - -import { Notifier } from "../src/lib/Notifier"; - -describe("test notifier", function() { - const SELECTOR = "dummy-selector"; - const MESSAGE = "This is a message"; - let jqueryMock: { jquery: JQueryMock.JQueryMock, element: JQueryMock.JQueryElementsMock }; - let clock: any; - - beforeEach(function() { - jqueryMock = JQueryMock.JQueryMock(); - clock = Sinon.useFakeTimers(); - }); - - afterEach(function() { - clock.restore(); - }); - - function should_fade_in_and_out_on_notification(notificationType: string): void { - const delayReturn = { - fadeOut: Sinon.stub() - }; - - jqueryMock.element.fadeIn.yields(); - - function onFadedInCallback() { - Assert(jqueryMock.element.fadeIn.calledOnce); - Assert(jqueryMock.element.addClass.calledWith(notificationType)); - Assert(!jqueryMock.element.removeClass.calledWith(notificationType)); - clock.tick(10 * 1000); - } - - function onFadedOutCallback() { - Assert(jqueryMock.element.removeClass.calledWith(notificationType)); - Assert(jqueryMock.element.fadeOut.calledOnce); - } - - const notifier = new Notifier(SELECTOR, jqueryMock.jquery as any); - - // Call the method by its name... Bad but allows code reuse. - (notifier as any)[notificationType](MESSAGE, { - onFadedIn: onFadedInCallback, - onFadedOut: onFadedOutCallback - }); - - clock.tick(510); - - Assert(jqueryMock.element.fadeIn.calledOnce); - } - - - it("should fade in and fade out an error message", function() { - should_fade_in_and_out_on_notification("error"); - }); - - it("should fade in and fade out an info message", function() { - should_fade_in_and_out_on_notification("info"); - }); - - it("should fade in and fade out an warning message", function() { - should_fade_in_and_out_on_notification("warning"); - }); - - it("should fade in and fade out an success message", function() { - should_fade_in_and_out_on_notification("success"); - }); -}); \ No newline at end of file diff --git a/client/test/firstfactor/FirstFactorValidator.test.ts b/client/test/firstfactor/FirstFactorValidator.test.ts deleted file mode 100644 index 027bc71d..00000000 --- a/client/test/firstfactor/FirstFactorValidator.test.ts +++ /dev/null @@ -1,46 +0,0 @@ - -import FirstFactorValidator = require("../../src/lib/firstfactor/FirstFactorValidator"); -import JQueryMock = require("../mocks/jquery"); -import BluebirdPromise = require("bluebird"); -import Assert = require("assert"); - -describe("test FirstFactorValidator", function () { - it("should validate first factor successfully", () => { - const postPromise = JQueryMock.JQueryDeferredMock(); - postPromise.done.yields({ redirect: "http://redirect" }); - postPromise.done.returns(postPromise); - - const jqueryMock = JQueryMock.JQueryMock(); - jqueryMock.jquery.ajax.returns(postPromise); - - return FirstFactorValidator.validate("username", "password", false, - "http://redirect", jqueryMock.jquery as any); - }); - - function should_fail_first_factor_validation(errorMessage: string) { - const xhr = { - status: 401 - }; - const postPromise = JQueryMock.JQueryDeferredMock(); - postPromise.fail.yields(xhr, errorMessage); - postPromise.done.returns(postPromise); - - const jqueryMock = JQueryMock.JQueryMock(); - jqueryMock.jquery.ajax.returns(postPromise); - - return FirstFactorValidator.validate("username", "password", false, - "http://redirect", jqueryMock.jquery as any) - .then(function () { - return BluebirdPromise.reject(new Error("First factor validation successfully finished while it should have not.")); - }, function (err: Error) { - Assert.equal(errorMessage, err.message); - return BluebirdPromise.resolve(); - }); - } - - describe("should fail first factor validation", () => { - it("should fail with error", () => { - return should_fail_first_factor_validation("Authentication failed. Please check your credentials."); - }); - }); -}); \ No newline at end of file diff --git a/client/test/mocks/NotifierStub.ts b/client/test/mocks/NotifierStub.ts deleted file mode 100644 index 9c268d66..00000000 --- a/client/test/mocks/NotifierStub.ts +++ /dev/null @@ -1,33 +0,0 @@ - -import Sinon = require("sinon"); -import { INotifier } from "../../src/lib/INotifier"; - -export class NotifierStub implements INotifier { - successStub: Sinon.SinonStub; - errorStub: Sinon.SinonStub; - warnStub: Sinon.SinonStub; - infoStub: Sinon.SinonStub; - - constructor() { - this.successStub = Sinon.stub(); - this.errorStub = Sinon.stub(); - this.warnStub = Sinon.stub(); - this.infoStub = Sinon.stub(); - } - - success(msg: string) { - this.successStub(); - } - - error(msg: string) { - this.errorStub(); - } - - warning(msg: string) { - this.warnStub(); - } - - info(msg: string) { - this.infoStub(); - } -} \ No newline at end of file diff --git a/client/test/mocks/jquery.ts b/client/test/mocks/jquery.ts deleted file mode 100644 index 273f9086..00000000 --- a/client/test/mocks/jquery.ts +++ /dev/null @@ -1,59 +0,0 @@ - -import sinon = require("sinon"); -import jquery = require("jquery"); - - -export interface JQueryMock extends sinon.SinonStub { - get: sinon.SinonStub; - post: sinon.SinonStub; - ajax: sinon.SinonStub; - notify: sinon.SinonStub; -} - -export interface JQueryElementsMock { - ready: sinon.SinonStub; - show: sinon.SinonStub; - hide: sinon.SinonStub; - html: sinon.SinonStub; - addClass: sinon.SinonStub; - removeClass: sinon.SinonStub; - fadeIn: sinon.SinonStub; - fadeOut: sinon.SinonStub; - on: sinon.SinonStub; -} - -export interface JQueryDeferredMock { - done: sinon.SinonStub; - fail: sinon.SinonStub; -} - -export function JQueryMock(): { jquery: JQueryMock, element: JQueryElementsMock } { - const jquery = sinon.stub() as any; - const jqueryInstance: JQueryElementsMock = { - ready: sinon.stub(), - show: sinon.stub(), - hide: sinon.stub(), - html: sinon.stub(), - addClass: sinon.stub(), - removeClass: sinon.stub(), - fadeIn: sinon.stub(), - fadeOut: sinon.stub(), - on: sinon.stub() - }; - jquery.ajax = sinon.stub(); - jquery.get = sinon.stub(); - jquery.post = sinon.stub(); - jquery.notify = sinon.stub(); - jquery.returns(jqueryInstance); - return { - jquery: jquery, - element: jqueryInstance - }; -} - -export function JQueryDeferredMock(): JQueryDeferredMock { - return { - done: sinon.stub(), - fail: sinon.stub() - }; -} diff --git a/client/test/mocks/u2f-api.ts b/client/test/mocks/u2f-api.ts deleted file mode 100644 index d123f6a9..00000000 --- a/client/test/mocks/u2f-api.ts +++ /dev/null @@ -1,14 +0,0 @@ - -import sinon = require("sinon"); - -export interface U2FApiMock { - sign: sinon.SinonStub; - register: sinon.SinonStub; -} - -export function U2FApiMock(): U2FApiMock { - return { - sign: sinon.stub(), - register: sinon.stub() - }; -} \ No newline at end of file diff --git a/client/test/secondfactor/TOTPValidator.test.ts b/client/test/secondfactor/TOTPValidator.test.ts deleted file mode 100644 index 5dd6f15c..00000000 --- a/client/test/secondfactor/TOTPValidator.test.ts +++ /dev/null @@ -1,37 +0,0 @@ - -import TOTPValidator = require("../../src/lib/secondfactor/TOTPValidator"); -import JQueryMock = require("../mocks/jquery"); -import BluebirdPromise = require("bluebird"); -import Assert = require("assert"); - -describe("test TOTPValidator", function () { - it("should initiate an identity check successfully", () => { - const postPromise = JQueryMock.JQueryDeferredMock(); - postPromise.done.yields({ redirect: "https://home.test.url" }); - postPromise.done.returns(postPromise); - - const jqueryMock = JQueryMock.JQueryMock(); - jqueryMock.jquery.ajax.returns(postPromise); - - return TOTPValidator.validate("totp_token", jqueryMock.jquery as any); - }); - - it("should fail validating TOTP token", () => { - const errorMessage = "Error while validating TOTP token"; - - const postPromise = JQueryMock.JQueryDeferredMock(); - postPromise.fail.yields(undefined, errorMessage); - postPromise.done.returns(postPromise); - - const jqueryMock = JQueryMock.JQueryMock(); - jqueryMock.jquery.ajax.returns(postPromise); - - return TOTPValidator.validate("totp_token", jqueryMock.jquery as any) - .then(function () { - return BluebirdPromise.reject(new Error("Registration successfully finished while it should have not.")); - }, function (err: Error) { - Assert.equal(errorMessage, err.message); - return BluebirdPromise.resolve(); - }); - }); -}); \ No newline at end of file diff --git a/client/test/totp-register/totp-register.test.ts b/client/test/totp-register/totp-register.test.ts deleted file mode 100644 index 86fc455a..00000000 --- a/client/test/totp-register/totp-register.test.ts +++ /dev/null @@ -1,31 +0,0 @@ - -import sinon = require("sinon"); -import assert = require("assert"); - -import UISelector = require("../../src/lib/totp-register/ui-selector"); -import TOTPRegister = require("../../src/lib/totp-register/totp-register"); - -describe("test totp-register", function() { - let jqueryMock: any; - let windowMock: any; - before(function() { - jqueryMock = sinon.stub(); - windowMock = { - QRCode: sinon.spy() - }; - }); - - it("should create qrcode in page", function() { - const mock = { - text: sinon.stub(), - empty: sinon.stub(), - get: sinon.stub() - }; - jqueryMock.withArgs(UISelector.QRCODE_ID_SELECTOR).returns(mock); - - TOTPRegister.default(windowMock, jqueryMock); - - assert(mock.text.calledOnce); - assert(mock.empty.calledOnce); - }); -}); \ No newline at end of file diff --git a/client/tsconfig.json b/client/tsconfig.json index 0bb4d62f..c5d6f230 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,24 +1,25 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "moduleResolution": "node", - "noImplicitAny": true, - "sourceMap": true, - "removeComments": true, - "outDir": "../dist", - "baseUrl": ".", - "paths": { - "*": [ - "./types/*", - "../shared/types/*" - ] - } - }, - "include": [ - "src/**/*" - ], - "exclude": [ - "test/**/*" + "compilerOptions": { + "target": "es6", + "allowJs": true, + "skipLibCheck": false, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "lib": [ + "dom", + "dom.iterable", + "esnext" ] + }, + "include": [ + "src" + ] } diff --git a/client/tslint.json b/client/tslint.json deleted file mode 100644 index c2c1b750..00000000 --- a/client/tslint.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "rules": { - "class-name": true, - "comment-format": [ - true, - "check-space" - ], - "indent": [ - true, - "spaces" - ], - "one-line": [ - true, - "check-open-brace", - "check-whitespace" - ], - "no-var-keyword": true, - "quotemark": [ - true, - "double", - "avoid-escape" - ], - "semicolon": [ - true, - "always", - "ignore-bound-class-methods" - ], - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-module", - "check-separator", - "check-type" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - }, - { - "call-signature": "onespace", - "index-signature": "onespace", - "parameter": "onespace", - "property-declaration": "onespace", - "variable-declaration": "onespace" - } - ], - "no-internal-module": true, - "no-trailing-whitespace": true, - "no-null-keyword": true, - "prefer-const": true, - "jsdoc-format": true - } -} diff --git a/scripts/dc-dev.sh b/scripts/dc-dev.sh index daf543b5..08f2dc20 100755 --- a/scripts/dc-dev.sh +++ b/scripts/dc-dev.sh @@ -4,7 +4,7 @@ set -e docker-compose \ -f docker-compose.dev.yml \ - -f client-react/docker-compose.yml \ + -f client/docker-compose.yml \ -f example/compose/docker-compose.base.yml \ -f example/compose/mongo/docker-compose.yml \ -f example/compose/redis/docker-compose.yml \ diff --git a/server/src/lib/routes/error/401/get.spec.ts b/server/src/lib/routes/error/401/get.spec.ts deleted file mode 100644 index 9fdac9c3..00000000 --- a/server/src/lib/routes/error/401/get.spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import Sinon = require("sinon"); -import Express = require("express"); -import Assert = require("assert"); -import Get401 from "./get"; -import { ServerVariables } from "../../../ServerVariables"; -import { ServerVariablesMockBuilder, ServerVariablesMock } - from "../../../ServerVariablesMockBuilder.spec"; - -describe("routes/error/401/get", function () { - let vars: ServerVariables; - let mocks: ServerVariablesMock; - let req: any; - let res: any; - let renderSpy: Sinon.SinonSpy; - - beforeEach(function () { - const s = ServerVariablesMockBuilder.build(); - vars = s.variables; - mocks = s.mocks; - - renderSpy = Sinon.spy(); - req = { - headers: {} - }; - res = { - render: renderSpy - }; - }); - - it("should set redirection url to the default redirection url", function () { - vars.config.default_redirection_url = "http://default-redirection"; - return Get401(vars)(req, res as any) - .then(function () { - Assert(renderSpy.calledOnce); - Assert(renderSpy.calledWithExactly("errors/401", { - redirection_url: "http://default-redirection" - })); - }); - }); - - it("should set redirection url to the referer", function () { - req.headers["referer"] = "http://redirection"; - return Get401(vars)(req, res as any) - .then(function () { - Assert(renderSpy.calledOnce); - Assert(renderSpy.calledWithExactly("errors/401", { - redirection_url: "http://redirection" - })); - }); - }); - - it("should render without redirecting the user", function () { - return Get401(vars)(req, res as any) - .then(function () { - Assert(renderSpy.calledOnce); - Assert(renderSpy.calledWithExactly("errors/401", { - redirection_url: undefined - })); - }); - }); -}); \ No newline at end of file diff --git a/server/src/lib/routes/error/401/get.ts b/server/src/lib/routes/error/401/get.ts deleted file mode 100644 index ca4a3963..00000000 --- a/server/src/lib/routes/error/401/get.ts +++ /dev/null @@ -1,15 +0,0 @@ - -import BluebirdPromise = require("bluebird"); -import express = require("express"); -import redirector from "../redirector"; -import { ServerVariables } from "../../../ServerVariables"; - -export default function (vars: ServerVariables) { - return function (req: express.Request, res: express.Response): BluebirdPromise { - const redirectionUrl = redirector(req, vars); - res.render("errors/401", { - redirection_url: redirectionUrl - }); - return BluebirdPromise.resolve(); - }; -} diff --git a/server/src/lib/routes/error/403/get.spec.ts b/server/src/lib/routes/error/403/get.spec.ts deleted file mode 100644 index 22eb8485..00000000 --- a/server/src/lib/routes/error/403/get.spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import Sinon = require("sinon"); -import Express = require("express"); -import Assert = require("assert"); -import Get403 from "./get"; -import { ServerVariables } from "../../../ServerVariables"; -import { ServerVariablesMockBuilder, ServerVariablesMock } - from "../../../ServerVariablesMockBuilder.spec"; - -describe("routes/error/403/get", function () { - let vars: ServerVariables; - let mocks: ServerVariablesMock; - let req: any; - let res: any; - let renderSpy: Sinon.SinonSpy; - - beforeEach(function () { - const s = ServerVariablesMockBuilder.build(); - vars = s.variables; - mocks = s.mocks; - - renderSpy = Sinon.spy(); - req = { - headers: {} - }; - res = { - render: renderSpy - }; - }); - - it("should set redirection url to the default redirection url", function () { - vars.config.default_redirection_url = "http://default-redirection"; - return Get403(vars)(req, res as any) - .then(function () { - Assert(renderSpy.calledOnce); - Assert(renderSpy.calledWithExactly("errors/403", { - redirection_url: "http://default-redirection" - })); - }); - }); - - it("should set redirection url to the referer", function () { - req.headers["referer"] = "http://redirection"; - return Get403(vars)(req, res as any) - .then(function () { - Assert(renderSpy.calledOnce); - Assert(renderSpy.calledWithExactly("errors/403", { - redirection_url: "http://redirection" - })); - }); - }); - - it("should render without redirecting the user", function () { - return Get403(vars)(req, res as any) - .then(function () { - Assert(renderSpy.calledOnce); - Assert(renderSpy.calledWithExactly("errors/403", { - redirection_url: undefined - })); - }); - }); -}); \ No newline at end of file diff --git a/server/src/lib/routes/error/403/get.ts b/server/src/lib/routes/error/403/get.ts deleted file mode 100644 index 3ab0319e..00000000 --- a/server/src/lib/routes/error/403/get.ts +++ /dev/null @@ -1,15 +0,0 @@ - -import BluebirdPromise = require("bluebird"); -import express = require("express"); -import redirector from "../redirector"; -import { ServerVariables } from "../../../ServerVariables"; - -export default function (vars: ServerVariables) { - return function (req: express.Request, res: express.Response): BluebirdPromise { - const redirectionUrl = redirector(req, vars); - res.render("errors/403", { - redirection_url: redirectionUrl - }); - return BluebirdPromise.resolve(); - }; -} \ No newline at end of file diff --git a/server/src/lib/routes/error/404/get.spec.ts b/server/src/lib/routes/error/404/get.spec.ts deleted file mode 100644 index 73e4e6ce..00000000 --- a/server/src/lib/routes/error/404/get.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Sinon = require("sinon"); -import Express = require("express"); -import Assert = require("assert"); -import Get404 from "./get"; - -describe("routes/error/404/get", function () { - it("should render the page", function () { - const req = {} as Express.Request; - const res = { - render: Sinon.stub() - }; - - return Get404(req, res as any) - .then(function () { - Assert(res.render.calledOnce); - Assert(res.render.calledWith("errors/404")); - }); - }); -}); \ No newline at end of file diff --git a/server/src/lib/routes/error/404/get.ts b/server/src/lib/routes/error/404/get.ts deleted file mode 100644 index 6693b6fc..00000000 --- a/server/src/lib/routes/error/404/get.ts +++ /dev/null @@ -1,8 +0,0 @@ - -import BluebirdPromise = require("bluebird"); -import express = require("express"); - -export default function (req: express.Request, res: express.Response): BluebirdPromise { - res.render("errors/404"); - return BluebirdPromise.resolve(); -} \ No newline at end of file diff --git a/server/src/lib/routes/error/redirector.ts b/server/src/lib/routes/error/redirector.ts deleted file mode 100644 index b1a3ccc1..00000000 --- a/server/src/lib/routes/error/redirector.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Express = require("express"); -import { ServerVariables } from "../../ServerVariables"; - -export default function (req: Express.Request, vars: ServerVariables): string { - let redirectionUrl: string; - - if (req.headers && req.headers["referer"]) - redirectionUrl = "" + req.headers["referer"]; - else if (vars.config.default_redirection_url) - redirectionUrl = vars.config.default_redirection_url; - - return redirectionUrl; -} \ No newline at end of file diff --git a/server/src/lib/routes/firstfactor/post.ts b/server/src/lib/routes/firstfactor/post.ts index 1e5b9e6a..16e79f7b 100644 --- a/server/src/lib/routes/firstfactor/post.ts +++ b/server/src/lib/routes/firstfactor/post.ts @@ -2,17 +2,13 @@ import Exceptions = require("../../Exceptions"); import BluebirdPromise = require("bluebird"); import express = require("express"); -import Endpoint = require("../../../../../shared/api"); import ErrorReplies = require("../../ErrorReplies"); import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; -import Constants = require("../../../../../shared/constants"); import UserMessages = require("../../../../../shared/UserMessages"); import { ServerVariables } from "../../ServerVariables"; import { AuthenticationSession } from "../../../../types/AuthenticationSession"; import { GroupsAndEmails } from "../../authentication/backends/GroupsAndEmails"; import {Level} from "../../authentication/Level"; -import { Level as AuthorizationLevel } from "../../authorization/Level"; -import { URLDecomposer } from "../../utils/URLDecomposer"; export default function (vars: ServerVariables) { return function (req: express.Request, res: express.Response) @@ -49,19 +45,9 @@ export default function (vars: ServerVariables) { authSession.userid = username; authSession.keep_me_logged_in = keepMeLoggedIn; authSession.authentication_level = Level.ONE_FACTOR; - const redirectUrl: string = req.query[Constants.REDIRECT_QUERY_PARAM] !== "undefined" - // Fuck, don't know why it is a string! - ? req.query[Constants.REDIRECT_QUERY_PARAM] - : ""; const emails: string[] = groupsAndEmails.emails; const groups: string[] = groupsAndEmails.groups; - const decomposition = URLDecomposer.fromUrl(redirectUrl); - const authorizationLevel = (decomposition) - ? vars.authorizer.authorization( - {domain: decomposition.domain, resource: decomposition.path}, - {user: username, groups: groups}) - : AuthorizationLevel.TWO_FACTOR; if (emails.length > 0) authSession.email = emails[0]; @@ -69,27 +55,8 @@ export default function (vars: ServerVariables) { vars.logger.debug(req, "Mark successful authentication to regulator."); vars.regulator.mark(username, true); - - if (authorizationLevel <= AuthorizationLevel.ONE_FACTOR) { - let newRedirectionUrl: string = redirectUrl; - if (!newRedirectionUrl) - newRedirectionUrl = Endpoint.LOGGED_IN; - res.send({ - redirect: newRedirectionUrl - }); - vars.logger.debug(req, "Redirect to '%s'", redirectUrl); - } - else { - let newRedirectUrl = '/2fa'; - if (redirectUrl) { - newRedirectUrl += "?" + Constants.REDIRECT_QUERY_PARAM + "=" - + redirectUrl; - } - vars.logger.debug(req, "Redirect to '%s'", newRedirectUrl); - res.send({ - redirect: newRedirectUrl - }); - } + res.status(204); + res.send(); return BluebirdPromise.resolve(); }) .catch(Exceptions.LdapBindError, function (err: Error) { diff --git a/server/src/lib/routes/loggedin/get.ts b/server/src/lib/routes/loggedin/get.ts deleted file mode 100644 index 3a6f183d..00000000 --- a/server/src/lib/routes/loggedin/get.ts +++ /dev/null @@ -1,23 +0,0 @@ -import Express = require("express"); -import Endpoints = require("../../../../../shared/api"); -import BluebirdPromise = require("bluebird"); -import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; -import { ServerVariables } from "../../ServerVariables"; -import ErrorReplies = require("../../ErrorReplies"); - -export default function (vars: ServerVariables) { - function handler(req: Express.Request, res: Express.Response): BluebirdPromise { - return new BluebirdPromise(function (resolve, reject) { - const authSession = AuthenticationSessionHandler.get(req, vars.logger); - res.render("already-logged-in", { - logout_endpoint: Endpoints.LOGOUT_POST, - username: authSession.userid, - redirection_url: vars.config.default_redirection_url - }); - resolve(); - }) - .catch(ErrorReplies.replyWithError401(req, res, vars.logger)); - } - - return handler; -} diff --git a/server/src/lib/routes/password-reset/request/get.ts b/server/src/lib/routes/password-reset/request/get.ts deleted file mode 100644 index d77a000f..00000000 --- a/server/src/lib/routes/password-reset/request/get.ts +++ /dev/null @@ -1,8 +0,0 @@ - -import express = require("express"); - -const TEMPLATE_NAME = "password-reset-request"; - -export default function (req: express.Request, res: express.Response) { - res.render(TEMPLATE_NAME); -} \ No newline at end of file diff --git a/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts index 91407676..a1545cbe 100644 --- a/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts +++ b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts @@ -1,13 +1,11 @@ import express = require("express"); import BluebirdPromise = require("bluebird"); -import objectPath = require("object-path"); import { Identity } from "../../../../../../types/Identity"; import { IdentityValidable } from "../../../../IdentityValidable"; import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationTemplate"; import Constants = require("../constants"); -import Endpoints = require("../../../../../../../shared/api"); import ErrorReplies = require("../../../../ErrorReplies"); import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler"; import UserMessages = require("../../../../../../../shared/UserMessages"); @@ -100,7 +98,6 @@ export default class RegistrationHandler implements IdentityValidable { res.json({ base32_secret: secret.base32, otpauth_url: secret.otpauth_url, - login_endpoint: Endpoints.FIRST_FACTOR_GET }); }) .catch(ErrorReplies.replyWithError200(req, res, that.logger, UserMessages.OPERATION_FAILED)); diff --git a/server/src/lib/web_server/RestApi.ts b/server/src/lib/web_server/RestApi.ts index 12d66117..b5ca43ae 100644 --- a/server/src/lib/web_server/RestApi.ts +++ b/server/src/lib/web_server/RestApi.ts @@ -19,13 +19,6 @@ import U2FRegisterPost = require("../routes/secondfactor/u2f/register/post"); import U2FRegisterRequestGet = require("../routes/secondfactor/u2f/register_request/get"); import ResetPasswordFormPost = require("../routes/password-reset/form/post"); -import ResetPasswordRequestPost = require("../routes/password-reset/request/get"); - -import Error401Get = require("../routes/error/401/get"); -import Error403Get = require("../routes/error/403/get"); -import Error404Get = require("../routes/error/404/get"); - -import LoggedIn = require("../routes/loggedin/get"); import { ServerVariables } from "../ServerVariables"; import Endpoints = require("../../../../shared/api"); @@ -86,18 +79,10 @@ function setupResetPassword(app: Express.Application, vars: ServerVariables) { new ResetPasswordIdentityHandler(vars.logger, vars.usersDatabase), vars); - app.get(Endpoints.RESET_PASSWORD_REQUEST_GET, - ResetPasswordRequestPost.default); app.post(Endpoints.RESET_PASSWORD_FORM_POST, ResetPasswordFormPost.default(vars)); } -function setupErrors(app: Express.Application, vars: ServerVariables) { - app.get(Endpoints.ERROR_401_GET, Error401Get.default(vars)); - app.get(Endpoints.ERROR_403_GET, Error403Get.default(vars)); - app.get(Endpoints.ERROR_404_GET, Error404Get.default); -} - export class RestApi { static setup(app: Express.Application, vars: ServerVariables): void { app.get(Endpoints.STATE_GET, StateGet(vars)); @@ -110,10 +95,5 @@ export class RestApi { setupTotp(app, vars); setupU2f(app, vars); setupResetPassword(app, vars); - setupErrors(app, vars); - - app.get(Endpoints.LOGGED_IN, - RequireValidatedFirstFactor.middleware(vars.logger), - LoggedIn.default(vars)); } } diff --git a/server/src/views/already-logged-in.pug b/server/src/views/already-logged-in.pug deleted file mode 100644 index 137bbea3..00000000 --- a/server/src/views/already-logged-in.pug +++ /dev/null @@ -1,14 +0,0 @@ -extends layout/layout.pug - -block form-header - h1 Sign in - -block content - img(class="header-img" src="/img/success.png" alt="success") - if redirection_url - p You are already logged in as #{ username }.

- | If you are not redirected in few seconds, click here.

- | Otherwise, click here to log off. - else - p You are already logged in as #{ username }.

- | Click here to log off. diff --git a/server/src/views/errors/401.pug b/server/src/views/errors/401.pug deleted file mode 100644 index b7a222ad..00000000 --- a/server/src/views/errors/401.pug +++ /dev/null @@ -1,16 +0,0 @@ -extends ../layout/layout.pug - -block variables - - page_classname = "error-401"; - -block form-header - h1 Error 401 - -block content - img(class="header-img" src="/img/warning.png" alt="warning") - if redirection_url - p You are not authorized to access this resource.

- | Please click here if you are not - | redirected in few seconds. - else - p You are not authorized to access this resource. \ No newline at end of file diff --git a/server/src/views/errors/403.pug b/server/src/views/errors/403.pug deleted file mode 100644 index f4b5ca8a..00000000 --- a/server/src/views/errors/403.pug +++ /dev/null @@ -1,16 +0,0 @@ -extends ../layout/layout.pug - -block variables - - page_classname = "error-403"; - -block form-header - h1 Error 403 - -block content - img(class="header-img" src="/img/warning.png" alt="warning") - if redirection_url - p You don't have enough privileges to access this resource.

- | Please click here if you are not - | redirected in few seconds. - else - p You don't have enough privileges to access this resource. diff --git a/server/src/views/errors/404.pug b/server/src/views/errors/404.pug deleted file mode 100644 index 06d6375f..00000000 --- a/server/src/views/errors/404.pug +++ /dev/null @@ -1,11 +0,0 @@ -extends ../layout/layout.pug - -block variables - - page_classname = "error-404"; - -block form-header -

Error 404

- -block content - img(class="header-img" src="/img/warning.png" alt="warning") - p Page not found. diff --git a/server/src/views/firstfactor.pug b/server/src/views/firstfactor.pug deleted file mode 100644 index 046b8c4c..00000000 --- a/server/src/views/firstfactor.pug +++ /dev/null @@ -1,23 +0,0 @@ -extends layout/layout.pug - -block variables - - page_classname = "firstfactor"; - -block form-header - h1 Sign in - -block content - div(class="notification") - img(class="header-img" src="/img/user.png" alt="user profile") - p Enter your credentials to sign in - form(class="form-signin") - div(class="form-inputs") - input(type="text" class="form-control" id="username" placeholder="Username" required autofocus) - input(type="password" class="form-control" id="password" placeholder="Password" required) - button(id="signin" class="btn btn-lg btn-primary btn-block" type="submit") Sign in - div(class="keep-me-logged-in pull-left") - input(type="checkbox" id="keep_me_logged_in" name="keep_me_logged_in" value="true") - label(for="keep_me_logged_in") Keep me logged in - div(class="bottom-right-links pull-right") - a(href=reset_password_request_endpoint, class="link forgot-password") Forgot password? - span(class="clearfix") diff --git a/server/src/views/layout/layout.pug b/server/src/views/layout/layout.pug deleted file mode 100644 index 8caf710b..00000000 --- a/server/src/views/layout/layout.pug +++ /dev/null @@ -1,28 +0,0 @@ -block variables - -doctype html -html - head - title Authelia - 2FA - meta(name="viewport", content="width=device-width, initial-scale=1.0") - meta(name="robots", content="noindex, nofollow, nosnippet, noarchive") - meta(http-equiv="Content-Security-Policy", content="default-src 'self'; img-src 'self' data:;") - link(rel="icon", href="/img/icon.png" type="image/png" sizes="32x32") - link(rel="stylesheet", type="text/css", href="/css/authelia.css") - if redirection_url - meta(http-equiv="refresh" content="4;url=" + redirection_url) - body - div(class="container") - div(class="row") - div(class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3") - div(class="account-wall " + page_classname) - div(class="row header") - block form-header - div(class="row body") - div(class="form col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2") - block content - div(class="row footer poweredby-block") - div(class="poweredby col-xs-6 col-xs-offset-4 col-sm-6 col-sm-offset-4 col-md-6 col-md-offset-4") - | Powered by Authelia - block entrypoint - script(src="/js/authelia.js", type="text/javascript") \ No newline at end of file diff --git a/server/src/views/need-identity-validation.pug b/server/src/views/need-identity-validation.pug deleted file mode 100644 index 4cfd6271..00000000 --- a/server/src/views/need-identity-validation.pug +++ /dev/null @@ -1,12 +0,0 @@ -extends layout/layout.pug - -block variables - - page_classname = "identity-validation"; - -block form-header - h1 Registration - -block content - img(class="header-img" src="/img/mail.png" alt="mail") - p A confirmation email has been sent to your mailbox. - | Please open it and click on the link within 15 minutes to confirm the registration. diff --git a/server/src/views/password-reset-form.pug b/server/src/views/password-reset-form.pug deleted file mode 100644 index 07f0baa7..00000000 --- a/server/src/views/password-reset-form.pug +++ /dev/null @@ -1,18 +0,0 @@ -extends layout/layout.pug - -block variables - - page_classname = "password-reset-form"; - -block form-header - h1 Reset password - -block content - div(class="notification") - img(class="header-img" src="/img/password.png" alt="password") - p Set your new password and confirm it. - form(class="form-signin") - div(class="form-inputs") - input(class="form-control" type="password" name="password1" id="password1" placeholder="New password" required="required") - input(class="form-control" type="password" name="password2" id="password2" placeholder="Password confirmation" required="required") - button(id="reset-password-button" class="btn btn-lg btn-primary btn-block" type="submit") Reset Password - span(class="clearfix") diff --git a/server/src/views/password-reset-request.pug b/server/src/views/password-reset-request.pug deleted file mode 100644 index 21746af9..00000000 --- a/server/src/views/password-reset-request.pug +++ /dev/null @@ -1,18 +0,0 @@ -extends layout/layout.pug - -block variables - - page_classname = "password-reset-request"; - -block form-header - h1 Reset password - -block content - div(class="notification") - div - img(class="header-img" src="/img/password.png" alt="password") - p After giving your username, you will receive an email to change your password. - form(class="form-signin") - div(class="form-inputs") - input(type="text" class="form-control" name="username" id="username" placeholder="Your username" required="required") - button(id="reset-password-button" class="btn btn-lg btn-primary btn-block" type="submit") Reset Password - span(class="clearfix") diff --git a/server/src/views/secondfactor.pug b/server/src/views/secondfactor.pug deleted file mode 100644 index 4df8ec25..00000000 --- a/server/src/views/secondfactor.pug +++ /dev/null @@ -1,30 +0,0 @@ -extends layout/layout.pug - -block variables - - page_classname = "secondfactor"; - -block form-header - h1 Sign in - -block content - div - div(class="notification") - h3 Hi #{username} - div(class="row") - div(class="u2f-token") - img(src="/img/pendrive.png", alt="security key") - p - | Please, touch your security key
- b Or
- | Get a one-time password - form(class="form-signin totp") - div(class="form-inputs") - input(type="text" autocomplete="off" class="form-control" id="token" placeholder="Token" required autofocus) - button(class="btn btn-lg btn-primary btn-block totp-button" type="submit") Sign in - div(class="pull-right bottom-right-links") - div Need to register? - div - a(href=u2f_identity_start_endpoint, class="link register-u2f", data-toggle="tooltip", title="A security key is required to register.") Security key - | | - a(href=totp_identity_start_endpoint, class="link register-totp") Google Authenticator - span(class="clearfix") \ No newline at end of file diff --git a/server/src/views/totp-register.pug b/server/src/views/totp-register.pug deleted file mode 100644 index 1b4d9835..00000000 --- a/server/src/views/totp-register.pug +++ /dev/null @@ -1,25 +0,0 @@ -extends layout/layout.pug - -block variables - - page_classname = "totp-register"; - -block form-header - h1 One-time passwords - -block content - p Open Google Authenticator and add this entry - p(id="secret") #{ base32_secret } - p or scan this barcode - div(id="qrcode") #{ otpauth_url } - p - a(href=login_endpoint, id="login-button") Login - div(class="need-google-authenticator") - | Need Google Authenticator? - div(class="store-badges") - a(href='https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1', target="_blank") - img(alt='Get it on Google Play', src='/img/stores/googleplay-badge.svg', class="store-badge") - a(href='https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8', target="_blank") - img(alt='Get it on Apple Store' src='/img/stores/applestore-badge.svg' class="store-badge") - -block entrypoint - script(src="/js/qrcode.min.js", type="text/javascript" ) diff --git a/server/src/views/u2f-register.pug b/server/src/views/u2f-register.pug deleted file mode 100644 index 5e24bc70..00000000 --- a/server/src/views/u2f-register.pug +++ /dev/null @@ -1,11 +0,0 @@ -extends layout/layout.pug - -block variables - - page_classname = "u2f-register"; - -block form-header - h1 Register your security key - -block content - p Touch the token to register your security key. - img(src="/img/pendrive.png" alt="pendrive") \ No newline at end of file diff --git a/shared/api.ts b/shared/api.ts index 2844cdcb..d02b9a78 100644 --- a/shared/api.ts +++ b/shared/api.ts @@ -239,18 +239,6 @@ export const RESET_PASSWORD_IDENTITY_FINISH_GET = "/api/password-reset/identity/ */ export const FIRST_FACTOR_POST = "/api/firstfactor"; -/** - * @api {get} / First factor page - * @apiName Login - * @apiGroup Authentication - * @apiVersion 1.0.0 - * - * @apiSuccess (Success 200) {String} Content The content of the first factor page. - * - * @apiDescription Serves the login page and create a create a cookie for the client. - */ -export const FIRST_FACTOR_GET = "/"; - /** * @api {get} /state Authentication state * @apiName State @@ -299,8 +287,3 @@ export const VERIFY_GET = "/api/verify"; */ export const LOGOUT_POST = "/api/logout"; -export const ERROR_401_GET = "/error/401"; -export const ERROR_403_GET = "/error/403"; -export const ERROR_404_GET = "/error/404"; - -export const LOGGED_IN = "/loggedin";