mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
Add default_redirection_url as configuration option
This URL is used when user access the authentication domain without providing the 'redirect' query parameter. In that case, Authelia does not know where to redirect the user. If the parameter is defined, Authelia can redirect the user to a default page when no redirect parameter is provided. When user is already authenticated and tries to access the authentication domain, the "already logged in" page is rendered and it now tells the user he is to be redirected in few seconds and uses this URL to redirect. This parameter is optional. If it is not provided, there is only a notification message at the end of the authentication process, as before, and the user is not redirected when visiting the authentication domain while already authenticated.
This commit is contained in:
parent
99b04809a5
commit
563e2da323
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import Endpoints = require("../../../../shared/api");
|
import Endpoints = require("../../../../shared/api");
|
||||||
|
import { RedirectionMessage } from "../../../../shared/RedirectionMessage";
|
||||||
|
import { ErrorMessage } from "../../../../shared/ErrorMessage";
|
||||||
|
|
||||||
export function validate(token: string, $: JQueryStatic): BluebirdPromise<string> {
|
export function validate(token: string, $: JQueryStatic): BluebirdPromise<string> {
|
||||||
return new BluebirdPromise<string>(function (resolve, reject) {
|
return new BluebirdPromise<string>(function (resolve, reject) {
|
||||||
|
@ -12,12 +14,12 @@ export function validate(token: string, $: JQueryStatic): BluebirdPromise<string
|
||||||
method: "POST",
|
method: "POST",
|
||||||
dataType: "json"
|
dataType: "json"
|
||||||
} as JQueryAjaxSettings)
|
} as JQueryAjaxSettings)
|
||||||
.done(function (body: any) {
|
.done(function (body: RedirectionMessage | ErrorMessage) {
|
||||||
if (body && body.error) {
|
if (body && "error" in body) {
|
||||||
reject(new Error(body.error));
|
reject(new Error((body as ErrorMessage).error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolve(body);
|
resolve((body as RedirectionMessage).redirect);
|
||||||
})
|
})
|
||||||
.fail(function (xhr: JQueryXHR, textStatus: string) {
|
.fail(function (xhr: JQueryXHR, textStatus: string) {
|
||||||
reject(new Error(textStatus));
|
reject(new Error(textStatus));
|
||||||
|
|
|
@ -6,21 +6,23 @@ import { SignMessage } from "../../../../shared/SignMessage";
|
||||||
import Endpoints = require("../../../../shared/api");
|
import Endpoints = require("../../../../shared/api");
|
||||||
import UserMessages = require("../../../../shared/UserMessages");
|
import UserMessages = require("../../../../shared/UserMessages");
|
||||||
import { INotifier } from "../INotifier";
|
import { INotifier } from "../INotifier";
|
||||||
|
import { RedirectionMessage } from "../../../../shared/RedirectionMessage";
|
||||||
|
import { ErrorMessage } from "../../../../shared/ErrorMessage";
|
||||||
|
|
||||||
function finishU2fAuthentication(responseData: U2fApi.SignResponse, $: JQueryStatic): BluebirdPromise<void> {
|
function finishU2fAuthentication(responseData: U2fApi.SignResponse, $: JQueryStatic): BluebirdPromise<string> {
|
||||||
return new BluebirdPromise<void>(function (resolve, reject) {
|
return new BluebirdPromise<string>(function (resolve, reject) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: Endpoints.SECOND_FACTOR_U2F_SIGN_POST,
|
url: Endpoints.SECOND_FACTOR_U2F_SIGN_POST,
|
||||||
data: responseData,
|
data: responseData,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
dataType: "json"
|
dataType: "json"
|
||||||
} as JQueryAjaxSettings)
|
} as JQueryAjaxSettings)
|
||||||
.done(function (body: any) {
|
.done(function (body: RedirectionMessage | ErrorMessage) {
|
||||||
if (body && body.error) {
|
if (body && "error" in body) {
|
||||||
reject(new Error(body.error));
|
reject(new Error((body as ErrorMessage).error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolve(body);
|
resolve((body as RedirectionMessage).redirect);
|
||||||
})
|
})
|
||||||
.fail(function (xhr: JQueryXHR, textStatus: string) {
|
.fail(function (xhr: JQueryXHR, textStatus: string) {
|
||||||
reject(new Error(textStatus));
|
reject(new Error(textStatus));
|
||||||
|
@ -28,8 +30,8 @@ function finishU2fAuthentication(responseData: U2fApi.SignResponse, $: JQuerySta
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function startU2fAuthentication($: JQueryStatic, notifier: INotifier, u2fApi: typeof U2fApi): BluebirdPromise<void> {
|
function startU2fAuthentication($: JQueryStatic, notifier: INotifier, u2fApi: typeof U2fApi): BluebirdPromise<string> {
|
||||||
return new BluebirdPromise<void>(function (resolve, reject) {
|
return new BluebirdPromise<string>(function (resolve, reject) {
|
||||||
$.get(Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, {}, undefined, "json")
|
$.get(Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, {}, undefined, "json")
|
||||||
.done(function (signResponse: SignMessage) {
|
.done(function (signResponse: SignMessage) {
|
||||||
notifier.info(UserMessages.PLEASE_TOUCH_TOKEN);
|
notifier.info(UserMessages.PLEASE_TOUCH_TOKEN);
|
||||||
|
@ -44,8 +46,8 @@ function startU2fAuthentication($: JQueryStatic, notifier: INotifier, u2fApi: ty
|
||||||
u2fApi.sign([signRequest], 60)
|
u2fApi.sign([signRequest], 60)
|
||||||
.then(function (signResponse: U2fApi.SignResponse) {
|
.then(function (signResponse: U2fApi.SignResponse) {
|
||||||
finishU2fAuthentication(signResponse, $)
|
finishU2fAuthentication(signResponse, $)
|
||||||
.then(function (data) {
|
.then(function (redirect: string) {
|
||||||
resolve(data);
|
resolve(redirect);
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
notifier.error(UserMessages.U2F_TRANSACTION_FINISH_FAILED);
|
notifier.error(UserMessages.U2F_TRANSACTION_FINISH_FAILED);
|
||||||
reject(err);
|
reject(err);
|
||||||
|
@ -62,6 +64,6 @@ function startU2fAuthentication($: JQueryStatic, notifier: INotifier, u2fApi: ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function validate($: JQueryStatic, notifier: INotifier, u2fApi: typeof U2fApi): BluebirdPromise<void> {
|
export function validate($: JQueryStatic, notifier: INotifier, u2fApi: typeof U2fApi): BluebirdPromise<string> {
|
||||||
return startU2fAuthentication($, notifier, u2fApi);
|
return startU2fAuthentication($, notifier, u2fApi);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,35 +4,37 @@ import jslogger = require("js-logger");
|
||||||
|
|
||||||
import TOTPValidator = require("./TOTPValidator");
|
import TOTPValidator = require("./TOTPValidator");
|
||||||
import U2FValidator = require("./U2FValidator");
|
import U2FValidator = require("./U2FValidator");
|
||||||
import Constants = require("./constants");
|
import ClientConstants = require("./constants");
|
||||||
import { Notifier } from "../Notifier";
|
import { Notifier } from "../Notifier";
|
||||||
import { QueryParametersRetriever } from "../QueryParametersRetriever";
|
import { QueryParametersRetriever } from "../QueryParametersRetriever";
|
||||||
import Endpoints = require("../../../../shared/api");
|
import Endpoints = require("../../../../shared/api");
|
||||||
import ServerConstants = require("../../../../shared/constants");
|
import ServerConstants = require("../../../../shared/constants");
|
||||||
import UserMessages = require("../../../../shared/UserMessages");
|
import UserMessages = require("../../../../shared/UserMessages");
|
||||||
|
import SharedConstants = require("../../../../shared/constants");
|
||||||
|
|
||||||
export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi) {
|
export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi) {
|
||||||
const notifierTotp = new Notifier(".notification-totp", $);
|
const notifierTotp = new Notifier(".notification-totp", $);
|
||||||
const notifierU2f = new Notifier(".notification-u2f", $);
|
const notifierU2f = new Notifier(".notification-u2f", $);
|
||||||
|
|
||||||
function onAuthenticationSuccess(data: any, notifier: Notifier) {
|
function onAuthenticationSuccess(serverRedirectUrl: string, notifier: Notifier) {
|
||||||
const redirectUrl = QueryParametersRetriever.get(ServerConstants.REDIRECT_QUERY_PARAM);
|
if (QueryParametersRetriever.get(SharedConstants.REDIRECT_QUERY_PARAM))
|
||||||
if (redirectUrl)
|
window.location.href = QueryParametersRetriever.get(SharedConstants.REDIRECT_QUERY_PARAM);
|
||||||
window.location.href = redirectUrl;
|
else if (serverRedirectUrl)
|
||||||
|
window.location.href = serverRedirectUrl;
|
||||||
else
|
else
|
||||||
notifier.success(UserMessages.AUTHENTICATION_SUCCEEDED);
|
notifier.success(UserMessages.AUTHENTICATION_SUCCEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSecondFactorTotpSuccess(data: any) {
|
function onSecondFactorTotpSuccess(redirectUrl: string) {
|
||||||
onAuthenticationSuccess(data, notifierTotp);
|
onAuthenticationSuccess(redirectUrl, notifierTotp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSecondFactorTotpFailure(err: Error) {
|
function onSecondFactorTotpFailure(err: Error) {
|
||||||
notifierTotp.error(UserMessages.AUTHENTICATION_TOTP_FAILED);
|
notifierTotp.error(UserMessages.AUTHENTICATION_TOTP_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onU2fAuthenticationSuccess(data: any) {
|
function onU2fAuthenticationSuccess(redirectUrl: string) {
|
||||||
onAuthenticationSuccess(data, notifierU2f);
|
onAuthenticationSuccess(redirectUrl, notifierU2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onU2fAuthenticationFailure() {
|
function onU2fAuthenticationFailure() {
|
||||||
|
@ -40,7 +42,7 @@ export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTOTPFormSubmitted(): boolean {
|
function onTOTPFormSubmitted(): boolean {
|
||||||
const token = $(Constants.TOTP_TOKEN_SELECTOR).val();
|
const token = $(ClientConstants.TOTP_TOKEN_SELECTOR).val();
|
||||||
TOTPValidator.validate(token, $)
|
TOTPValidator.validate(token, $)
|
||||||
.then(onSecondFactorTotpSuccess)
|
.then(onSecondFactorTotpSuccess)
|
||||||
.catch(onSecondFactorTotpFailure);
|
.catch(onSecondFactorTotpFailure);
|
||||||
|
@ -54,7 +56,7 @@ export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi)
|
||||||
}
|
}
|
||||||
|
|
||||||
$(window.document).ready(function () {
|
$(window.document).ready(function () {
|
||||||
$(Constants.TOTP_FORM_SELECTOR).on("submit", onTOTPFormSubmitted);
|
$(ClientConstants.TOTP_FORM_SELECTOR).on("submit", onTOTPFormSubmitted);
|
||||||
$(Constants.U2F_FORM_SELECTOR).on("submit", onU2FFormSubmitted);
|
$(ClientConstants.U2F_FORM_SELECTOR).on("submit", onU2FFormSubmitted);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -6,6 +6,8 @@ import jslogger = require("js-logger");
|
||||||
import { Notifier } from "../Notifier";
|
import { Notifier } from "../Notifier";
|
||||||
import Endpoints = require("../../../../shared/api");
|
import Endpoints = require("../../../../shared/api");
|
||||||
import UserMessages = require("../../../../shared/UserMessages");
|
import UserMessages = require("../../../../shared/UserMessages");
|
||||||
|
import { RedirectionMessage } from "../../../../shared/RedirectionMessage";
|
||||||
|
import { ErrorMessage } from "../../../../shared/ErrorMessage";
|
||||||
|
|
||||||
export default function (window: Window, $: JQueryStatic) {
|
export default function (window: Window, $: JQueryStatic) {
|
||||||
const notifier = new Notifier(".notification", $);
|
const notifier = new Notifier(".notification", $);
|
||||||
|
@ -17,12 +19,12 @@ export default function (window: Window, $: JQueryStatic) {
|
||||||
|
|
||||||
return new BluebirdPromise<string>(function (resolve, reject) {
|
return new BluebirdPromise<string>(function (resolve, reject) {
|
||||||
$.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, registrationData, undefined, "json")
|
$.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, registrationData, undefined, "json")
|
||||||
.done(function (body: any) {
|
.done(function (body: RedirectionMessage | ErrorMessage) {
|
||||||
if (body && body.error) {
|
if (body && "error" in body) {
|
||||||
reject(new Error(body.error));
|
reject(new Error((body as ErrorMessage).error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolve(body.redirection_url);
|
resolve((body as RedirectionMessage).redirect);
|
||||||
})
|
})
|
||||||
.fail(function (xhr, status) {
|
.fail(function (xhr, status) {
|
||||||
reject();
|
reject();
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Assert = require("assert");
|
||||||
describe("test TOTPValidator", function () {
|
describe("test TOTPValidator", function () {
|
||||||
it("should initiate an identity check successfully", () => {
|
it("should initiate an identity check successfully", () => {
|
||||||
const postPromise = JQueryMock.JQueryDeferredMock();
|
const postPromise = JQueryMock.JQueryDeferredMock();
|
||||||
postPromise.done.yields();
|
postPromise.done.yields({ redirect: "https://home.test.url" });
|
||||||
postPromise.done.returns(postPromise);
|
postPromise.done.returns(postPromise);
|
||||||
|
|
||||||
const jqueryMock = JQueryMock.JQueryMock();
|
const jqueryMock = JQueryMock.JQueryMock();
|
||||||
|
|
|
@ -32,7 +32,7 @@ describe("test U2F validation", function () {
|
||||||
getPromise.done.returns(getPromise);
|
getPromise.done.returns(getPromise);
|
||||||
|
|
||||||
const postPromise = JQueryMock.JQueryDeferredMock();
|
const postPromise = JQueryMock.JQueryDeferredMock();
|
||||||
postPromise.done.yields();
|
postPromise.done.yields({ redirect: "https://home.test.url" });
|
||||||
postPromise.done.returns(postPromise);
|
postPromise.done.returns(postPromise);
|
||||||
|
|
||||||
const jqueryMock = JQueryMock.JQueryMock();
|
const jqueryMock = JQueryMock.JQueryMock();
|
||||||
|
|
|
@ -10,6 +10,18 @@ port: 80
|
||||||
# Level of verbosity for logs
|
# Level of verbosity for logs
|
||||||
logs_level: debug
|
logs_level: debug
|
||||||
|
|
||||||
|
# Default redirection URL
|
||||||
|
#
|
||||||
|
# If user tries to authenticate without any referer, Authelia
|
||||||
|
# does not know where to redirect the user to at the end of the
|
||||||
|
# authentication process.
|
||||||
|
# This parameter allows you to specify the default redirection
|
||||||
|
# URL Authelia will use in such a case.
|
||||||
|
#
|
||||||
|
# Note: this parameter is optional. If not provided, user won't
|
||||||
|
# be redirected upon successful authentication.
|
||||||
|
default_redirection_url: https://home.test.local:8080/
|
||||||
|
|
||||||
# LDAP configuration
|
# LDAP configuration
|
||||||
#
|
#
|
||||||
# Example: for user john, the DN will be cn=john,ou=users,dc=example,dc=com
|
# Example: for user john, the DN will be cn=john,ou=users,dc=example,dc=com
|
||||||
|
|
|
@ -2,24 +2,9 @@
|
||||||
|
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
import U2f = require("u2f");
|
import U2f = require("u2f");
|
||||||
import { ServerVariablesHandler } from "./ServerVariablesHandler";
|
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
|
import { AuthenticationSession } from "../../types/AuthenticationSession";
|
||||||
export interface AuthenticationSession {
|
import { IRequestLogger } from "./logging/IRequestLogger";
|
||||||
userid: string;
|
|
||||||
first_factor: boolean;
|
|
||||||
second_factor: boolean;
|
|
||||||
last_activity_datetime: number;
|
|
||||||
identity_check?: {
|
|
||||||
challenge: string;
|
|
||||||
userid: string;
|
|
||||||
};
|
|
||||||
register_request?: U2f.Request;
|
|
||||||
sign_request?: U2f.Request;
|
|
||||||
email: string;
|
|
||||||
groups: string[];
|
|
||||||
redirect?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const INITIAL_AUTHENTICATION_SESSION: AuthenticationSession = {
|
const INITIAL_AUTHENTICATION_SESSION: AuthenticationSession = {
|
||||||
first_factor: false,
|
first_factor: false,
|
||||||
|
@ -35,16 +20,13 @@ const INITIAL_AUTHENTICATION_SESSION: AuthenticationSession = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function reset(req: express.Request): void {
|
export function reset(req: express.Request): void {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
|
||||||
logger.debug(req, "Authentication session %s is being reset.", req.sessionID);
|
|
||||||
req.session.auth = Object.assign({}, INITIAL_AUTHENTICATION_SESSION, {});
|
req.session.auth = Object.assign({}, INITIAL_AUTHENTICATION_SESSION, {});
|
||||||
|
|
||||||
// Initialize last activity with current time
|
// Initialize last activity with current time
|
||||||
req.session.auth.last_activity_datetime = new Date().getTime();
|
req.session.auth.last_activity_datetime = new Date().getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get(req: express.Request): BluebirdPromise<AuthenticationSession> {
|
export function get(req: express.Request, logger: IRequestLogger): BluebirdPromise<AuthenticationSession> {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
|
||||||
if (!req.session) {
|
if (!req.session) {
|
||||||
const errorMsg = "Something is wrong with session cookies. Please check Redis is running and Authelia can contact it.";
|
const errorMsg = "Something is wrong with session cookies. Please check Redis is running and Authelia can contact it.";
|
||||||
logger.error(req, errorMsg);
|
logger.error(req, errorMsg);
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
import objectPath = require("object-path");
|
import objectPath = require("object-path");
|
||||||
|
|
||||||
import FirstFactorValidator = require("./FirstFactorValidator");
|
import FirstFactorValidator = require("./FirstFactorValidator");
|
||||||
import AuthenticationSession = require("./AuthenticationSession");
|
import AuthenticationSessionHandler = require("./AuthenticationSession");
|
||||||
|
import { IRequestLogger } from "./logging/IRequestLogger";
|
||||||
|
|
||||||
export function validate(req: express.Request): BluebirdPromise<void> {
|
export function validate(req: express.Request, logger: IRequestLogger): BluebirdPromise<void> {
|
||||||
return FirstFactorValidator.validate(req)
|
return FirstFactorValidator.validate(req, logger)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return AuthenticationSession.get(req);
|
return AuthenticationSessionHandler.get(req, logger);
|
||||||
})
|
})
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
if (!authSession.second_factor)
|
if (!authSession.second_factor)
|
||||||
return BluebirdPromise.reject("No second factor variable.");
|
return BluebirdPromise.reject("No second factor variable.");
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
|
|
|
@ -3,11 +3,12 @@ import BluebirdPromise = require("bluebird");
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
import objectPath = require("object-path");
|
import objectPath = require("object-path");
|
||||||
import Exceptions = require("./Exceptions");
|
import Exceptions = require("./Exceptions");
|
||||||
import AuthenticationSession = require("./AuthenticationSession");
|
import AuthenticationSessionHandler = require("./AuthenticationSession");
|
||||||
|
import { IRequestLogger } from "./logging/IRequestLogger";
|
||||||
|
|
||||||
export function validate(req: express.Request): BluebirdPromise<void> {
|
export function validate(req: express.Request, logger: IRequestLogger): BluebirdPromise<void> {
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSessionHandler.get(req, logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
if (!authSession.userid || !authSession.first_factor)
|
if (!authSession.userid || !authSession.first_factor)
|
||||||
return BluebirdPromise.reject(
|
return BluebirdPromise.reject(
|
||||||
new Exceptions.FirstFactorValidationError(
|
new Exceptions.FirstFactorValidationError(
|
||||||
|
|
|
@ -10,8 +10,9 @@ import { IUserDataStore } from "./storage/IUserDataStore";
|
||||||
import { Winston } from "../../types/Dependencies";
|
import { Winston } from "../../types/Dependencies";
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
import ErrorReplies = require("./ErrorReplies");
|
import ErrorReplies = require("./ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "./ServerVariablesHandler";
|
import AuthenticationSessionHandler = require("./AuthenticationSession");
|
||||||
import AuthenticationSession = require("./AuthenticationSession");
|
import { AuthenticationSession } from "../../types/AuthenticationSession";
|
||||||
|
import { ServerVariables } from "./ServerVariables";
|
||||||
|
|
||||||
import Identity = require("../../types/Identity");
|
import Identity = require("../../types/Identity");
|
||||||
import { IdentityValidationDocument } from "./storage/IdentityValidationDocument";
|
import { IdentityValidationDocument } from "./storage/IdentityValidationDocument";
|
||||||
|
@ -53,9 +54,9 @@ function consumeToken(token: string, challenge: string, userDataStore: IUserData
|
||||||
}
|
}
|
||||||
|
|
||||||
export function register(app: express.Application, pre_validation_endpoint: string,
|
export function register(app: express.Application, pre_validation_endpoint: string,
|
||||||
post_validation_endpoint: string, handler: IdentityValidable) {
|
post_validation_endpoint: string, handler: IdentityValidable, vars: ServerVariables) {
|
||||||
app.get(pre_validation_endpoint, get_start_validation(handler, post_validation_endpoint));
|
app.get(pre_validation_endpoint, get_start_validation(handler, post_validation_endpoint, vars));
|
||||||
app.get(post_validation_endpoint, get_finish_validation(handler));
|
app.get(post_validation_endpoint, get_finish_validation(handler, vars));
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIdentityToken(req: express.Request, identityToken: string): BluebirdPromise<void> {
|
function checkIdentityToken(req: express.Request, identityToken: string): BluebirdPromise<void> {
|
||||||
|
@ -64,27 +65,26 @@ function checkIdentityToken(req: express.Request, identityToken: string): Bluebi
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_finish_validation(handler: IdentityValidable): express.RequestHandler {
|
export function get_finish_validation(handler: IdentityValidable,
|
||||||
|
vars: ServerVariables)
|
||||||
|
: express.RequestHandler {
|
||||||
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
let authSession: AuthenticationSession;
|
||||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
|
||||||
|
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
|
||||||
const identityToken = objectPath.get<express.Request, string>(req, "query.identity_token");
|
const identityToken = objectPath.get<express.Request, string>(req, "query.identity_token");
|
||||||
logger.debug(req, "Identity token provided is %s", identityToken);
|
vars.logger.debug(req, "Identity token provided is %s", identityToken);
|
||||||
|
|
||||||
return checkIdentityToken(req, identityToken)
|
return checkIdentityToken(req, identityToken)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return handler.postValidationInit(req);
|
return handler.postValidationInit(req);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return AuthenticationSession.get(req);
|
return AuthenticationSessionHandler.get(req, vars.logger);
|
||||||
})
|
})
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return consumeToken(identityToken, handler.challenge(), userDataStore);
|
return consumeToken(identityToken, handler.challenge(), vars.userDataStore);
|
||||||
})
|
})
|
||||||
.then(function (doc: IdentityValidationDocument) {
|
.then(function (doc: IdentityValidationDocument) {
|
||||||
authSession.identity_check = {
|
authSession.identity_check = {
|
||||||
|
@ -94,17 +94,16 @@ export function get_finish_validation(handler: IdentityValidable): express.Reque
|
||||||
handler.postValidationResponse(req, res);
|
handler.postValidationResponse(req, res);
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
})
|
})
|
||||||
.catch(ErrorReplies.replyWithError401(req, res, logger));
|
.catch(ErrorReplies.replyWithError401(req, res, vars.logger));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function get_start_validation(handler: IdentityValidable, postValidationEndpoint: string)
|
export function get_start_validation(handler: IdentityValidable,
|
||||||
|
postValidationEndpoint: string,
|
||||||
|
vars: ServerVariables)
|
||||||
: express.RequestHandler {
|
: express.RequestHandler {
|
||||||
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
|
||||||
const notifier = ServerVariablesHandler.getNotifier(req.app);
|
|
||||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
|
||||||
let identity: Identity.Identity;
|
let identity: Identity.Identity;
|
||||||
|
|
||||||
return handler.preValidationInit(req)
|
return handler.preValidationInit(req)
|
||||||
|
@ -112,25 +111,25 @@ export function get_start_validation(handler: IdentityValidable, postValidationE
|
||||||
identity = id;
|
identity = id;
|
||||||
const email = identity.email;
|
const email = identity.email;
|
||||||
const userid = identity.userid;
|
const userid = identity.userid;
|
||||||
logger.info(req, "Start identity validation of user \"%s\"", userid);
|
vars.logger.info(req, "Start identity validation of user \"%s\"", userid);
|
||||||
|
|
||||||
if (!(email && userid))
|
if (!(email && userid))
|
||||||
return BluebirdPromise.reject(new Exceptions.IdentityError(
|
return BluebirdPromise.reject(new Exceptions.IdentityError(
|
||||||
"Missing user id or email address"));
|
"Missing user id or email address"));
|
||||||
|
|
||||||
return createAndSaveToken(userid, handler.challenge(), userDataStore);
|
return createAndSaveToken(userid, handler.challenge(), vars.userDataStore);
|
||||||
})
|
})
|
||||||
.then(function (token: string) {
|
.then(function (token: string) {
|
||||||
const host = req.get("Host");
|
const host = req.get("Host");
|
||||||
const link_url = util.format("https://%s%s?identity_token=%s", host,
|
const link_url = util.format("https://%s%s?identity_token=%s", host,
|
||||||
postValidationEndpoint, token);
|
postValidationEndpoint, token);
|
||||||
logger.info(req, "Notification sent to user \"%s\"", identity.userid);
|
vars.logger.info(req, "Notification sent to user \"%s\"", identity.userid);
|
||||||
return notifier.notify(identity.email, handler.mailSubject(), link_url);
|
return vars.notifier.notify(identity.email, handler.mailSubject(), link_url);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
handler.preValidationResponse(req, res);
|
handler.preValidationResponse(req, res);
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
})
|
})
|
||||||
.catch(ErrorReplies.replyWithError401(req, res, logger));
|
.catch(ErrorReplies.replyWithError401(req, res, vars.logger));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,14 +32,14 @@ import Error404Get = require("./routes/error/404/get");
|
||||||
|
|
||||||
import LoggedIn = require("./routes/loggedin/get");
|
import LoggedIn = require("./routes/loggedin/get");
|
||||||
|
|
||||||
import { ServerVariablesHandler } from "./ServerVariablesHandler";
|
|
||||||
import { ServerVariables } from "./ServerVariables";
|
import { ServerVariables } from "./ServerVariables";
|
||||||
|
import { IRequestLogger } from "./logging/IRequestLogger";
|
||||||
|
|
||||||
import Endpoints = require("../../../shared/api");
|
import Endpoints = require("../../../shared/api");
|
||||||
|
|
||||||
function withLog(fn: (req: Express.Request, res: Express.Response) => void) {
|
function withHeadersLogged(fn: (req: Express.Request, res: Express.Response) => void,
|
||||||
return function(req: Express.Request, res: Express.Response) {
|
logger: IRequestLogger) {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
return function (req: Express.Request, res: Express.Response) {
|
||||||
logger.debug(req, "Headers = %s", JSON.stringify(req.headers));
|
logger.debug(req, "Headers = %s", JSON.stringify(req.headers));
|
||||||
fn(req, res);
|
fn(req, res);
|
||||||
};
|
};
|
||||||
|
@ -47,35 +47,38 @@ function withLog(fn: (req: Express.Request, res: Express.Response) => void) {
|
||||||
|
|
||||||
export class RestApi {
|
export class RestApi {
|
||||||
static setup(app: Express.Application, vars: ServerVariables): void {
|
static setup(app: Express.Application, vars: ServerVariables): void {
|
||||||
app.get(Endpoints.FIRST_FACTOR_GET, withLog(FirstFactorGet.default));
|
app.get(Endpoints.FIRST_FACTOR_GET, withHeadersLogged(FirstFactorGet.default(vars), vars.logger));
|
||||||
app.get(Endpoints.SECOND_FACTOR_GET, withLog(SecondFactorGet.default));
|
app.get(Endpoints.SECOND_FACTOR_GET, withHeadersLogged(SecondFactorGet.default(vars), vars.logger));
|
||||||
app.get(Endpoints.LOGOUT_GET, withLog(LogoutGet.default));
|
app.get(Endpoints.LOGOUT_GET, withHeadersLogged(LogoutGet.default, vars.logger));
|
||||||
|
|
||||||
IdentityCheckMiddleware.register(app, Endpoints.SECOND_FACTOR_TOTP_IDENTITY_START_GET,
|
IdentityCheckMiddleware.register(app, Endpoints.SECOND_FACTOR_TOTP_IDENTITY_START_GET,
|
||||||
Endpoints.SECOND_FACTOR_TOTP_IDENTITY_FINISH_GET, new TOTPRegistrationIdentityHandler());
|
Endpoints.SECOND_FACTOR_TOTP_IDENTITY_FINISH_GET,
|
||||||
|
new TOTPRegistrationIdentityHandler(vars.logger, vars.userDataStore, vars.totpHandler), vars);
|
||||||
|
|
||||||
IdentityCheckMiddleware.register(app, Endpoints.SECOND_FACTOR_U2F_IDENTITY_START_GET,
|
IdentityCheckMiddleware.register(app, Endpoints.SECOND_FACTOR_U2F_IDENTITY_START_GET,
|
||||||
Endpoints.SECOND_FACTOR_U2F_IDENTITY_FINISH_GET, new U2FRegistrationIdentityHandler());
|
Endpoints.SECOND_FACTOR_U2F_IDENTITY_FINISH_GET,
|
||||||
|
new U2FRegistrationIdentityHandler(vars.logger), vars);
|
||||||
|
|
||||||
IdentityCheckMiddleware.register(app, Endpoints.RESET_PASSWORD_IDENTITY_START_GET,
|
IdentityCheckMiddleware.register(app, Endpoints.RESET_PASSWORD_IDENTITY_START_GET,
|
||||||
Endpoints.RESET_PASSWORD_IDENTITY_FINISH_GET, new ResetPasswordIdentityHandler());
|
Endpoints.RESET_PASSWORD_IDENTITY_FINISH_GET,
|
||||||
|
new ResetPasswordIdentityHandler(vars.logger, vars.ldapEmailsRetriever), vars);
|
||||||
|
|
||||||
app.get(Endpoints.RESET_PASSWORD_REQUEST_GET, withLog(ResetPasswordRequestPost.default));
|
app.get(Endpoints.RESET_PASSWORD_REQUEST_GET, withHeadersLogged(ResetPasswordRequestPost.default, vars.logger));
|
||||||
app.post(Endpoints.RESET_PASSWORD_FORM_POST, withLog(ResetPasswordFormPost.default));
|
app.post(Endpoints.RESET_PASSWORD_FORM_POST, withHeadersLogged(ResetPasswordFormPost.default(vars), vars.logger));
|
||||||
|
|
||||||
app.get(Endpoints.VERIFY_GET, withLog(VerifyGet.default(vars)));
|
app.get(Endpoints.VERIFY_GET, withHeadersLogged(VerifyGet.default(vars), vars.logger));
|
||||||
app.post(Endpoints.FIRST_FACTOR_POST, withLog(FirstFactorPost.default(vars)));
|
app.post(Endpoints.FIRST_FACTOR_POST, withHeadersLogged(FirstFactorPost.default(vars), vars.logger));
|
||||||
app.post(Endpoints.SECOND_FACTOR_TOTP_POST, withLog(TOTPSignGet.default(vars)));
|
app.post(Endpoints.SECOND_FACTOR_TOTP_POST, withHeadersLogged(TOTPSignGet.default(vars), vars.logger));
|
||||||
|
|
||||||
app.get(Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, withLog(U2FSignRequestGet.default));
|
app.get(Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, withHeadersLogged(U2FSignRequestGet.default(vars), vars.logger));
|
||||||
app.post(Endpoints.SECOND_FACTOR_U2F_SIGN_POST, withLog(U2FSignPost.default));
|
app.post(Endpoints.SECOND_FACTOR_U2F_SIGN_POST, withHeadersLogged(U2FSignPost.default(vars), vars.logger));
|
||||||
|
|
||||||
app.get(Endpoints.SECOND_FACTOR_U2F_REGISTER_REQUEST_GET, withLog(U2FRegisterRequestGet.default));
|
app.get(Endpoints.SECOND_FACTOR_U2F_REGISTER_REQUEST_GET, withHeadersLogged(U2FRegisterRequestGet.default(vars), vars.logger));
|
||||||
app.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, withLog(U2FRegisterPost.default));
|
app.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, withHeadersLogged(U2FRegisterPost.default(vars), vars.logger));
|
||||||
|
|
||||||
app.get(Endpoints.ERROR_401_GET, withLog(Error401Get.default));
|
app.get(Endpoints.ERROR_401_GET, withHeadersLogged(Error401Get.default, vars.logger));
|
||||||
app.get(Endpoints.ERROR_403_GET, withLog(Error403Get.default));
|
app.get(Endpoints.ERROR_403_GET, withHeadersLogged(Error403Get.default, vars.logger));
|
||||||
app.get(Endpoints.ERROR_404_GET, withLog(Error404Get.default));
|
app.get(Endpoints.ERROR_404_GET, withHeadersLogged(Error404Get.default, vars.logger));
|
||||||
app.get(Endpoints.LOGGED_IN, withLog(LoggedIn.default));
|
app.get(Endpoints.LOGGED_IN, withHeadersLogged(LoggedIn.default(vars), vars.logger));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ import { GlobalDependencies } from "../../types/Dependencies";
|
||||||
import { UserDataStore } from "./storage/UserDataStore";
|
import { UserDataStore } from "./storage/UserDataStore";
|
||||||
import { ConfigurationParser } from "./configuration/ConfigurationParser";
|
import { ConfigurationParser } from "./configuration/ConfigurationParser";
|
||||||
import { RestApi } from "./RestApi";
|
import { RestApi } from "./RestApi";
|
||||||
import { ServerVariablesHandler, ServerVariablesInitializer } from "./ServerVariablesHandler";
|
|
||||||
import { SessionConfigurationBuilder } from "./configuration/SessionConfigurationBuilder";
|
import { SessionConfigurationBuilder } from "./configuration/SessionConfigurationBuilder";
|
||||||
import { GlobalLogger } from "./logging/GlobalLogger";
|
import { GlobalLogger } from "./logging/GlobalLogger";
|
||||||
import { RequestLogger } from "./logging/RequestLogger";
|
import { RequestLogger } from "./logging/RequestLogger";
|
||||||
import { ServerVariables } from "./ServerVariables";
|
import { ServerVariables } from "./ServerVariables";
|
||||||
|
import { ServerVariablesInitializer } from "./ServerVariablesInitializer";
|
||||||
|
|
||||||
import * as Express from "express";
|
import * as Express from "express";
|
||||||
import * as BodyParser from "body-parser";
|
import * as BodyParser from "body-parser";
|
||||||
|
@ -96,7 +96,6 @@ export default class Server {
|
||||||
.then(function (vars: ServerVariables) {
|
.then(function (vars: ServerVariables) {
|
||||||
that.serverVariables = vars;
|
that.serverVariables = vars;
|
||||||
that.setupExpressApplication(config, app, deps);
|
that.setupExpressApplication(config, app, deps);
|
||||||
ServerVariablesHandler.setup(app, vars);
|
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,6 @@ import { GlobalDependencies } from "../../types/Dependencies";
|
||||||
import { ServerVariables } from "./ServerVariables";
|
import { ServerVariables } from "./ServerVariables";
|
||||||
import { AuthenticationMethodCalculator } from "./AuthenticationMethodCalculator";
|
import { AuthenticationMethodCalculator } from "./AuthenticationMethodCalculator";
|
||||||
|
|
||||||
|
|
||||||
import express = require("express");
|
|
||||||
|
|
||||||
export const VARIABLES_KEY = "authelia-variables";
|
|
||||||
|
|
||||||
class UserDataStoreFactory {
|
class UserDataStoreFactory {
|
||||||
static create(config: Configuration.AppConfiguration): BluebirdPromise<UserDataStore> {
|
static create(config: Configuration.AppConfiguration): BluebirdPromise<UserDataStore> {
|
||||||
if (config.storage.local) {
|
if (config.storage.local) {
|
||||||
|
@ -104,53 +99,3 @@ export class ServerVariablesInitializer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ServerVariablesHandler {
|
|
||||||
static setup(app: express.Application, variables: ServerVariables): void {
|
|
||||||
app.set(VARIABLES_KEY, variables);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getLogger(app: express.Application): IRequestLogger {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getUserDataStore(app: express.Application): IUserDataStore {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).userDataStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getNotifier(app: express.Application): INotifier {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).notifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getLdapAuthenticator(app: express.Application): IAuthenticator {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).ldapAuthenticator;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getLdapPasswordUpdater(app: express.Application): IPasswordUpdater {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).ldapPasswordUpdater;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getLdapEmailsRetriever(app: express.Application): IEmailsRetriever {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).ldapEmailsRetriever;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getConfiguration(app: express.Application): Configuration.AppConfiguration {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).config;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getAuthenticationRegulator(app: express.Application): IRegulator {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).regulator;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getAccessController(app: express.Application): IAccessController {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).accessController;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTotpHandler(app: express.Application): ITotpHandler {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).totpHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getU2F(app: express.Application): typeof U2F {
|
|
||||||
return (app.get(VARIABLES_KEY) as ServerVariables).u2f;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -131,6 +131,7 @@ export interface UserConfiguration {
|
||||||
authentication_methods?: AuthenticationMethodsConfiguration;
|
authentication_methods?: AuthenticationMethodsConfiguration;
|
||||||
access_control?: ACLConfiguration;
|
access_control?: ACLConfiguration;
|
||||||
regulation: RegulationConfiguration;
|
regulation: RegulationConfiguration;
|
||||||
|
default_redirection_url?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AppConfiguration {
|
export interface AppConfiguration {
|
||||||
|
@ -143,4 +144,5 @@ export interface AppConfiguration {
|
||||||
authentication_methods: AuthenticationMethodsConfiguration;
|
authentication_methods: AuthenticationMethodsConfiguration;
|
||||||
access_control?: ACLConfiguration;
|
access_control?: ACLConfiguration;
|
||||||
regulation: RegulationConfiguration;
|
regulation: RegulationConfiguration;
|
||||||
|
default_redirection_url?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,8 @@ function adaptFromUserConfiguration(userConfiguration: UserConfiguration)
|
||||||
notifier: ObjectPath.get<object, NotifierConfiguration>(userConfiguration, "notifier"),
|
notifier: ObjectPath.get<object, NotifierConfiguration>(userConfiguration, "notifier"),
|
||||||
access_control: ACLAdapter.adapt(userConfiguration.access_control),
|
access_control: ACLAdapter.adapt(userConfiguration.access_control),
|
||||||
regulation: userConfiguration.regulation,
|
regulation: userConfiguration.regulation,
|
||||||
authentication_methods: authenticationMethods
|
authentication_methods: authenticationMethods,
|
||||||
|
default_redirection_url: userConfiguration.default_redirection_url
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,19 +5,17 @@ import FirstFactorValidator = require("../FirstFactorValidator");
|
||||||
import Exceptions = require("../Exceptions");
|
import Exceptions = require("../Exceptions");
|
||||||
import ErrorReplies = require("../ErrorReplies");
|
import ErrorReplies = require("../ErrorReplies");
|
||||||
import objectPath = require("object-path");
|
import objectPath = require("object-path");
|
||||||
import { ServerVariablesHandler } from "../ServerVariablesHandler";
|
|
||||||
import AuthenticationSession = require("../AuthenticationSession");
|
import AuthenticationSession = require("../AuthenticationSession");
|
||||||
import UserMessages = require("../../../../shared/UserMessages");
|
import UserMessages = require("../../../../shared/UserMessages");
|
||||||
|
import { IRequestLogger } from "../logging/IRequestLogger";
|
||||||
|
|
||||||
type Handler = (req: express.Request, res: express.Response) => BluebirdPromise<void>;
|
type Handler = (req: express.Request, res: express.Response) => BluebirdPromise<void>;
|
||||||
|
|
||||||
export default function (callback: Handler): Handler {
|
export default function (callback: Handler, logger: IRequestLogger): Handler {
|
||||||
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
return AuthenticationSession.get(req, logger)
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
return FirstFactorValidator.validate(req);
|
return FirstFactorValidator.validate(req, logger);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return callback(req, res);
|
return callback(req, res);
|
||||||
|
|
|
@ -4,11 +4,11 @@ import objectPath = require("object-path");
|
||||||
import winston = require("winston");
|
import winston = require("winston");
|
||||||
import Endpoints = require("../../../../../shared/api");
|
import Endpoints = require("../../../../../shared/api");
|
||||||
import AuthenticationValidator = require("../../AuthenticationValidator");
|
import AuthenticationValidator = require("../../AuthenticationValidator");
|
||||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import AuthenticationSession = require("../../AuthenticationSession");
|
import AuthenticationSession = require("../../AuthenticationSession");
|
||||||
import Constants = require("../../../../../shared/constants");
|
import Constants = require("../../../../../shared/constants");
|
||||||
import Util = require("util");
|
import Util = require("util");
|
||||||
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
|
|
||||||
function getRedirectParam(req: express.Request) {
|
function getRedirectParam(req: express.Request) {
|
||||||
return req.query[Constants.REDIRECT_QUERY_PARAM] != "undefined"
|
return req.query[Constants.REDIRECT_QUERY_PARAM] != "undefined"
|
||||||
|
@ -40,18 +40,20 @@ function renderFirstFactor(res: express.Response) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
export default function (vars: ServerVariables) {
|
||||||
return AuthenticationSession.get(req)
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
.then(function (authSession) {
|
return AuthenticationSession.get(req, vars.logger)
|
||||||
if (authSession.first_factor) {
|
.then(function (authSession) {
|
||||||
if (authSession.second_factor)
|
if (authSession.first_factor) {
|
||||||
redirectToService(req, res);
|
if (authSession.second_factor)
|
||||||
else
|
redirectToService(req, res);
|
||||||
redirectToSecondFactorPage(req, res);
|
else
|
||||||
return BluebirdPromise.resolve();
|
redirectToSecondFactorPage(req, res);
|
||||||
}
|
return BluebirdPromise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
renderFirstFactor(res);
|
renderFirstFactor(res);
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
});
|
});
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -8,20 +8,20 @@ import { Regulator } from "../../regulation/Regulator";
|
||||||
import { GroupsAndEmails } from "../../ldap/IClient";
|
import { GroupsAndEmails } from "../../ldap/IClient";
|
||||||
import Endpoint = require("../../../../../shared/api");
|
import Endpoint = require("../../../../../shared/api");
|
||||||
import ErrorReplies = require("../../ErrorReplies");
|
import ErrorReplies = require("../../ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
import AuthenticationSessionHandler = require("../../AuthenticationSession");
|
||||||
import AuthenticationSession = require("../../AuthenticationSession");
|
|
||||||
import Constants = require("../../../../../shared/constants");
|
import Constants = require("../../../../../shared/constants");
|
||||||
import { DomainExtractor } from "../../utils/DomainExtractor";
|
import { DomainExtractor } from "../../utils/DomainExtractor";
|
||||||
import UserMessages = require("../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../shared/UserMessages");
|
||||||
import { AuthenticationMethodCalculator } from "../../AuthenticationMethodCalculator";
|
import { AuthenticationMethodCalculator } from "../../AuthenticationMethodCalculator";
|
||||||
import { ServerVariables } from "../../ServerVariables";
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
|
import { AuthenticationSession } from "../../../../types/AuthenticationSession";
|
||||||
|
|
||||||
export default function (vars: ServerVariables) {
|
export default function (vars: ServerVariables) {
|
||||||
return function (req: express.Request, res: express.Response)
|
return function (req: express.Request, res: express.Response)
|
||||||
: BluebirdPromise<void> {
|
: BluebirdPromise<void> {
|
||||||
const username: string = req.body.username;
|
const username: string = req.body.username;
|
||||||
const password: string = req.body.password;
|
const password: string = req.body.password;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let authSession: AuthenticationSession;
|
||||||
|
|
||||||
return BluebirdPromise.resolve()
|
return BluebirdPromise.resolve()
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
@ -29,9 +29,9 @@ export default function (vars: ServerVariables) {
|
||||||
return BluebirdPromise.reject(new Error("No username or password."));
|
return BluebirdPromise.reject(new Error("No username or password."));
|
||||||
}
|
}
|
||||||
vars.logger.info(req, "Starting authentication of user \"%s\"", username);
|
vars.logger.info(req, "Starting authentication of user \"%s\"", username);
|
||||||
return AuthenticationSession.get(req);
|
return AuthenticationSessionHandler.get(req, vars.logger);
|
||||||
})
|
})
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
return vars.regulator.regulate(username);
|
return vars.regulator.regulate(username);
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,16 +2,20 @@ import Express = require("express");
|
||||||
import Endpoints = require("../../../../../shared/api");
|
import Endpoints = require("../../../../../shared/api");
|
||||||
import FirstFactorBlocker from "../FirstFactorBlocker";
|
import FirstFactorBlocker from "../FirstFactorBlocker";
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import AuthenticationSession = require("../../AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../AuthenticationSession");
|
||||||
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
|
|
||||||
export default FirstFactorBlocker(handler);
|
export default function (vars: ServerVariables) {
|
||||||
|
function handler(req: Express.Request, res: Express.Response): BluebirdPromise<void> {
|
||||||
function handler(req: Express.Request, res: Express.Response): BluebirdPromise<void> {
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
return AuthenticationSession.get(req)
|
.then(function (authSession) {
|
||||||
.then(function (authSession) {
|
res.render("already-logged-in", {
|
||||||
res.render("already-logged-in", {
|
logout_endpoint: Endpoints.LOGOUT_GET,
|
||||||
logout_endpoint: Endpoints.LOGOUT_GET,
|
username: authSession.userid,
|
||||||
username: authSession.userid
|
redirection_url: vars.config.default_redirection_url
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
return FirstFactorBlocker(handler, vars.logger);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,38 +3,40 @@ import express = require("express");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import objectPath = require("object-path");
|
import objectPath = require("object-path");
|
||||||
import exceptions = require("../../../Exceptions");
|
import exceptions = require("../../../Exceptions");
|
||||||
import { ServerVariablesHandler } from "../../../ServerVariablesHandler";
|
import AuthenticationSessionHandler = require("../../../AuthenticationSession");
|
||||||
import AuthenticationSession = require("../../../AuthenticationSession");
|
import { AuthenticationSession } from "../../../../../types/AuthenticationSession";
|
||||||
import ErrorReplies = require("../../../ErrorReplies");
|
import ErrorReplies = require("../../../ErrorReplies");
|
||||||
import UserMessages = require("../../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../../shared/UserMessages");
|
||||||
|
import { ServerVariables } from "../../../ServerVariables";
|
||||||
|
|
||||||
import Constants = require("./../constants");
|
import Constants = require("./../constants");
|
||||||
|
|
||||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
export default function (vars: ServerVariables) {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
const ldapPasswordUpdater = ServerVariablesHandler.getLdapPasswordUpdater(req.app);
|
let authSession: AuthenticationSession;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
const newPassword = objectPath.get<express.Request, string>(req, "body.password");
|
||||||
const newPassword = objectPath.get<express.Request, string>(req, "body.password");
|
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
.then(function (_authSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
logger.info(req, "User %s wants to reset his/her password.",
|
vars.logger.info(req, "User %s wants to reset his/her password.",
|
||||||
authSession.identity_check.userid);
|
authSession.identity_check.userid);
|
||||||
logger.debug(req, "Challenge %s", authSession.identity_check.challenge);
|
vars.logger.debug(req, "Challenge %s", authSession.identity_check.challenge);
|
||||||
|
|
||||||
if (authSession.identity_check.challenge != Constants.CHALLENGE) {
|
if (authSession.identity_check.challenge != Constants.CHALLENGE) {
|
||||||
return BluebirdPromise.reject(new Error("Bad challenge."));
|
return BluebirdPromise.reject(new Error("Bad challenge."));
|
||||||
}
|
}
|
||||||
return ldapPasswordUpdater.updatePassword(authSession.identity_check.userid, newPassword);
|
return vars.ldapPasswordUpdater.updatePassword(authSession.identity_check.userid, newPassword);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
logger.info(req, "Password reset for user '%s'",
|
vars.logger.info(req, "Password reset for user '%s'",
|
||||||
authSession.identity_check.userid);
|
authSession.identity_check.userid);
|
||||||
AuthenticationSession.reset(req);
|
AuthenticationSessionHandler.reset(req);
|
||||||
res.status(204);
|
res.status(204);
|
||||||
res.send();
|
res.send();
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
})
|
})
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, logger, UserMessages.RESET_PASSWORD_FAILED));
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
||||||
|
UserMessages.RESET_PASSWORD_FAILED));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,49 +7,55 @@ import { Identity } from "../../../../../types/Identity";
|
||||||
import { IdentityValidable } from "../../../IdentityCheckMiddleware";
|
import { IdentityValidable } from "../../../IdentityCheckMiddleware";
|
||||||
import { PRE_VALIDATION_TEMPLATE } from "../../../IdentityCheckPreValidationTemplate";
|
import { PRE_VALIDATION_TEMPLATE } from "../../../IdentityCheckPreValidationTemplate";
|
||||||
import Constants = require("../constants");
|
import Constants = require("../constants");
|
||||||
import { Winston } from "winston";
|
import { IRequestLogger } from "../../../logging/IRequestLogger";
|
||||||
import { ServerVariablesHandler } from "../../../ServerVariablesHandler";
|
import { IEmailsRetriever } from "../../../ldap/IEmailsRetriever";
|
||||||
|
|
||||||
export const TEMPLATE_NAME = "password-reset-form";
|
export const TEMPLATE_NAME = "password-reset-form";
|
||||||
|
|
||||||
export default class PasswordResetHandler implements IdentityValidable {
|
export default class PasswordResetHandler implements IdentityValidable {
|
||||||
challenge(): string {
|
private logger: IRequestLogger;
|
||||||
return Constants.CHALLENGE;
|
private emailsRetriever: IEmailsRetriever;
|
||||||
}
|
|
||||||
|
|
||||||
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
constructor(logger: IRequestLogger, emailsRetriever: IEmailsRetriever) {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
this.logger = logger;
|
||||||
const userid: string = objectPath.get<express.Request, string>(req, "query.userid");
|
this.emailsRetriever = emailsRetriever;
|
||||||
|
}
|
||||||
|
|
||||||
logger.debug(req, "User '%s' requested a password reset", userid);
|
challenge(): string {
|
||||||
if (!userid)
|
return Constants.CHALLENGE;
|
||||||
return BluebirdPromise.reject(new exceptions.AccessDeniedError("No user id provided"));
|
}
|
||||||
|
|
||||||
const emailsRetriever = ServerVariablesHandler.getLdapEmailsRetriever(req.app);
|
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
||||||
return emailsRetriever.retrieve(userid)
|
const userid: string = objectPath.get<express.Request, string>(req, "query.userid");
|
||||||
.then(function (emails: string[]) {
|
|
||||||
if (!emails && emails.length <= 0) throw new Error("No email found");
|
|
||||||
const identity = {
|
|
||||||
email: emails[0],
|
|
||||||
userid: userid
|
|
||||||
};
|
|
||||||
return BluebirdPromise.resolve(identity);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
preValidationResponse(req: express.Request, res: express.Response) {
|
this.logger.debug(req, "User '%s' requested a password reset", userid);
|
||||||
res.render(PRE_VALIDATION_TEMPLATE);
|
if (!userid)
|
||||||
}
|
return BluebirdPromise.reject(new exceptions.AccessDeniedError("No user id provided"));
|
||||||
|
|
||||||
postValidationInit(req: express.Request) {
|
return this.emailsRetriever.retrieve(userid)
|
||||||
return BluebirdPromise.resolve();
|
.then(function (emails: string[]) {
|
||||||
}
|
if (!emails && emails.length <= 0) throw new Error("No email found");
|
||||||
|
const identity = {
|
||||||
|
email: emails[0],
|
||||||
|
userid: userid
|
||||||
|
};
|
||||||
|
return BluebirdPromise.resolve(identity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
postValidationResponse(req: express.Request, res: express.Response) {
|
preValidationResponse(req: express.Request, res: express.Response) {
|
||||||
res.render(TEMPLATE_NAME);
|
res.render(PRE_VALIDATION_TEMPLATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mailSubject(): string {
|
postValidationInit(req: express.Request) {
|
||||||
return "Reset your password";
|
return BluebirdPromise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postValidationResponse(req: express.Request, res: express.Response) {
|
||||||
|
res.render(TEMPLATE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
mailSubject(): string {
|
||||||
|
return "Reset your password";
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,26 +3,28 @@ import Express = require("express");
|
||||||
import Endpoints = require("../../../../../shared/api");
|
import Endpoints = require("../../../../../shared/api");
|
||||||
import FirstFactorBlocker = require("../FirstFactorBlocker");
|
import FirstFactorBlocker = require("../FirstFactorBlocker");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
import AuthenticationSessionHandler = require("../../AuthenticationSession");
|
||||||
import AuthenticationSession = require("../../AuthenticationSession");
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
|
|
||||||
const TEMPLATE_NAME = "secondfactor";
|
const TEMPLATE_NAME = "secondfactor";
|
||||||
|
|
||||||
export default FirstFactorBlocker.default(handler);
|
export default function (vars: ServerVariables) {
|
||||||
|
function handler(req: Express.Request, res: Express.Response): BluebirdPromise<void> {
|
||||||
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
|
.then(function (authSession) {
|
||||||
|
if (authSession.first_factor && authSession.second_factor) {
|
||||||
|
res.redirect(Endpoints.LOGGED_IN);
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
function handler(req: Express.Request, res: Express.Response): BluebirdPromise<void> {
|
res.render(TEMPLATE_NAME, {
|
||||||
return AuthenticationSession.get(req)
|
username: authSession.userid,
|
||||||
.then(function (authSession) {
|
totp_identity_start_endpoint: Endpoints.SECOND_FACTOR_TOTP_IDENTITY_START_GET,
|
||||||
if (authSession.first_factor && authSession.second_factor) {
|
u2f_identity_start_endpoint: Endpoints.SECOND_FACTOR_U2F_IDENTITY_START_GET
|
||||||
res.redirect(Endpoints.LOGGED_IN);
|
|
||||||
return BluebirdPromise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
res.render(TEMPLATE_NAME, {
|
|
||||||
username: authSession.userid,
|
|
||||||
totp_identity_start_endpoint: Endpoints.SECOND_FACTOR_TOTP_IDENTITY_START_GET,
|
|
||||||
u2f_identity_start_endpoint: Endpoints.SECOND_FACTOR_U2F_IDENTITY_START_GET
|
|
||||||
});
|
|
||||||
return BluebirdPromise.resolve();
|
|
||||||
});
|
});
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return FirstFactorBlocker.default(handler, vars.logger);
|
||||||
}
|
}
|
|
@ -3,22 +3,29 @@ import express = require("express");
|
||||||
import objectPath = require("object-path");
|
import objectPath = require("object-path");
|
||||||
import winston = require("winston");
|
import winston = require("winston");
|
||||||
import Endpoints = require("../../../../../shared/api");
|
import Endpoints = require("../../../../../shared/api");
|
||||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
import AuthenticationSession = require("../../AuthenticationSession");
|
import AuthenticationSession = require("../../AuthenticationSession");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import ErrorReplies = require("../../ErrorReplies");
|
import ErrorReplies = require("../../ErrorReplies");
|
||||||
import UserMessages = require("../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../shared/UserMessages");
|
||||||
|
import { RedirectionMessage } from "../../../../../shared/RedirectionMessage";
|
||||||
|
import Constants = require("../../../../../shared/constants");
|
||||||
|
|
||||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
export default function (vars: ServerVariables) {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSession.get(req, vars.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
const redirectUrl = req.query.redirect || Endpoints.FIRST_FACTOR_GET;
|
let redirectUrl: string;
|
||||||
res.json({
|
if (vars.config.default_redirection_url) {
|
||||||
redirection_url: redirectUrl
|
redirectUrl = vars.config.default_redirection_url;
|
||||||
});
|
}
|
||||||
return BluebirdPromise.resolve();
|
vars.logger.debug(req, "Request redirection to \"%s\".", redirectUrl);
|
||||||
})
|
res.json({
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, logger,
|
redirect: redirectUrl
|
||||||
UserMessages.OPERATION_FAILED));
|
} as RedirectionMessage);
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
})
|
||||||
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
||||||
|
UserMessages.OPERATION_FAILED));
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -9,21 +9,34 @@ import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationT
|
||||||
import Constants = require("../constants");
|
import Constants = require("../constants");
|
||||||
import Endpoints = require("../../../../../../../shared/api");
|
import Endpoints = require("../../../../../../../shared/api");
|
||||||
import ErrorReplies = require("../../../../ErrorReplies");
|
import ErrorReplies = require("../../../../ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
|
||||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
import AuthenticationSession = require("../../../../AuthenticationSession");
|
||||||
import UserMessages = require("../../../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../../../shared/UserMessages");
|
||||||
|
|
||||||
import FirstFactorValidator = require("../../../../FirstFactorValidator");
|
import FirstFactorValidator = require("../../../../FirstFactorValidator");
|
||||||
|
import { IRequestLogger } from "../../../../logging/IRequestLogger";
|
||||||
|
import { IUserDataStore } from "../../../../storage/IUserDataStore";
|
||||||
|
import { ITotpHandler } from "../../../../authentication/totp/ITotpHandler";
|
||||||
|
|
||||||
|
|
||||||
export default class RegistrationHandler implements IdentityValidable {
|
export default class RegistrationHandler implements IdentityValidable {
|
||||||
|
private logger: IRequestLogger;
|
||||||
|
private userDataStore: IUserDataStore;
|
||||||
|
private totp: ITotpHandler;
|
||||||
|
|
||||||
|
constructor(logger: IRequestLogger,
|
||||||
|
userDataStore: IUserDataStore,
|
||||||
|
totp: ITotpHandler) {
|
||||||
|
this.logger = logger;
|
||||||
|
this.userDataStore = userDataStore;
|
||||||
|
this.totp = totp;
|
||||||
|
}
|
||||||
|
|
||||||
challenge(): string {
|
challenge(): string {
|
||||||
return Constants.CHALLENGE;
|
return Constants.CHALLENGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private retrieveIdentity(req: express.Request): BluebirdPromise<Identity> {
|
private retrieveIdentity(req: express.Request): BluebirdPromise<Identity> {
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSession.get(req, this.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
const userid = authSession.userid;
|
const userid = authSession.userid;
|
||||||
const email = authSession.email;
|
const email = authSession.email;
|
||||||
|
|
||||||
|
@ -41,7 +54,7 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
|
|
||||||
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
||||||
const that = this;
|
const that = this;
|
||||||
return FirstFactorValidator.validate(req)
|
return FirstFactorValidator.validate(req, this.logger)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return that.retrieveIdentity(req);
|
return that.retrieveIdentity(req);
|
||||||
});
|
});
|
||||||
|
@ -52,26 +65,22 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationInit(req: express.Request) {
|
postValidationInit(req: express.Request) {
|
||||||
return FirstFactorValidator.validate(req);
|
return FirstFactorValidator.validate(req, this.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationResponse(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
postValidationResponse(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
const that = this;
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSession.get(req, this.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
const userid = authSession.identity_check.userid;
|
const userid = authSession.identity_check.userid;
|
||||||
const challenge = authSession.identity_check.challenge;
|
const challenge = authSession.identity_check.challenge;
|
||||||
|
|
||||||
if (challenge != Constants.CHALLENGE || !userid) {
|
if (challenge != Constants.CHALLENGE || !userid) {
|
||||||
return BluebirdPromise.reject(new Error("Bad challenge."));
|
return BluebirdPromise.reject(new Error("Bad challenge."));
|
||||||
}
|
}
|
||||||
|
const secret = that.totp.generate();
|
||||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
that.logger.debug(req, "Save the TOTP secret in DB");
|
||||||
const totpHandler = ServerVariablesHandler.getTotpHandler(req.app);
|
return that.userDataStore.saveTOTPSecret(userid, secret)
|
||||||
const secret = totpHandler.generate();
|
|
||||||
|
|
||||||
logger.debug(req, "Save the TOTP secret in DB");
|
|
||||||
return userDataStore.saveTOTPSecret(userid, secret)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
AuthenticationSession.reset(req);
|
AuthenticationSession.reset(req);
|
||||||
|
|
||||||
|
@ -82,7 +91,7 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, logger, UserMessages.OPERATION_FAILED));
|
.catch(ErrorReplies.replyWithError200(req, res, that.logger, UserMessages.OPERATION_FAILED));
|
||||||
}
|
}
|
||||||
|
|
||||||
mailSubject(): string {
|
mailSubject(): string {
|
||||||
|
|
|
@ -8,8 +8,8 @@ import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||||
import Endpoints = require("../../../../../../../shared/api");
|
import Endpoints = require("../../../../../../../shared/api");
|
||||||
import redirect from "../../redirect";
|
import redirect from "../../redirect";
|
||||||
import ErrorReplies = require("../../../../ErrorReplies");
|
import ErrorReplies = require("../../../../ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "./../../../../ServerVariablesHandler";
|
import AuthenticationSessionHandler = require("../../../../AuthenticationSession");
|
||||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
import { AuthenticationSession } from "../../../../../../types/AuthenticationSession";
|
||||||
import UserMessages = require("../../../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../../../shared/UserMessages");
|
||||||
import { ServerVariables } from "../../../../ServerVariables";
|
import { ServerVariables } from "../../../../ServerVariables";
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@ const UNAUTHORIZED_MESSAGE = "Unauthorized access";
|
||||||
|
|
||||||
export default function (vars: ServerVariables) {
|
export default function (vars: ServerVariables) {
|
||||||
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let authSession: AuthenticationSession;
|
||||||
const token = req.body.token;
|
const token = req.body.token;
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
vars.logger.info(req, "Initiate TOTP validation for user \"%s\".", authSession.userid);
|
vars.logger.info(req, "Initiate TOTP validation for user \"%s\".", authSession.userid);
|
||||||
return vars.userDataStore.retrieveTOTPSecret(authSession.userid);
|
return vars.userDataStore.retrieveTOTPSecret(authSession.userid);
|
||||||
|
@ -32,11 +32,11 @@ export default function (vars: ServerVariables) {
|
||||||
|
|
||||||
vars.logger.debug(req, "TOTP validation succeeded.");
|
vars.logger.debug(req, "TOTP validation succeeded.");
|
||||||
authSession.second_factor = true;
|
authSession.second_factor = true;
|
||||||
redirect(req, res);
|
redirect(vars)(req, res);
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
})
|
})
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
||||||
UserMessages.OPERATION_FAILED));
|
UserMessages.OPERATION_FAILED));
|
||||||
}
|
}
|
||||||
return FirstFactorBlocker(handler);
|
return FirstFactorBlocker(handler, vars.logger);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { Identity } from "../../../../../../types/Identity";
|
||||||
import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationTemplate";
|
import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationTemplate";
|
||||||
import FirstFactorValidator = require("../../../../FirstFactorValidator");
|
import FirstFactorValidator = require("../../../../FirstFactorValidator");
|
||||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
import AuthenticationSession = require("../../../../AuthenticationSession");
|
||||||
|
import { IRequestLogger } from "../../../../logging/IRequestLogger";
|
||||||
|
|
||||||
const CHALLENGE = "u2f-register";
|
const CHALLENGE = "u2f-register";
|
||||||
const MAIL_SUBJECT = "Register your U2F device";
|
const MAIL_SUBJECT = "Register your U2F device";
|
||||||
|
@ -16,13 +17,19 @@ const POST_VALIDATION_TEMPLATE_NAME = "u2f-register";
|
||||||
|
|
||||||
|
|
||||||
export default class RegistrationHandler implements IdentityValidable {
|
export default class RegistrationHandler implements IdentityValidable {
|
||||||
|
private logger: IRequestLogger;
|
||||||
|
|
||||||
|
constructor(logger: IRequestLogger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
challenge(): string {
|
challenge(): string {
|
||||||
return CHALLENGE;
|
return CHALLENGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private retrieveIdentity(req: express.Request): BluebirdPromise<Identity> {
|
private retrieveIdentity(req: express.Request): BluebirdPromise<Identity> {
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSession.get(req, this.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
const userid = authSession.userid;
|
const userid = authSession.userid;
|
||||||
const email = authSession.email;
|
const email = authSession.email;
|
||||||
|
|
||||||
|
@ -40,7 +47,7 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
|
|
||||||
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
||||||
const that = this;
|
const that = this;
|
||||||
return FirstFactorValidator.validate(req)
|
return FirstFactorValidator.validate(req, this.logger)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return that.retrieveIdentity(req);
|
return that.retrieveIdentity(req);
|
||||||
});
|
});
|
||||||
|
@ -51,7 +58,7 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationInit(req: express.Request) {
|
postValidationInit(req: express.Request) {
|
||||||
return FirstFactorValidator.validate(req);
|
return FirstFactorValidator.validate(req, this.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationResponse(req: express.Request, res: express.Response) {
|
postValidationResponse(req: express.Request, res: express.Response) {
|
||||||
|
|
|
@ -10,60 +10,59 @@ import { U2FRegistration } from "../../../../../../types/U2FRegistration";
|
||||||
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||||
import redirect from "../../redirect";
|
import redirect from "../../redirect";
|
||||||
import ErrorReplies = require("../../../../ErrorReplies");
|
import ErrorReplies = require("../../../../ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
import { ServerVariables } from "../../../../ServerVariables";
|
||||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../../../AuthenticationSession");
|
||||||
import UserMessages = require("../../../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../../../shared/UserMessages");
|
||||||
|
import { AuthenticationSession } from "../../../../../../types/AuthenticationSession";
|
||||||
|
|
||||||
|
|
||||||
export default FirstFactorBlocker(handler);
|
export default function (vars: ServerVariables) {
|
||||||
|
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
|
let authSession: AuthenticationSession;
|
||||||
|
const appid = u2f_common.extract_app_id(req);
|
||||||
|
const registrationResponse: U2f.RegistrationData = req.body;
|
||||||
|
|
||||||
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
|
.then(function (_authSession) {
|
||||||
|
authSession = _authSession;
|
||||||
|
const registrationRequest = authSession.register_request;
|
||||||
|
|
||||||
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
if (!registrationRequest) {
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
return BluebirdPromise.reject(new Error("No registration request"));
|
||||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
}
|
||||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
|
||||||
const appid = u2f_common.extract_app_id(req);
|
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
|
||||||
const registrationResponse: U2f.RegistrationData = req.body;
|
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
if (!authSession.identity_check
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|| authSession.identity_check.challenge != "u2f-register") {
|
||||||
authSession = _authSession;
|
return BluebirdPromise.reject(new Error("Bad challenge for registration request"));
|
||||||
const registrationRequest = authSession.register_request;
|
}
|
||||||
|
|
||||||
if (!registrationRequest) {
|
vars.logger.info(req, "Finishing registration");
|
||||||
return BluebirdPromise.reject(new Error("No registration request"));
|
vars.logger.debug(req, "RegistrationRequest = %s", JSON.stringify(registrationRequest));
|
||||||
}
|
vars.logger.debug(req, "RegistrationResponse = %s", JSON.stringify(registrationResponse));
|
||||||
|
|
||||||
if (!authSession.identity_check
|
return BluebirdPromise.resolve(vars.u2f.checkRegistration(registrationRequest, registrationResponse));
|
||||||
|| authSession.identity_check.challenge != "u2f-register") {
|
})
|
||||||
return BluebirdPromise.reject(new Error("Bad challenge for registration request"));
|
.then(function (u2fResult: U2f.RegistrationResult | U2f.Error): BluebirdPromise<void> {
|
||||||
}
|
if (objectPath.has(u2fResult, "errorCode"))
|
||||||
|
return BluebirdPromise.reject(new Error("Error while registering."));
|
||||||
|
|
||||||
logger.info(req, "Finishing registration");
|
const registrationResult: U2f.RegistrationResult = u2fResult as U2f.RegistrationResult;
|
||||||
logger.debug(req, "RegistrationRequest = %s", JSON.stringify(registrationRequest));
|
vars.logger.info(req, "Store registration and reply");
|
||||||
logger.debug(req, "RegistrationResponse = %s", JSON.stringify(registrationResponse));
|
vars.logger.debug(req, "RegistrationResult = %s", JSON.stringify(registrationResult));
|
||||||
|
const registration: U2FRegistration = {
|
||||||
|
keyHandle: registrationResult.keyHandle,
|
||||||
|
publicKey: registrationResult.publicKey
|
||||||
|
};
|
||||||
|
return vars.userDataStore.saveU2FRegistration(authSession.userid, appid, registration);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
authSession.identity_check = undefined;
|
||||||
|
redirect(vars)(req, res);
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
})
|
||||||
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
||||||
|
UserMessages.OPERATION_FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
return BluebirdPromise.resolve(u2f.checkRegistration(registrationRequest, registrationResponse));
|
return FirstFactorBlocker(handler, vars.logger);
|
||||||
})
|
|
||||||
.then(function (u2fResult: U2f.RegistrationResult | U2f.Error): BluebirdPromise<void> {
|
|
||||||
if (objectPath.has(u2fResult, "errorCode"))
|
|
||||||
return BluebirdPromise.reject(new Error("Error while registering."));
|
|
||||||
|
|
||||||
const registrationResult: U2f.RegistrationResult = u2fResult as U2f.RegistrationResult;
|
|
||||||
logger.info(req, "Store registration and reply");
|
|
||||||
logger.debug(req, "RegistrationResult = %s", JSON.stringify(registrationResult));
|
|
||||||
const registration: U2FRegistration = {
|
|
||||||
keyHandle: registrationResult.keyHandle,
|
|
||||||
publicKey: registrationResult.publicKey
|
|
||||||
};
|
|
||||||
return userDataStore.saveU2FRegistration(authSession.userid, appid, registration);
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
authSession.identity_check = undefined;
|
|
||||||
redirect(req, res);
|
|
||||||
return BluebirdPromise.resolve();
|
|
||||||
})
|
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, logger,
|
|
||||||
UserMessages.OPERATION_FAILED));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,40 +8,40 @@ import express = require("express");
|
||||||
import U2f = require("u2f");
|
import U2f = require("u2f");
|
||||||
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||||
import ErrorReplies = require("../../../../ErrorReplies");
|
import ErrorReplies = require("../../../../ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
import AuthenticationSessionHandler = require("../../../../AuthenticationSession");
|
||||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
import { AuthenticationSession } from "../../../../../../types/AuthenticationSession";
|
||||||
import UserMessages = require("../../../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../../../shared/UserMessages");
|
||||||
|
import { ServerVariables } from "../../../../ServerVariables";
|
||||||
|
|
||||||
export default FirstFactorBlocker(handler);
|
export default function (vars: ServerVariables) {
|
||||||
|
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
|
let authSession: AuthenticationSession;
|
||||||
|
const appid: string = u2f_common.extract_app_id(req);
|
||||||
|
|
||||||
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
.then(function (_authSession) {
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
authSession = _authSession;
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
if (!authSession.identity_check
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|| authSession.identity_check.challenge != "u2f-register") {
|
||||||
authSession = _authSession;
|
res.status(403);
|
||||||
|
res.send();
|
||||||
|
return BluebirdPromise.reject(new Error("Bad challenge."));
|
||||||
|
}
|
||||||
|
|
||||||
if (!authSession.identity_check
|
vars.logger.info(req, "Starting registration for appId '%s'", appid);
|
||||||
|| authSession.identity_check.challenge != "u2f-register") {
|
|
||||||
res.status(403);
|
|
||||||
res.send();
|
|
||||||
return BluebirdPromise.reject(new Error("Bad challenge."));
|
|
||||||
}
|
|
||||||
|
|
||||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
return BluebirdPromise.resolve(vars.u2f.request(appid));
|
||||||
const appid: string = u2f_common.extract_app_id(req);
|
})
|
||||||
|
.then(function (registrationRequest: U2f.Request) {
|
||||||
|
vars.logger.debug(req, "RegistrationRequest = %s", JSON.stringify(registrationRequest));
|
||||||
|
authSession.register_request = registrationRequest;
|
||||||
|
res.json(registrationRequest);
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
})
|
||||||
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
||||||
|
UserMessages.OPERATION_FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
logger.info(req, "Starting registration for appId '%s'", appid);
|
return FirstFactorBlocker(handler, vars.logger);
|
||||||
|
|
||||||
return BluebirdPromise.resolve(u2f.request(appid));
|
|
||||||
})
|
|
||||||
.then(function (registrationRequest: U2f.Request) {
|
|
||||||
logger.debug(req, "RegistrationRequest = %s", JSON.stringify(registrationRequest));
|
|
||||||
authSession.register_request = registrationRequest;
|
|
||||||
res.json(registrationRequest);
|
|
||||||
return BluebirdPromise.resolve();
|
|
||||||
})
|
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, logger,
|
|
||||||
UserMessages.OPERATION_FAILED));
|
|
||||||
}
|
}
|
|
@ -11,47 +11,45 @@ import exceptions = require("../../../../Exceptions");
|
||||||
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||||
import redirect from "../../redirect";
|
import redirect from "../../redirect";
|
||||||
import ErrorReplies = require("../../../../ErrorReplies");
|
import ErrorReplies = require("../../../../ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
import { ServerVariables } from "../../../../ServerVariables";
|
||||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../../../AuthenticationSession");
|
||||||
import UserMessages = require("../../../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../../../shared/UserMessages");
|
||||||
|
import { AuthenticationSession } from "../../../../../../types/AuthenticationSession";
|
||||||
|
|
||||||
export default FirstFactorBlocker(handler);
|
export default function (vars: ServerVariables) {
|
||||||
|
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
|
let authSession: AuthenticationSession;
|
||||||
|
const appId = u2f_common.extract_app_id(req);
|
||||||
|
|
||||||
export function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
.then(function (_authSession) {
|
||||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
authSession = _authSession;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
if (!authSession.sign_request) {
|
||||||
|
const err = new Error("No sign request");
|
||||||
|
ErrorReplies.replyWithError401(req, res, vars.logger)(err);
|
||||||
|
return BluebirdPromise.reject(err);
|
||||||
|
}
|
||||||
|
const userid = authSession.userid;
|
||||||
|
return vars.userDataStore.retrieveU2FRegistration(userid, appId);
|
||||||
|
})
|
||||||
|
.then(function (doc: U2FRegistrationDocument): BluebirdPromise<U2f.SignatureResult | U2f.Error> {
|
||||||
|
const signRequest = authSession.sign_request;
|
||||||
|
const signData: U2f.SignatureData = req.body;
|
||||||
|
vars.logger.info(req, "Finish authentication");
|
||||||
|
return BluebirdPromise.resolve(vars.u2f.checkSignature(signRequest, signData, doc.registration.publicKey));
|
||||||
|
})
|
||||||
|
.then(function (result: U2f.SignatureResult | U2f.Error): BluebirdPromise<void> {
|
||||||
|
if (objectPath.has(result, "errorCode"))
|
||||||
|
return BluebirdPromise.reject(new Error("Error while signing"));
|
||||||
|
vars.logger.info(req, "Successful authentication");
|
||||||
|
authSession.second_factor = true;
|
||||||
|
redirect(vars)(req, res);
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
})
|
||||||
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
||||||
|
UserMessages.OPERATION_FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
return FirstFactorBlocker(handler, vars.logger);
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|
||||||
authSession = _authSession;
|
|
||||||
if (!authSession.sign_request) {
|
|
||||||
const err = new Error("No sign request");
|
|
||||||
ErrorReplies.replyWithError401(req, res, logger)(err);
|
|
||||||
return BluebirdPromise.reject(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
const userid = authSession.userid;
|
|
||||||
const appid = u2f_common.extract_app_id(req);
|
|
||||||
return userDataStore.retrieveU2FRegistration(userid, appid);
|
|
||||||
})
|
|
||||||
.then(function (doc: U2FRegistrationDocument): BluebirdPromise<U2f.SignatureResult | U2f.Error> {
|
|
||||||
const appId = u2f_common.extract_app_id(req);
|
|
||||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
|
||||||
const signRequest = authSession.sign_request;
|
|
||||||
const signData: U2f.SignatureData = req.body;
|
|
||||||
logger.info(req, "Finish authentication");
|
|
||||||
return BluebirdPromise.resolve(u2f.checkSignature(signRequest, signData, doc.registration.publicKey));
|
|
||||||
})
|
|
||||||
.then(function (result: U2f.SignatureResult | U2f.Error): BluebirdPromise<void> {
|
|
||||||
if (objectPath.has(result, "errorCode"))
|
|
||||||
return BluebirdPromise.reject(new Error("Error while signing"));
|
|
||||||
logger.info(req, "Successful authentication");
|
|
||||||
authSession.second_factor = true;
|
|
||||||
redirect(req, res);
|
|
||||||
return BluebirdPromise.resolve();
|
|
||||||
})
|
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, logger,
|
|
||||||
UserMessages.OPERATION_FAILED));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,47 +11,46 @@ import exceptions = require("../../../../Exceptions");
|
||||||
import { SignMessage } from "../../../../../../../shared/SignMessage";
|
import { SignMessage } from "../../../../../../../shared/SignMessage";
|
||||||
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||||
import ErrorReplies = require("../../../../ErrorReplies");
|
import ErrorReplies = require("../../../../ErrorReplies");
|
||||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
import AuthenticationSessionHandler = require("../../../../AuthenticationSession");
|
||||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
|
||||||
import UserMessages = require("../../../../../../../shared/UserMessages");
|
import UserMessages = require("../../../../../../../shared/UserMessages");
|
||||||
|
import { ServerVariables } from "../../../../ServerVariables";
|
||||||
|
import { AuthenticationSession } from "../../../../../../types/AuthenticationSession";
|
||||||
|
|
||||||
export default FirstFactorBlocker(handler);
|
export default function (vars: ServerVariables) {
|
||||||
|
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
|
let authSession: AuthenticationSession;
|
||||||
|
const appId = u2f_common.extract_app_id(req);
|
||||||
|
|
||||||
export function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
.then(function (_authSession) {
|
||||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
authSession = _authSession;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
return vars.userDataStore.retrieveU2FRegistration(authSession.userid, appId);
|
||||||
const appId = u2f_common.extract_app_id(req);
|
})
|
||||||
|
.then(function (doc: U2FRegistrationDocument): BluebirdPromise<SignMessage> {
|
||||||
|
if (!doc)
|
||||||
|
return BluebirdPromise.reject(new exceptions.AccessDeniedError("No U2F registration found"));
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
const appId: string = u2f_common.extract_app_id(req);
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
vars.logger.info(req, "Start authentication of app '%s'", appId);
|
||||||
authSession = _authSession;
|
vars.logger.debug(req, "AppId = %s, keyHandle = %s", appId, JSON.stringify(doc.registration.keyHandle));
|
||||||
return userDataStore.retrieveU2FRegistration(authSession.userid, appId);
|
|
||||||
})
|
|
||||||
.then(function (doc: U2FRegistrationDocument): BluebirdPromise<SignMessage> {
|
|
||||||
if (!doc)
|
|
||||||
return BluebirdPromise.reject(new exceptions.AccessDeniedError("No U2F registration found"));
|
|
||||||
|
|
||||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
const request = vars.u2f.request(appId, doc.registration.keyHandle);
|
||||||
const appId: string = u2f_common.extract_app_id(req);
|
const authenticationMessage: SignMessage = {
|
||||||
logger.info(req, "Start authentication of app '%s'", appId);
|
request: request,
|
||||||
logger.debug(req, "AppId = %s, keyHandle = %s", appId, JSON.stringify(doc.registration.keyHandle));
|
keyHandle: doc.registration.keyHandle
|
||||||
|
};
|
||||||
|
return BluebirdPromise.resolve(authenticationMessage);
|
||||||
|
})
|
||||||
|
.then(function (authenticationMessage: SignMessage) {
|
||||||
|
vars.logger.info(req, "Store authentication request and reply");
|
||||||
|
vars.logger.debug(req, "AuthenticationRequest = %s", authenticationMessage);
|
||||||
|
authSession.sign_request = authenticationMessage.request;
|
||||||
|
res.json(authenticationMessage);
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
})
|
||||||
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger,
|
||||||
|
UserMessages.OPERATION_FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
const request = u2f.request(appId, doc.registration.keyHandle);
|
return FirstFactorBlocker(handler, vars.logger);
|
||||||
const authenticationMessage: SignMessage = {
|
|
||||||
request: request,
|
|
||||||
keyHandle: doc.registration.keyHandle
|
|
||||||
};
|
|
||||||
return BluebirdPromise.resolve(authenticationMessage);
|
|
||||||
})
|
|
||||||
.then(function (authenticationMessage: SignMessage) {
|
|
||||||
logger.info(req, "Store authentication request and reply");
|
|
||||||
logger.debug(req, "AuthenticationRequest = %s", authenticationMessage);
|
|
||||||
authSession.sign_request = authenticationMessage.request;
|
|
||||||
res.json(authenticationMessage);
|
|
||||||
return BluebirdPromise.resolve();
|
|
||||||
})
|
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, logger,
|
|
||||||
UserMessages.OPERATION_FAILED));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ import winston = require("winston");
|
||||||
import AuthenticationValidator = require("../../AuthenticationValidator");
|
import AuthenticationValidator = require("../../AuthenticationValidator");
|
||||||
import ErrorReplies = require("../../ErrorReplies");
|
import ErrorReplies = require("../../ErrorReplies");
|
||||||
import { AppConfiguration } from "../../configuration/Configuration";
|
import { AppConfiguration } from "../../configuration/Configuration";
|
||||||
import AuthenticationSession = require("../../AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../AuthenticationSession");
|
||||||
|
import { AuthenticationSession } from "../../../../types/AuthenticationSession";
|
||||||
import Constants = require("../../../../../shared/constants");
|
import Constants = require("../../../../../shared/constants");
|
||||||
import Util = require("util");
|
import Util = require("util");
|
||||||
import { DomainExtractor } from "../../utils/DomainExtractor";
|
import { DomainExtractor } from "../../utils/DomainExtractor";
|
||||||
|
@ -22,7 +23,7 @@ const REMOTE_USER = "Remote-User";
|
||||||
const REMOTE_GROUPS = "Remote-Groups";
|
const REMOTE_GROUPS = "Remote-Groups";
|
||||||
|
|
||||||
function verify_inactivity(req: express.Request,
|
function verify_inactivity(req: express.Request,
|
||||||
authSession: AuthenticationSession.AuthenticationSession,
|
authSession: AuthenticationSession,
|
||||||
configuration: AppConfiguration, logger: IRequestLogger)
|
configuration: AppConfiguration, logger: IRequestLogger)
|
||||||
: BluebirdPromise<void> {
|
: BluebirdPromise<void> {
|
||||||
|
|
||||||
|
@ -43,17 +44,17 @@ function verify_inactivity(req: express.Request,
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(req, "Session has been reset after too long inactivity period.");
|
logger.debug(req, "Session has been reset after too long inactivity period.");
|
||||||
AuthenticationSession.reset(req);
|
AuthenticationSessionHandler.reset(req);
|
||||||
return BluebirdPromise.reject(new Error("Inactivity period exceeded."));
|
return BluebirdPromise.reject(new Error("Inactivity period exceeded."));
|
||||||
}
|
}
|
||||||
|
|
||||||
function verify_filter(req: express.Request, res: express.Response,
|
function verify_filter(req: express.Request, res: express.Response,
|
||||||
vars: ServerVariables): BluebirdPromise<void> {
|
vars: ServerVariables): BluebirdPromise<void> {
|
||||||
let _authSession: AuthenticationSession.AuthenticationSession;
|
let _authSession: AuthenticationSession;
|
||||||
let username: string;
|
let username: string;
|
||||||
let groups: string[];
|
let groups: string[];
|
||||||
|
|
||||||
return AuthenticationSession.get(req)
|
return AuthenticationSessionHandler.get(req, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
_authSession = authSession;
|
_authSession = authSession;
|
||||||
username = _authSession.userid;
|
username = _authSession.userid;
|
||||||
|
@ -97,6 +98,7 @@ function verify_filter(req: express.Request, res: express.Response,
|
||||||
.then(function () {
|
.then(function () {
|
||||||
res.setHeader(REMOTE_USER, username);
|
res.setHeader(REMOTE_USER, username);
|
||||||
res.setHeader(REMOTE_GROUPS, groups.join(","));
|
res.setHeader(REMOTE_GROUPS, groups.join(","));
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,6 @@ block form-header
|
||||||
<img class="header-img" src="/img/success.png" alt="">
|
<img class="header-img" src="/img/success.png" alt="">
|
||||||
|
|
||||||
block content
|
block content
|
||||||
<p>You are already logged in as <b>#{ username }</b>.<br/>
|
<p>You are already logged in as <b>#{ username }</b>.<br/><br/>
|
||||||
| Click <a href="#{ logout_endpoint }">here</a> to log off.<p>
|
| If you are not redirected in few seconds, click <a href="#{ redirection_url }">here</a>.<br/><br/>
|
||||||
|
| Otherwise, click <a href="#{ logout_endpoint }">here</a> to log off.<p>
|
||||||
|
|
|
@ -7,7 +7,7 @@ html
|
||||||
link(rel="icon", href="/img/icon.png" type="image/png" sizes="32x32")/
|
link(rel="icon", href="/img/icon.png" type="image/png" sizes="32x32")/
|
||||||
link(rel="stylesheet", type="text/css", href="/css/authelia.css")/
|
link(rel="stylesheet", type="text/css", href="/css/authelia.css")/
|
||||||
if redirection_url
|
if redirection_url
|
||||||
<meta http-equiv="refresh" content="5;url=#{redirection_url}">
|
<meta http-equiv="refresh" content="4;url=#{redirection_url}">
|
||||||
body
|
body
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -1,39 +1,41 @@
|
||||||
|
|
||||||
import sinon = require("sinon");
|
import sinon = require("sinon");
|
||||||
import IdentityValidator = require("../src/lib/IdentityCheckMiddleware");
|
import IdentityValidator = require("../src/lib/IdentityCheckMiddleware");
|
||||||
import AuthenticationSession = require("../src/lib/AuthenticationSession");
|
import AuthenticationSessionHandler = require("../src/lib/AuthenticationSession");
|
||||||
|
import { AuthenticationSession } from "../types/AuthenticationSession";
|
||||||
import { UserDataStore } from "../src/lib/storage/UserDataStore";
|
import { UserDataStore } from "../src/lib/storage/UserDataStore";
|
||||||
|
|
||||||
import exceptions = require("../src/lib/Exceptions");
|
import exceptions = require("../src/lib/Exceptions");
|
||||||
|
import { ServerVariables } from "../src/lib/ServerVariables";
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import Promise = require("bluebird");
|
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
|
|
||||||
import ExpressMock = require("./mocks/express");
|
import ExpressMock = require("./mocks/express");
|
||||||
import NotifierMock = require("./mocks/Notifier");
|
import NotifierMock = require("./mocks/Notifier");
|
||||||
import IdentityValidatorMock = require("./mocks/IdentityValidator");
|
import IdentityValidatorMock = require("./mocks/IdentityValidator");
|
||||||
import ServerVariablesMock = require("./mocks/ServerVariablesMock");
|
import { RequestLoggerStub } from "./mocks/RequestLoggerStub";
|
||||||
|
import { ServerVariablesMock, ServerVariablesMockBuilder } from "./mocks/ServerVariablesMockBuilder";
|
||||||
|
|
||||||
|
|
||||||
describe("test identity check process", function () {
|
describe("test identity check process", function () {
|
||||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let notifier: NotifierMock.NotifierMock;
|
|
||||||
let app: express.Application;
|
let app: express.Application;
|
||||||
let app_get: sinon.SinonStub;
|
let app_get: sinon.SinonStub;
|
||||||
let app_post: sinon.SinonStub;
|
let app_post: sinon.SinonStub;
|
||||||
let identityValidable: IdentityValidatorMock.IdentityValidableMock;
|
let identityValidable: IdentityValidatorMock.IdentityValidableMock;
|
||||||
|
let mocks: ServerVariablesMock;
|
||||||
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
res = ExpressMock.ResponseMock();
|
res = ExpressMock.ResponseMock();
|
||||||
|
|
||||||
identityValidable = IdentityValidatorMock.IdentityValidableMock();
|
identityValidable = IdentityValidatorMock.IdentityValidableMock();
|
||||||
|
|
||||||
notifier = NotifierMock.NotifierMock();
|
|
||||||
notifier.notify = sinon.stub().returns(Promise.resolve());
|
|
||||||
|
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.session = {};
|
req.session = {};
|
||||||
|
@ -42,9 +44,7 @@ describe("test identity check process", function () {
|
||||||
req.query = {};
|
req.query = {};
|
||||||
req.app = {};
|
req.app = {};
|
||||||
|
|
||||||
mocks = ServerVariablesMock.mock(req.app);
|
mocks.notifier.notifyStub.returns(BluebirdPromise.resolve());
|
||||||
mocks.notifier = notifier;
|
|
||||||
|
|
||||||
mocks.userDataStore.produceIdentityValidationTokenStub.returns(Promise.resolve());
|
mocks.userDataStore.produceIdentityValidationTokenStub.returns(Promise.resolve());
|
||||||
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(Promise.resolve({ userId: "user" }));
|
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(Promise.resolve({ userId: "user" }));
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ describe("test identity check process", function () {
|
||||||
function test_start_get_handler() {
|
function test_start_get_handler() {
|
||||||
it("should send 401 if pre validation initialization throws a first factor error", function () {
|
it("should send 401 if pre validation initialization throws a first factor error", function () {
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.reject(new exceptions.FirstFactorValidationError("Error during prevalidation")));
|
identityValidable.preValidationInit.returns(BluebirdPromise.reject(new exceptions.FirstFactorValidationError("Error during prevalidation")));
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint");
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
||||||
|
@ -77,7 +77,7 @@ describe("test identity check process", function () {
|
||||||
const identity = { userid: "abc" };
|
const identity = { userid: "abc" };
|
||||||
|
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint");
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
||||||
|
@ -91,7 +91,7 @@ describe("test identity check process", function () {
|
||||||
const identity = { email: "abc@example.com" };
|
const identity = { email: "abc@example.com" };
|
||||||
|
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint");
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||||
|
@ -107,11 +107,11 @@ describe("test identity check process", function () {
|
||||||
req.get = sinon.stub().withArgs("Host").returns("localhost");
|
req.get = sinon.stub().withArgs("Host").returns("localhost");
|
||||||
|
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/finish_endpoint");
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/finish_endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert(notifier.notify.calledOnce);
|
Assert(mocks.notifier.notifyStub.calledOnce);
|
||||||
Assert(mocks.userDataStore.produceIdentityValidationTokenStub.calledOnce);
|
Assert(mocks.userDataStore.produceIdentityValidationTokenStub.calledOnce);
|
||||||
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[0], "user");
|
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[0], "user");
|
||||||
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[3], 240000);
|
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[3], 240000);
|
||||||
|
@ -122,7 +122,7 @@ describe("test identity check process", function () {
|
||||||
function test_finish_get_handler() {
|
function test_finish_get_handler() {
|
||||||
it("should send 401 if no identity_token is provided", function () {
|
it("should send 401 if no identity_token is provided", function () {
|
||||||
|
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable);
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
||||||
|
@ -134,7 +134,7 @@ describe("test identity check process", function () {
|
||||||
it("should call postValidation if identity_token is provided and still valid", function () {
|
it("should call postValidation if identity_token is provided and still valid", function () {
|
||||||
req.query.identity_token = "token";
|
req.query.identity_token = "token";
|
||||||
|
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable);
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
||||||
return callback(req as any, res as any, undefined);
|
return callback(req as any, res as any, undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ describe("test identity check process", function () {
|
||||||
|
|
||||||
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.reject(new Error("Invalid token")));
|
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.reject(new Error("Invalid token")));
|
||||||
|
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable);
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
|
@ -155,11 +155,11 @@ describe("test identity check process", function () {
|
||||||
req.query.identity_token = "token";
|
req.query.identity_token = "token";
|
||||||
|
|
||||||
req.session = {};
|
req.session = {};
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let authSession: AuthenticationSession;
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable);
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
return callback(req as any, res as any, undefined);
|
return callback(req as any, res as any, undefined);
|
||||||
})
|
})
|
||||||
|
|
|
@ -167,4 +167,13 @@ describe("test config parser", function () {
|
||||||
} as ACLConfiguration);
|
} as ACLConfiguration);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("default_redirection_url", function() {
|
||||||
|
it("should parse default_redirection_url", function() {
|
||||||
|
const userConfig = buildYamlConfig();
|
||||||
|
userConfig.default_redirection_url = "dummy_url";
|
||||||
|
const config = ConfigurationParser.parse(userConfig);
|
||||||
|
Assert.deepEqual(config.default_redirection_url, "dummy_url");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
import Sinon = require("sinon");
|
|
||||||
import express = require("express");
|
|
||||||
import { RequestLoggerStub } from "./RequestLoggerStub";
|
|
||||||
import { UserDataStoreStub } from "./storage/UserDataStoreStub";
|
|
||||||
import { AuthenticationMethodCalculator } from "../../src/lib/AuthenticationMethodCalculator";
|
|
||||||
import { VARIABLES_KEY } from "../../src/lib/ServerVariablesHandler";
|
|
||||||
|
|
||||||
export interface ServerVariablesMock {
|
|
||||||
logger: any;
|
|
||||||
ldapAuthenticator: any;
|
|
||||||
ldapEmailsRetriever: any;
|
|
||||||
ldapPasswordUpdater: any;
|
|
||||||
totpValidator: any;
|
|
||||||
totpGenerator: any;
|
|
||||||
u2f: any;
|
|
||||||
userDataStore: UserDataStoreStub;
|
|
||||||
notifier: any;
|
|
||||||
regulator: any;
|
|
||||||
config: any;
|
|
||||||
accessController: any;
|
|
||||||
authenticationMethodsCalculator: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function mock(app: express.Application): ServerVariablesMock {
|
|
||||||
const mocks: ServerVariablesMock = {
|
|
||||||
accessController: Sinon.stub(),
|
|
||||||
config: Sinon.stub(),
|
|
||||||
ldapAuthenticator: Sinon.stub() as any,
|
|
||||||
ldapEmailsRetriever: Sinon.stub() as any,
|
|
||||||
ldapPasswordUpdater: Sinon.stub() as any,
|
|
||||||
logger: new RequestLoggerStub(),
|
|
||||||
notifier: Sinon.stub(),
|
|
||||||
regulator: Sinon.stub(),
|
|
||||||
totpGenerator: Sinon.stub(),
|
|
||||||
totpValidator: Sinon.stub(),
|
|
||||||
u2f: Sinon.stub(),
|
|
||||||
userDataStore: new UserDataStoreStub(),
|
|
||||||
authenticationMethodsCalculator: new AuthenticationMethodCalculator({
|
|
||||||
default_method: "two_factor",
|
|
||||||
per_subdomain_methods: {}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
app.get = Sinon.stub().withArgs(VARIABLES_KEY).returns(mocks);
|
|
||||||
return mocks;
|
|
||||||
}
|
|
|
@ -2,13 +2,11 @@
|
||||||
import Sinon = require("sinon");
|
import Sinon = require("sinon");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import Winston = require("winston");
|
|
||||||
|
|
||||||
import FirstFactorPost = require("../../../src/lib/routes/firstfactor/post");
|
import FirstFactorPost = require("../../../src/lib/routes/firstfactor/post");
|
||||||
import exceptions = require("../../../src/lib/Exceptions");
|
import exceptions = require("../../../src/lib/Exceptions");
|
||||||
import AuthenticationSession = require("../../../src/lib/AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../../src/lib/AuthenticationSession");
|
||||||
|
import { AuthenticationSession } from "../../../types/AuthenticationSession";
|
||||||
import Endpoints = require("../../../../shared/api");
|
import Endpoints = require("../../../../shared/api");
|
||||||
|
|
||||||
import AuthenticationRegulatorMock = require("../../mocks/AuthenticationRegulator");
|
import AuthenticationRegulatorMock = require("../../mocks/AuthenticationRegulator");
|
||||||
import { AccessControllerStub } from "../../mocks/AccessControllerStub";
|
import { AccessControllerStub } from "../../mocks/AccessControllerStub";
|
||||||
import ExpressMock = require("../../mocks/express");
|
import ExpressMock = require("../../mocks/express");
|
||||||
|
@ -35,9 +33,6 @@ describe("test the first factor validation route", function () {
|
||||||
mocks.regulator.markStub.returns(BluebirdPromise.resolve());
|
mocks.regulator.markStub.returns(BluebirdPromise.resolve());
|
||||||
|
|
||||||
req = {
|
req = {
|
||||||
app: {
|
|
||||||
get: Sinon.stub().returns({ logger: Winston })
|
|
||||||
},
|
|
||||||
body: {
|
body: {
|
||||||
username: "username",
|
username: "username",
|
||||||
password: "password"
|
password: "password"
|
||||||
|
@ -52,7 +47,6 @@ describe("test the first factor validation route", function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AuthenticationSession.reset(req as any);
|
|
||||||
res = ExpressMock.ResponseMock();
|
res = ExpressMock.ResponseMock();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,9 +56,9 @@ describe("test the first factor validation route", function () {
|
||||||
emails: emails,
|
emails: emails,
|
||||||
groups: groups
|
groups: groups
|
||||||
}));
|
}));
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let authSession: AuthenticationSession;
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
return FirstFactorPost.default(vars)(req as any, res as any);
|
return FirstFactorPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
|
@ -82,15 +76,15 @@ describe("test the first factor validation route", function () {
|
||||||
|
|
||||||
it("should set first email address as user session variable", function () {
|
it("should set first email address as user session variable", function () {
|
||||||
const emails = ["test_ok@example.com"];
|
const emails = ["test_ok@example.com"];
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let authSession: AuthenticationSession;
|
||||||
mocks.ldapAuthenticator.authenticateStub.withArgs("username", "password")
|
mocks.ldapAuthenticator.authenticateStub.withArgs("username", "password")
|
||||||
.returns(BluebirdPromise.resolve({
|
.returns(BluebirdPromise.resolve({
|
||||||
emails: emails,
|
emails: emails,
|
||||||
groups: groups
|
groups: groups
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
return FirstFactorPost.default(vars)(req as any, res as any);
|
return FirstFactorPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,103 +1,77 @@
|
||||||
|
|
||||||
import PasswordResetHandler from "../../../../src/lib/routes/password-reset/identity/PasswordResetHandler";
|
import PasswordResetHandler from "../../../../src/lib/routes/password-reset/identity/PasswordResetHandler";
|
||||||
import PasswordUpdater = require("../../../../src/lib/ldap/PasswordUpdater");
|
import PasswordUpdater = require("../../../../src/lib/ldap/PasswordUpdater");
|
||||||
import { ServerVariablesHandler } from "../../../../src/lib/ServerVariablesHandler";
|
|
||||||
import { UserDataStore } from "../../../../src/lib/storage/UserDataStore";
|
import { UserDataStore } from "../../../../src/lib/storage/UserDataStore";
|
||||||
import Sinon = require("sinon");
|
import Sinon = require("sinon");
|
||||||
import winston = require("winston");
|
import winston = require("winston");
|
||||||
import assert = require("assert");
|
import assert = require("assert");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
|
|
||||||
import ExpressMock = require("../../../mocks/express");
|
import ExpressMock = require("../../../mocks/express");
|
||||||
import ServerVariablesMock = require("../../../mocks/ServerVariablesMock");
|
import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../mocks/ServerVariablesMockBuilder";
|
||||||
|
import { ServerVariables } from "../../../../src/lib/ServerVariables";
|
||||||
|
|
||||||
describe("test reset password identity check", function () {
|
describe("test reset password identity check", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let configuration: any;
|
let mocks: ServerVariablesMock;
|
||||||
let serverVariables: ServerVariablesMock.ServerVariablesMock;
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = {
|
req = {
|
||||||
query: {
|
query: {
|
||||||
userid: "user"
|
userid: "user"
|
||||||
},
|
},
|
||||||
app: {
|
session: {
|
||||||
get: Sinon.stub()
|
auth: {
|
||||||
},
|
userid: "user",
|
||||||
session: {
|
email: "user@example.com",
|
||||||
auth_session: {
|
first_factor: true,
|
||||||
userid: "user",
|
second_factor: false
|
||||||
email: "user@example.com",
|
}
|
||||||
first_factor: true,
|
},
|
||||||
second_factor: false
|
headers: {
|
||||||
}
|
host: "localhost"
|
||||||
},
|
}
|
||||||
headers: {
|
};
|
||||||
host: "localhost"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
inMemoryOnly: true
|
inMemoryOnly: true
|
||||||
};
|
};
|
||||||
|
|
||||||
serverVariables = ServerVariablesMock.mock(req.app);
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
serverVariables.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||||
serverVariables.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||||
serverVariables.userDataStore.produceIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.produceIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
||||||
serverVariables.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
||||||
|
res = ExpressMock.ResponseMock();
|
||||||
|
});
|
||||||
|
|
||||||
configuration = {
|
describe("test reset password identity pre check", () => {
|
||||||
ldap: {
|
it("should fail when no userid is provided", function () {
|
||||||
base_dn: "dc=example,dc=com",
|
req.query.userid = undefined;
|
||||||
user_name_attribute: "cn"
|
const handler = new PasswordResetHandler(vars.logger, vars.ldapEmailsRetriever);
|
||||||
}
|
return handler.preValidationInit(req as any)
|
||||||
};
|
.then(function () { return BluebirdPromise.reject("It should fail"); })
|
||||||
|
.catch(function (err: Error) {
|
||||||
serverVariables.config = configuration;
|
return BluebirdPromise.resolve();
|
||||||
serverVariables.ldapEmailsRetriever = {
|
|
||||||
retrieve: Sinon.stub()
|
|
||||||
} as any;
|
|
||||||
res = ExpressMock.ResponseMock();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("test reset password identity pre check", () => {
|
|
||||||
it("should fail when no userid is provided", function () {
|
|
||||||
req.query.userid = undefined;
|
|
||||||
const handler = new PasswordResetHandler();
|
|
||||||
return handler.preValidationInit(req as any)
|
|
||||||
.then(function () { return BluebirdPromise.reject("It should fail"); })
|
|
||||||
.catch(function (err: Error) {
|
|
||||||
return BluebirdPromise.resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should fail if ldap fail", function (done) {
|
|
||||||
(serverVariables.ldapEmailsRetriever as any).retrieve.returns(BluebirdPromise.reject("Internal error"));
|
|
||||||
new PasswordResetHandler().preValidationInit(req as any)
|
|
||||||
.catch(function (err: Error) {
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perform a search in ldap to find email address", function (done) {
|
|
||||||
configuration.ldap.user_name_attribute = "uid";
|
|
||||||
(serverVariables.ldapEmailsRetriever as any).retrieve.returns(BluebirdPromise.resolve([]));
|
|
||||||
new PasswordResetHandler().preValidationInit(req as any)
|
|
||||||
.then(function () {
|
|
||||||
assert.equal("user", (serverVariables.ldapEmailsRetriever as any).retrieve.getCall(0).args[0]);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should returns identity when ldap replies", function (done) {
|
|
||||||
(serverVariables.ldapEmailsRetriever as any).retrieve.returns(BluebirdPromise.resolve(["test@example.com"]));
|
|
||||||
new PasswordResetHandler().preValidationInit(req as any)
|
|
||||||
.then(function () {
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should fail if ldap fail", function () {
|
||||||
|
mocks.ldapEmailsRetriever.retrieveStub.returns(BluebirdPromise.reject("Internal error"));
|
||||||
|
new PasswordResetHandler(vars.logger, vars.ldapEmailsRetriever).preValidationInit(req as any)
|
||||||
|
.then(function () { return BluebirdPromise.reject(new Error("should not be here")); },
|
||||||
|
function (err: Error) {
|
||||||
|
return BluebirdPromise.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should returns identity when ldap replies", function () {
|
||||||
|
mocks.ldapEmailsRetriever.retrieveStub.returns(BluebirdPromise.resolve(["test@example.com"]));
|
||||||
|
return new PasswordResetHandler(vars.logger, vars.ldapEmailsRetriever).preValidationInit(req as any);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,65 +1,60 @@
|
||||||
|
|
||||||
import PasswordResetFormPost = require("../../../src/lib/routes/password-reset/form/post");
|
import PasswordResetFormPost = require("../../../src/lib/routes/password-reset/form/post");
|
||||||
import { PasswordUpdater } from "../../../src/lib/ldap/PasswordUpdater";
|
import { PasswordUpdater } from "../../../src/lib/ldap/PasswordUpdater";
|
||||||
import AuthenticationSession = require("../../../src/lib/AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../../src/lib/AuthenticationSession");
|
||||||
import { ServerVariablesHandler } from "../../../src/lib/ServerVariablesHandler";
|
|
||||||
import { UserDataStore } from "../../../src/lib/storage/UserDataStore";
|
import { UserDataStore } from "../../../src/lib/storage/UserDataStore";
|
||||||
import Sinon = require("sinon");
|
import Sinon = require("sinon");
|
||||||
import winston = require("winston");
|
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
|
|
||||||
import ExpressMock = require("../../mocks/express");
|
import ExpressMock = require("../../mocks/express");
|
||||||
import ServerVariablesMock = require("../../mocks/ServerVariablesMock");
|
import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../mocks/ServerVariablesMockBuilder";
|
||||||
|
import { ServerVariables } from "../../../src/lib/ServerVariables";
|
||||||
|
|
||||||
describe("test reset password route", function () {
|
describe("test reset password route", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let configuration: any;
|
let vars: ServerVariables;
|
||||||
let serverVariables: ServerVariablesMock.ServerVariablesMock;
|
let mocks: ServerVariablesMock;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = {
|
req = {
|
||||||
body: {
|
body: {
|
||||||
userid: "user"
|
userid: "user"
|
||||||
},
|
},
|
||||||
app: {
|
|
||||||
get: Sinon.stub().returns({ logger: winston })
|
|
||||||
},
|
|
||||||
session: {},
|
session: {},
|
||||||
headers: {
|
headers: {
|
||||||
host: "localhost"
|
host: "localhost"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AuthenticationSession.reset(req as any);
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
inMemoryOnly: true
|
inMemoryOnly: true
|
||||||
};
|
};
|
||||||
|
|
||||||
serverVariables = ServerVariablesMock.mock(req.app);
|
mocks.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||||
serverVariables.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||||
serverVariables.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.produceIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
||||||
serverVariables.userDataStore.produceIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
||||||
serverVariables.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.resolve({}));
|
|
||||||
|
|
||||||
configuration = {
|
mocks.config.ldap = {
|
||||||
ldap: {
|
url: "ldap://ldapjs",
|
||||||
base_dn: "dc=example,dc=com",
|
mail_attribute: "mail",
|
||||||
user_name_attribute: "cn"
|
user: "user",
|
||||||
}
|
password: "password",
|
||||||
|
users_dn: "ou=users,dc=example,dc=com",
|
||||||
|
groups_dn: "ou=groups,dc=example,dc=com",
|
||||||
|
users_filter: "user",
|
||||||
|
group_name_attribute: "cn",
|
||||||
|
groups_filter: "groups"
|
||||||
};
|
};
|
||||||
|
|
||||||
serverVariables.config = configuration;
|
|
||||||
|
|
||||||
serverVariables.ldapPasswordUpdater = {
|
|
||||||
updatePassword: Sinon.stub()
|
|
||||||
} as any;
|
|
||||||
|
|
||||||
res = ExpressMock.ResponseMock();
|
res = ExpressMock.ResponseMock();
|
||||||
AuthenticationSession.get(req as any)
|
AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
authSession.userid = "user";
|
authSession.userid = "user";
|
||||||
authSession.email = "user@example.com";
|
authSession.email = "user@example.com";
|
||||||
authSession.first_factor = true;
|
authSession.first_factor = true;
|
||||||
|
@ -72,19 +67,19 @@ describe("test reset password route", function () {
|
||||||
req.body = {};
|
req.body = {};
|
||||||
req.body.password = "new-password";
|
req.body.password = "new-password";
|
||||||
|
|
||||||
(serverVariables.ldapPasswordUpdater.updatePassword as sinon.SinonStub).returns(BluebirdPromise.resolve());
|
mocks.ldapPasswordUpdater.updatePasswordStub.returns(BluebirdPromise.resolve());
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.identity_check = {
|
authSession.identity_check = {
|
||||||
userid: "user",
|
userid: "user",
|
||||||
challenge: "reset-password"
|
challenge: "reset-password"
|
||||||
};
|
};
|
||||||
return PasswordResetFormPost.default(req as any, res as any);
|
return PasswordResetFormPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return AuthenticationSession.get(req as any);
|
return AuthenticationSessionHandler.get(req as any, vars.logger);
|
||||||
}).then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
}).then(function (_authSession) {
|
||||||
Assert.equal(res.status.getCall(0).args[0], 204);
|
Assert.equal(res.status.getCall(0).args[0], 204);
|
||||||
Assert.equal(_authSession.first_factor, false);
|
Assert.equal(_authSession.first_factor, false);
|
||||||
Assert.equal(_authSession.second_factor, false);
|
Assert.equal(_authSession.second_factor, false);
|
||||||
|
@ -93,13 +88,13 @@ describe("test reset password route", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should fail if identity_challenge does not exist", function () {
|
it("should fail if identity_challenge does not exist", function () {
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.identity_check = {
|
authSession.identity_check = {
|
||||||
userid: "user",
|
userid: "user",
|
||||||
challenge: undefined
|
challenge: undefined
|
||||||
};
|
};
|
||||||
return PasswordResetFormPost.default(req as any, res as any);
|
return PasswordResetFormPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert.equal(res.status.getCall(0).args[0], 200);
|
Assert.equal(res.status.getCall(0).args[0], 200);
|
||||||
|
@ -113,16 +108,16 @@ describe("test reset password route", function () {
|
||||||
req.body = {};
|
req.body = {};
|
||||||
req.body.password = "new-password";
|
req.body.password = "new-password";
|
||||||
|
|
||||||
(serverVariables.ldapPasswordUpdater.updatePassword as Sinon.SinonStub)
|
mocks.ldapPasswordUpdater.updatePasswordStub
|
||||||
.returns(BluebirdPromise.reject("Internal error with LDAP"));
|
.returns(BluebirdPromise.reject("Internal error with LDAP"));
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.identity_check = {
|
authSession.identity_check = {
|
||||||
challenge: "reset-password",
|
challenge: "reset-password",
|
||||||
userid: "user"
|
userid: "user"
|
||||||
};
|
};
|
||||||
return PasswordResetFormPost.default(req as any, res as any);
|
return PasswordResetFormPost.default(vars)(req as any, res as any);
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
Assert.equal(res.status.getCall(0).args[0], 200);
|
Assert.equal(res.status.getCall(0).args[0], 200);
|
||||||
Assert.deepEqual(res.send.getCall(0).args[0], {
|
Assert.deepEqual(res.send.getCall(0).args[0], {
|
||||||
|
|
|
@ -6,23 +6,30 @@ import AuthenticationSession = require("../../../../../src/lib/AuthenticationSes
|
||||||
import { UserDataStore } from "../../../../../src/lib/storage/UserDataStore";
|
import { UserDataStore } from "../../../../../src/lib/storage/UserDataStore";
|
||||||
import assert = require("assert");
|
import assert = require("assert");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
|
|
||||||
import ExpressMock = require("../../../../mocks/express");
|
import ExpressMock = require("../../../../mocks/express");
|
||||||
import ServerVariablesMock = require("../../../../mocks/ServerVariablesMock");
|
import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../mocks/ServerVariablesMockBuilder";
|
||||||
|
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
||||||
|
|
||||||
describe("test totp register", function () {
|
describe("test totp register", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
const registrationHandler: RegistrationHandler = new RegistrationHandler();
|
let mocks: ServerVariablesMock;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
const mocks = ServerVariablesMock.mock(req.app);
|
req.session = {
|
||||||
req.session = {};
|
auth: {
|
||||||
|
userid: "user",
|
||||||
AuthenticationSession.reset(req as any);
|
email: "user@example.com",
|
||||||
|
first_factor: true,
|
||||||
|
second_factor: false
|
||||||
|
}
|
||||||
|
};
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.headers.host = "localhost";
|
req.headers.host = "localhost";
|
||||||
|
|
||||||
|
@ -37,23 +44,15 @@ describe("test totp register", function () {
|
||||||
mocks.userDataStore.saveTOTPSecretStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.saveTOTPSecretStub.returns(BluebirdPromise.resolve({}));
|
||||||
|
|
||||||
res = ExpressMock.ResponseMock();
|
res = ExpressMock.ResponseMock();
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|
||||||
authSession = _authSession;
|
|
||||||
authSession.userid = "user";
|
|
||||||
authSession.email = "user@example.com";
|
|
||||||
authSession.first_factor = true;
|
|
||||||
authSession.second_factor = false;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("test totp registration check", test_registration_check);
|
describe("test totp registration check", test_registration_check);
|
||||||
|
|
||||||
function test_registration_check() {
|
function test_registration_check() {
|
||||||
it("should fail if first_factor has not been passed", function () {
|
it("should fail if first_factor has not been passed", function () {
|
||||||
authSession.first_factor = false;
|
req.session.auth.first_factor = false;
|
||||||
return registrationHandler.preValidationInit(req as any)
|
return new RegistrationHandler(vars.logger, vars.userDataStore, vars.totpHandler)
|
||||||
|
.preValidationInit(req as any)
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||||
.catch(function (err: Error) {
|
.catch(function (err: Error) {
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
|
@ -61,27 +60,30 @@ describe("test totp register", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should fail if userid is missing", function (done) {
|
it("should fail if userid is missing", function (done) {
|
||||||
authSession.first_factor = false;
|
req.session.auth.first_factor = false;
|
||||||
authSession.userid = undefined;
|
req.session.auth.userid = undefined;
|
||||||
|
|
||||||
registrationHandler.preValidationInit(req as any)
|
new RegistrationHandler(vars.logger, vars.userDataStore, vars.totpHandler)
|
||||||
|
.preValidationInit(req as any)
|
||||||
.catch(function (err: Error) {
|
.catch(function (err: Error) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should fail if email is missing", function (done) {
|
it("should fail if email is missing", function (done) {
|
||||||
authSession.first_factor = false;
|
req.session.auth.first_factor = false;
|
||||||
authSession.email = undefined;
|
req.session.auth.email = undefined;
|
||||||
|
|
||||||
registrationHandler.preValidationInit(req as any)
|
new RegistrationHandler(vars.logger, vars.userDataStore, vars.totpHandler)
|
||||||
|
.preValidationInit(req as any)
|
||||||
.catch(function (err: Error) {
|
.catch(function (err: Error) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should succeed if first factor passed, userid and email are provided", function (done) {
|
it("should succeed if first factor passed, userid and email are provided", function (done) {
|
||||||
registrationHandler.preValidationInit(req as any)
|
new RegistrationHandler(vars.logger, vars.userDataStore, vars.totpHandler)
|
||||||
|
.preValidationInit(req as any)
|
||||||
.then(function (identity: Identity) {
|
.then(function (identity: Identity) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,8 @@ import assert = require("assert");
|
||||||
import winston = require("winston");
|
import winston = require("winston");
|
||||||
|
|
||||||
import exceptions = require("../../../../../src/lib/Exceptions");
|
import exceptions = require("../../../../../src/lib/Exceptions");
|
||||||
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../../../../src/lib/AuthenticationSession");
|
||||||
|
import { AuthenticationSession } from "../../../../../types/AuthenticationSession";
|
||||||
import SignPost = require("../../../../../src/lib/routes/secondfactor/totp/sign/post");
|
import SignPost = require("../../../../../src/lib/routes/secondfactor/totp/sign/post");
|
||||||
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../moc
|
||||||
describe("test totp route", function () {
|
describe("test totp route", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let authSession: AuthenticationSession;
|
||||||
let vars: ServerVariables;
|
let vars: ServerVariables;
|
||||||
let mocks: ServerVariablesMock;
|
let mocks: ServerVariablesMock;
|
||||||
|
|
||||||
|
@ -38,7 +39,6 @@ describe("test totp route", function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
res = ExpressMock.ResponseMock();
|
res = ExpressMock.ResponseMock();
|
||||||
AuthenticationSession.reset(req as any);
|
|
||||||
|
|
||||||
const doc = {
|
const doc = {
|
||||||
userid: "user",
|
userid: "user",
|
||||||
|
@ -47,8 +47,8 @@ describe("test totp route", function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mocks.userDataStore.retrieveTOTPSecretStub.returns(BluebirdPromise.resolve(doc));
|
mocks.userDataStore.retrieveTOTPSecretStub.returns(BluebirdPromise.resolve(doc));
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (_authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
authSession.userid = "user";
|
authSession.userid = "user";
|
||||||
authSession.first_factor = true;
|
authSession.first_factor = true;
|
||||||
|
|
|
@ -9,19 +9,30 @@ import AuthenticationSession = require("../../../../../src/lib/AuthenticationSes
|
||||||
|
|
||||||
import ExpressMock = require("../../../../mocks/express");
|
import ExpressMock = require("../../../../mocks/express");
|
||||||
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
||||||
import ServerVariablesMock = require("../../../../mocks/ServerVariablesMock");
|
import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../mocks/ServerVariablesMockBuilder";
|
||||||
|
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
||||||
|
|
||||||
describe("test register handler", function () {
|
describe("test register handler", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let mocks: ServerVariablesMock;
|
||||||
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
req.app = {};
|
req.app = {};
|
||||||
const mocks = ServerVariablesMock.mock(req.app);
|
req.session = {
|
||||||
req.session = {};
|
auth: {
|
||||||
AuthenticationSession.reset(req as any);
|
userid: "user",
|
||||||
|
email: "user@example.com",
|
||||||
|
first_factor: true,
|
||||||
|
second_factor: false
|
||||||
|
}
|
||||||
|
};
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.headers.host = "localhost";
|
req.headers.host = "localhost";
|
||||||
|
|
||||||
|
@ -38,23 +49,14 @@ describe("test register handler", function () {
|
||||||
res.send = sinon.spy();
|
res.send = sinon.spy();
|
||||||
res.json = sinon.spy();
|
res.json = sinon.spy();
|
||||||
res.status = sinon.spy();
|
res.status = sinon.spy();
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|
||||||
authSession = _authSession;
|
|
||||||
authSession.userid = "user";
|
|
||||||
authSession.email = "user@example.com";
|
|
||||||
authSession.first_factor = true;
|
|
||||||
authSession.second_factor = false;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("test u2f registration check", test_registration_check);
|
describe("test u2f registration check", test_registration_check);
|
||||||
|
|
||||||
function test_registration_check() {
|
function test_registration_check() {
|
||||||
it("should fail if first_factor has not been passed", function () {
|
it("should fail if first_factor has not been passed", function () {
|
||||||
authSession.first_factor = false;
|
req.session.auth.first_factor = false;
|
||||||
return new RegistrationHandler().preValidationInit(req as any)
|
return new RegistrationHandler(vars.logger).preValidationInit(req as any)
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||||
.catch(function (err: Error) {
|
.catch(function (err: Error) {
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
|
@ -62,27 +64,27 @@ describe("test register handler", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should fail if userid is missing", function (done) {
|
it("should fail if userid is missing", function (done) {
|
||||||
authSession.first_factor = false;
|
req.session.auth.first_factor = false;
|
||||||
authSession.userid = undefined;
|
req.session.auth.userid = undefined;
|
||||||
|
|
||||||
new RegistrationHandler().preValidationInit(req as any)
|
new RegistrationHandler(vars.logger).preValidationInit(req as any)
|
||||||
.catch(function (err: Error) {
|
.catch(function (err: Error) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should fail if email is missing", function (done) {
|
it("should fail if email is missing", function (done) {
|
||||||
authSession.first_factor = false;
|
req.session.auth.first_factor = false;
|
||||||
authSession.email = undefined;
|
req.session.auth.email = undefined;
|
||||||
|
|
||||||
new RegistrationHandler().preValidationInit(req as any)
|
new RegistrationHandler(vars.logger).preValidationInit(req as any)
|
||||||
.catch(function (err: Error) {
|
.catch(function (err: Error) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should succeed if first factor passed, userid and email are provided", function (done) {
|
it("should succeed if first factor passed, userid and email are provided", function (done) {
|
||||||
new RegistrationHandler().preValidationInit(req as any)
|
new RegistrationHandler(vars.logger).preValidationInit(req as any)
|
||||||
.then(function (identity: Identity) {
|
.then(function (identity: Identity) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,28 +4,39 @@ import BluebirdPromise = require("bluebird");
|
||||||
import assert = require("assert");
|
import assert = require("assert");
|
||||||
import U2FRegisterPost = require("../../../../../src/lib/routes/secondfactor/u2f/register/post");
|
import U2FRegisterPost = require("../../../../../src/lib/routes/secondfactor/u2f/register/post");
|
||||||
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
||||||
import { ServerVariablesHandler } from "../../../../../src/lib/ServerVariablesHandler";
|
|
||||||
import winston = require("winston");
|
|
||||||
|
|
||||||
import ExpressMock = require("../../../../mocks/express");
|
import ExpressMock = require("../../../../mocks/express");
|
||||||
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
||||||
import U2FMock = require("../../../../mocks/u2f");
|
import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../mocks/ServerVariablesMockBuilder";
|
||||||
import ServerVariablesMock = require("../../../../mocks/ServerVariablesMock");
|
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
||||||
import U2f = require("u2f");
|
|
||||||
|
|
||||||
describe("test u2f routes: register", function () {
|
describe("test u2f routes: register", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
let mocks: ServerVariablesMock;
|
||||||
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
req.app = {};
|
req.app = {};
|
||||||
mocks = ServerVariablesMock.mock(req.app);
|
req.session = {
|
||||||
req.session = {};
|
auth: {
|
||||||
|
userid: "user",
|
||||||
|
first_factor: true,
|
||||||
|
second_factor: false,
|
||||||
|
identity_check: {
|
||||||
|
challenge: "u2f-register",
|
||||||
|
userid: "user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.headers.host = "localhost";
|
req.headers.host = "localhost";
|
||||||
|
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
inMemoryOnly: true
|
inMemoryOnly: true
|
||||||
};
|
};
|
||||||
|
@ -37,18 +48,6 @@ describe("test u2f routes: register", function () {
|
||||||
res.send = sinon.spy();
|
res.send = sinon.spy();
|
||||||
res.json = sinon.spy();
|
res.json = sinon.spy();
|
||||||
res.status = sinon.spy();
|
res.status = sinon.spy();
|
||||||
|
|
||||||
AuthenticationSession.reset(req as any);
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
|
||||||
authSession.userid = "user";
|
|
||||||
authSession.first_factor = true;
|
|
||||||
authSession.second_factor = false;
|
|
||||||
authSession.identity_check = {
|
|
||||||
challenge: "u2f-register",
|
|
||||||
userid: "user"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("test registration", test_registration);
|
describe("test registration", test_registration);
|
||||||
|
@ -61,11 +60,9 @@ describe("test u2f routes: register", function () {
|
||||||
publicKey: "pbk",
|
publicKey: "pbk",
|
||||||
certificate: "cert"
|
certificate: "cert"
|
||||||
};
|
};
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
mocks.u2f.checkRegistrationStub.returns(BluebirdPromise.resolve(expectedStatus));
|
||||||
u2f_mock.checkRegistration.returns(BluebirdPromise.resolve(expectedStatus));
|
|
||||||
mocks.u2f = u2f_mock;
|
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSession.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.register_request = {
|
authSession.register_request = {
|
||||||
appId: "app",
|
appId: "app",
|
||||||
|
@ -73,10 +70,10 @@ describe("test u2f routes: register", function () {
|
||||||
keyHandle: "key",
|
keyHandle: "key",
|
||||||
version: "U2F_V2"
|
version: "U2F_V2"
|
||||||
};
|
};
|
||||||
return U2FRegisterPost.default(req as any, res as any);
|
return U2FRegisterPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return AuthenticationSession.get(req as any);
|
return AuthenticationSession.get(req as any, vars.logger);
|
||||||
})
|
})
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
assert.equal("user", mocks.userDataStore.saveU2FRegistrationStub.getCall(0).args[0]);
|
assert.equal("user", mocks.userDataStore.saveU2FRegistrationStub.getCall(0).args[0]);
|
||||||
|
@ -85,12 +82,9 @@ describe("test u2f routes: register", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return error message on finishRegistration error", function () {
|
it("should return error message on finishRegistration error", function () {
|
||||||
const user_key_container = {};
|
mocks.u2f.checkRegistrationStub.returns({ errorCode: 500 });
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
|
||||||
u2f_mock.checkRegistration.returns({ errorCode: 500 });
|
|
||||||
mocks.u2f = u2f_mock;
|
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSession.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.register_request = {
|
authSession.register_request = {
|
||||||
appId: "app",
|
appId: "app",
|
||||||
|
@ -99,7 +93,7 @@ describe("test u2f routes: register", function () {
|
||||||
version: "U2F_V2"
|
version: "U2F_V2"
|
||||||
};
|
};
|
||||||
|
|
||||||
return U2FRegisterPost.default(req as any, res as any);
|
return U2FRegisterPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
|
@ -112,15 +106,11 @@ describe("test u2f routes: register", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return error message when register_request is not provided", function () {
|
it("should return error message when register_request is not provided", function () {
|
||||||
const user_key_container = {};
|
mocks.u2f.checkRegistrationStub.returns(BluebirdPromise.resolve());
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
return AuthenticationSession.get(req as any, vars.logger)
|
||||||
u2f_mock.checkRegistration.returns(BluebirdPromise.resolve());
|
|
||||||
|
|
||||||
mocks.u2f = u2f_mock;
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.register_request = undefined;
|
authSession.register_request = undefined;
|
||||||
return U2FRegisterPost.default(req as any, res as any);
|
return U2FRegisterPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
|
@ -133,15 +123,11 @@ describe("test u2f routes: register", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return error message when no auth request has been initiated", function () {
|
it("should return error message when no auth request has been initiated", function () {
|
||||||
const user_key_container = {};
|
mocks.u2f.checkRegistrationStub.returns(BluebirdPromise.resolve());
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
return AuthenticationSession.get(req as any, vars.logger)
|
||||||
u2f_mock.checkRegistration.returns(BluebirdPromise.resolve());
|
|
||||||
|
|
||||||
mocks.u2f = u2f_mock;
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.register_request = undefined;
|
authSession.register_request = undefined;
|
||||||
return U2FRegisterPost.default(req as any, res as any);
|
return U2FRegisterPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
|
@ -154,10 +140,10 @@ describe("test u2f routes: register", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return error message when identity has not been verified", function () {
|
it("should return error message when identity has not been verified", function () {
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSession.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.identity_check = undefined;
|
authSession.identity_check = undefined;
|
||||||
return U2FRegisterPost.default(req as any, res as any);
|
return U2FRegisterPost.default(vars)(req as any, res as any);
|
||||||
})
|
})
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
|
|
|
@ -4,36 +4,42 @@ import BluebirdPromise = require("bluebird");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import U2FRegisterRequestGet = require("../../../../../src/lib/routes/secondfactor/u2f/register_request/get");
|
import U2FRegisterRequestGet = require("../../../../../src/lib/routes/secondfactor/u2f/register_request/get");
|
||||||
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
||||||
import { ServerVariablesHandler } from "../../../../../src/lib/ServerVariablesHandler";
|
|
||||||
import winston = require("winston");
|
|
||||||
|
|
||||||
import ExpressMock = require("../../../../mocks/express");
|
import ExpressMock = require("../../../../mocks/express");
|
||||||
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
||||||
import U2FMock = require("../../../../mocks/u2f");
|
import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../mocks/ServerVariablesMockBuilder";
|
||||||
import ServerVariablesMock = require("../../../../mocks/ServerVariablesMock");
|
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
||||||
import U2f = require("u2f");
|
|
||||||
|
|
||||||
describe("test u2f routes: register_request", function () {
|
describe("test u2f routes: register_request", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
let mocks: ServerVariablesMock;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
req.app = {};
|
req.app = {};
|
||||||
mocks = ServerVariablesMock.mock(req.app);
|
req.session = {
|
||||||
req.session = {};
|
auth: {
|
||||||
AuthenticationSession.reset(req as any);
|
userid: "user",
|
||||||
|
first_factor: true,
|
||||||
|
second_factor: false,
|
||||||
|
identity_check: {
|
||||||
|
challenge: "u2f-register",
|
||||||
|
userid: "user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.headers.host = "localhost";
|
req.headers.host = "localhost";
|
||||||
|
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
inMemoryOnly: true
|
inMemoryOnly: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
mocks.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||||
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||||
|
|
||||||
|
@ -41,18 +47,6 @@ describe("test u2f routes: register_request", function () {
|
||||||
res.send = sinon.spy();
|
res.send = sinon.spy();
|
||||||
res.json = sinon.spy();
|
res.json = sinon.spy();
|
||||||
res.status = sinon.spy();
|
res.status = sinon.spy();
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|
||||||
authSession = _authSession;
|
|
||||||
authSession.userid = "user";
|
|
||||||
authSession.first_factor = true;
|
|
||||||
authSession.second_factor = false;
|
|
||||||
authSession.identity_check = {
|
|
||||||
challenge: "u2f-register",
|
|
||||||
userid: "user"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("test registration request", () => {
|
describe("test registration request", () => {
|
||||||
|
@ -60,12 +54,8 @@ describe("test u2f routes: register_request", function () {
|
||||||
const expectedRequest = {
|
const expectedRequest = {
|
||||||
test: "abc"
|
test: "abc"
|
||||||
};
|
};
|
||||||
const user_key_container = {};
|
mocks.u2f.requestStub.returns(BluebirdPromise.resolve(expectedRequest));
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
return U2FRegisterRequestGet.default(vars)(req as any, res as any)
|
||||||
u2f_mock.request.returns(BluebirdPromise.resolve(expectedRequest));
|
|
||||||
|
|
||||||
mocks.u2f = u2f_mock;
|
|
||||||
return U2FRegisterRequestGet.default(req as any, res as any)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert.deepEqual(expectedRequest, res.json.getCall(0).args[0]);
|
Assert.deepEqual(expectedRequest, res.json.getCall(0).args[0]);
|
||||||
});
|
});
|
||||||
|
@ -74,22 +64,19 @@ describe("test u2f routes: register_request", function () {
|
||||||
it("should return internal error on registration request", function () {
|
it("should return internal error on registration request", function () {
|
||||||
res.send = sinon.spy();
|
res.send = sinon.spy();
|
||||||
const user_key_container = {};
|
const user_key_container = {};
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
mocks.u2f.requestStub.returns(BluebirdPromise.reject("Internal error"));
|
||||||
u2f_mock.request.returns(BluebirdPromise.reject("Internal error"));
|
return U2FRegisterRequestGet.default(vars)(req as any, res as any)
|
||||||
|
.then(function () {
|
||||||
mocks.u2f = u2f_mock;
|
Assert.equal(res.status.getCall(0).args[0], 200);
|
||||||
return U2FRegisterRequestGet.default(req as any, res as any)
|
Assert.deepEqual(res.send.getCall(0).args[0], {
|
||||||
.then(function() {
|
error: "Operation failed."
|
||||||
Assert.equal(res.status.getCall(0).args[0], 200);
|
});
|
||||||
Assert.deepEqual(res.send.getCall(0).args[0], {
|
|
||||||
error: "Operation failed."
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return forbidden if identity has not been verified", function () {
|
it("should return forbidden if identity has not been verified", function () {
|
||||||
authSession.identity_check = undefined;
|
req.session.auth.identity_check = undefined;
|
||||||
return U2FRegisterRequestGet.default(req as any, res as any)
|
return U2FRegisterRequestGet.default(vars)(req as any, res as any)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert.equal(403, res.status.getCall(0).args[0]);
|
Assert.equal(403, res.status.getCall(0).args[0]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,27 +4,39 @@ import BluebirdPromise = require("bluebird");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import U2FSignPost = require("../../../../../src/lib/routes/secondfactor/u2f/sign/post");
|
import U2FSignPost = require("../../../../../src/lib/routes/secondfactor/u2f/sign/post");
|
||||||
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
||||||
import { ServerVariablesHandler } from "../../../../../src/lib/ServerVariablesHandler";
|
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
||||||
import winston = require("winston");
|
import winston = require("winston");
|
||||||
|
|
||||||
|
import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../mocks/ServerVariablesMockBuilder";
|
||||||
import ExpressMock = require("../../../../mocks/express");
|
import ExpressMock = require("../../../../mocks/express");
|
||||||
import ServerVariablesMock = require("../../../../mocks/ServerVariablesMock");
|
|
||||||
import U2FMock = require("../../../../mocks/u2f");
|
import U2FMock = require("../../../../mocks/u2f");
|
||||||
import U2f = require("u2f");
|
import U2f = require("u2f");
|
||||||
|
|
||||||
describe("test u2f routes: sign", function () {
|
describe("test u2f routes: sign", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let mocks: ServerVariablesMock;
|
||||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
req.app = {};
|
req.app = {};
|
||||||
|
|
||||||
mocks = ServerVariablesMock.mock(req.app);
|
const s = ServerVariablesMockBuilder.build();
|
||||||
req.session = {};
|
mocks = s.mocks;
|
||||||
AuthenticationSession.reset(req as any);
|
vars = s.variables;
|
||||||
|
|
||||||
|
req.session = {
|
||||||
|
auth: {
|
||||||
|
userid: "user",
|
||||||
|
first_factor: true,
|
||||||
|
second_factor: false,
|
||||||
|
identity_check: {
|
||||||
|
challenge: "u2f-register",
|
||||||
|
userid: "user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.headers.host = "localhost";
|
req.headers.host = "localhost";
|
||||||
|
|
||||||
|
@ -36,18 +48,6 @@ describe("test u2f routes: sign", function () {
|
||||||
res.send = sinon.spy();
|
res.send = sinon.spy();
|
||||||
res.json = sinon.spy();
|
res.json = sinon.spy();
|
||||||
res.status = sinon.spy();
|
res.status = sinon.spy();
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|
||||||
authSession = _authSession;
|
|
||||||
authSession.userid = "user";
|
|
||||||
authSession.first_factor = true;
|
|
||||||
authSession.second_factor = false;
|
|
||||||
authSession.identity_check = {
|
|
||||||
challenge: "u2f-register",
|
|
||||||
userid: "user"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return status code 204", function () {
|
it("should return status code 204", function () {
|
||||||
|
@ -56,8 +56,7 @@ describe("test u2f routes: sign", function () {
|
||||||
publicKey: "pbk",
|
publicKey: "pbk",
|
||||||
certificate: "cert"
|
certificate: "cert"
|
||||||
};
|
};
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
mocks.u2f.checkSignatureStub.returns(expectedStatus);
|
||||||
u2f_mock.checkSignature.returns(expectedStatus);
|
|
||||||
|
|
||||||
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({
|
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({
|
||||||
registration: {
|
registration: {
|
||||||
|
@ -65,16 +64,15 @@ describe("test u2f routes: sign", function () {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
authSession.sign_request = {
|
req.session.auth.sign_request = {
|
||||||
appId: "app",
|
appId: "app",
|
||||||
challenge: "challenge",
|
challenge: "challenge",
|
||||||
keyHandle: "key",
|
keyHandle: "key",
|
||||||
version: "U2F_V2"
|
version: "U2F_V2"
|
||||||
};
|
};
|
||||||
mocks.u2f = u2f_mock;
|
return U2FSignPost.default(vars)(req as any, res as any)
|
||||||
return U2FSignPost.default(req as any, res as any)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert(authSession.second_factor);
|
Assert(req.session.auth.second_factor);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -84,18 +82,15 @@ describe("test u2f routes: sign", function () {
|
||||||
publicKey: "PUBKEY"
|
publicKey: "PUBKEY"
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
mocks.u2f.checkSignatureStub.returns({ errorCode: 500 });
|
||||||
|
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
req.session.auth.sign_request = {
|
||||||
u2f_mock.checkSignature.returns({ errorCode: 500 });
|
|
||||||
|
|
||||||
authSession.sign_request = {
|
|
||||||
appId: "app",
|
appId: "app",
|
||||||
challenge: "challenge",
|
challenge: "challenge",
|
||||||
keyHandle: "key",
|
keyHandle: "key",
|
||||||
version: "U2F_V2"
|
version: "U2F_V2"
|
||||||
};
|
};
|
||||||
mocks.u2f = u2f_mock;
|
return U2FSignPost.default(vars)(req as any, res as any)
|
||||||
return U2FSignPost.default(req as any, res as any)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert.equal(res.status.getCall(0).args[0], 200);
|
Assert.equal(res.status.getCall(0).args[0], 200);
|
||||||
Assert.deepEqual(res.send.getCall(0).args[0],
|
Assert.deepEqual(res.send.getCall(0).args[0],
|
||||||
|
|
|
@ -3,37 +3,44 @@ import sinon = require("sinon");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import assert = require("assert");
|
import assert = require("assert");
|
||||||
import U2FSignRequestGet = require("../../../../../src/lib/routes/secondfactor/u2f/sign_request/get");
|
import U2FSignRequestGet = require("../../../../../src/lib/routes/secondfactor/u2f/sign_request/get");
|
||||||
import AuthenticationSession = require("../../../../../src/lib/AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../../../../src/lib/AuthenticationSession");
|
||||||
import { ServerVariablesHandler } from "../../../../../src/lib/ServerVariablesHandler";
|
import { AuthenticationSession } from "../../../../../types/AuthenticationSession";
|
||||||
import winston = require("winston");
|
|
||||||
|
|
||||||
import ExpressMock = require("../../../../mocks/express");
|
import ExpressMock = require("../../../../mocks/express");
|
||||||
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub";
|
||||||
import ServerVariablesMock = require("../../../../mocks/ServerVariablesMock");
|
|
||||||
import U2FMock = require("../../../../mocks/u2f");
|
import U2FMock = require("../../../../mocks/u2f");
|
||||||
import U2f = require("u2f");
|
import U2f = require("u2f");
|
||||||
|
import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../mocks/ServerVariablesMockBuilder";
|
||||||
|
import { ServerVariables } from "../../../../../src/lib/ServerVariables";
|
||||||
|
|
||||||
import { SignMessage } from "../../../../../../shared/SignMessage";
|
import { SignMessage } from "../../../../../../shared/SignMessage";
|
||||||
|
|
||||||
describe("test u2f routes: sign_request", function () {
|
describe("test u2f routes: sign_request", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
let mocks: ServerVariablesMock;
|
||||||
let authSession: AuthenticationSession.AuthenticationSession;
|
let vars: ServerVariables;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
req.app = {};
|
req.app = {};
|
||||||
|
req.session = {
|
||||||
mocks = ServerVariablesMock.mock(req.app);
|
auth: {
|
||||||
|
userid: "user",
|
||||||
req.session = {};
|
first_factor: true,
|
||||||
|
second_factor: false,
|
||||||
AuthenticationSession.reset(req as any);
|
identity_check: {
|
||||||
|
challenge: "u2f-register",
|
||||||
|
userid: "user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.headers.host = "localhost";
|
req.headers.host = "localhost";
|
||||||
|
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
mocks = s.mocks;
|
||||||
|
vars = s.variables;
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
inMemoryOnly: true
|
inMemoryOnly: true
|
||||||
};
|
};
|
||||||
|
@ -42,18 +49,6 @@ describe("test u2f routes: sign_request", function () {
|
||||||
res.send = sinon.spy();
|
res.send = sinon.spy();
|
||||||
res.json = sinon.spy();
|
res.json = sinon.spy();
|
||||||
res.status = sinon.spy();
|
res.status = sinon.spy();
|
||||||
|
|
||||||
return AuthenticationSession.get(req as any)
|
|
||||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
|
||||||
authSession = _authSession;
|
|
||||||
authSession.userid = "user";
|
|
||||||
authSession.first_factor = true;
|
|
||||||
authSession.second_factor = false;
|
|
||||||
authSession.identity_check = {
|
|
||||||
challenge: "u2f-register",
|
|
||||||
userid: "user"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should send back the sign request and save it in the session", function () {
|
it("should send back the sign request and save it in the session", function () {
|
||||||
|
@ -63,9 +58,7 @@ describe("test u2f routes: sign_request", function () {
|
||||||
certificate: "Certificate",
|
certificate: "Certificate",
|
||||||
successful: true
|
successful: true
|
||||||
};
|
};
|
||||||
const u2f_mock = U2FMock.U2FMock();
|
mocks.u2f.requestStub.returns(expectedRequest);
|
||||||
u2f_mock.request.returns(expectedRequest);
|
|
||||||
|
|
||||||
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({
|
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({
|
||||||
registration: {
|
registration: {
|
||||||
publicKey: "PUBKEY",
|
publicKey: "PUBKEY",
|
||||||
|
@ -73,10 +66,9 @@ describe("test u2f routes: sign_request", function () {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
mocks.u2f = u2f_mock;
|
return U2FSignRequestGet.default(vars)(req as any, res as any)
|
||||||
return U2FSignRequestGet.default(req as any, res as any)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
assert.deepEqual(expectedRequest, authSession.sign_request);
|
assert.deepEqual(expectedRequest, req.session.auth.sign_request);
|
||||||
assert.deepEqual(expectedRequest, res.json.getCall(0).args[0].request);
|
assert.deepEqual(expectedRequest, res.json.getCall(0).args[0].request);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import VerifyGet = require("../../../src/lib/routes/verify/get");
|
import VerifyGet = require("../../../src/lib/routes/verify/get");
|
||||||
import AuthenticationSession = require("../../../src/lib/AuthenticationSession");
|
import AuthenticationSessionHandler = require("../../../src/lib/AuthenticationSession");
|
||||||
|
import { AuthenticationSession } from "../../../types/AuthenticationSession";
|
||||||
import { AuthenticationMethodCalculator } from "../../../src/lib/AuthenticationMethodCalculator";
|
import { AuthenticationMethodCalculator } from "../../../src/lib/AuthenticationMethodCalculator";
|
||||||
import { AuthenticationMethodsConfiguration } from "../../../src/lib/configuration/Configuration";
|
import { AuthenticationMethodsConfiguration } from "../../../src/lib/configuration/Configuration";
|
||||||
import Sinon = require("sinon");
|
import Sinon = require("sinon");
|
||||||
|
@ -28,7 +29,7 @@ describe("test /verify endpoint", function () {
|
||||||
req.app = {
|
req.app = {
|
||||||
get: Sinon.stub().returns({ logger: winston })
|
get: Sinon.stub().returns({ logger: winston })
|
||||||
};
|
};
|
||||||
AuthenticationSession.reset(req as any);
|
AuthenticationSessionHandler.reset(req as any);
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.headers.host = "secret.example.com";
|
req.headers.host = "secret.example.com";
|
||||||
const s = ServerVariablesMockBuilder.build();
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
@ -39,9 +40,9 @@ describe("test /verify endpoint", function () {
|
||||||
it("should be already authenticated", function () {
|
it("should be already authenticated", function () {
|
||||||
req.session = {};
|
req.session = {};
|
||||||
mocks.accessController.isAccessAllowedMock.returns(true);
|
mocks.accessController.isAccessAllowedMock.returns(true);
|
||||||
AuthenticationSession.reset(req as any);
|
AuthenticationSessionHandler.reset(req as any);
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
authSession.first_factor = true;
|
authSession.first_factor = true;
|
||||||
authSession.second_factor = true;
|
authSession.second_factor = true;
|
||||||
authSession.userid = "myuser";
|
authSession.userid = "myuser";
|
||||||
|
@ -55,8 +56,8 @@ describe("test /verify endpoint", function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function test_session(_authSession: AuthenticationSession.AuthenticationSession, status_code: number) {
|
function test_session(_authSession: AuthenticationSession, status_code: number) {
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession = _authSession;
|
authSession = _authSession;
|
||||||
return VerifyGet.default(vars)(req as express.Request, res as any);
|
return VerifyGet.default(vars)(req as express.Request, res as any);
|
||||||
|
@ -66,15 +67,15 @@ describe("test /verify endpoint", function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_non_authenticated_401(authSession: AuthenticationSession.AuthenticationSession) {
|
function test_non_authenticated_401(authSession: AuthenticationSession) {
|
||||||
return test_session(authSession, 401);
|
return test_session(authSession, 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_unauthorized_403(authSession: AuthenticationSession.AuthenticationSession) {
|
function test_unauthorized_403(authSession: AuthenticationSession) {
|
||||||
return test_session(authSession, 403);
|
return test_session(authSession, 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_authorized(authSession: AuthenticationSession.AuthenticationSession) {
|
function test_authorized(authSession: AuthenticationSession) {
|
||||||
return test_session(authSession, 204);
|
return test_session(authSession, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ describe("test /verify endpoint", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not be authenticated when domain is not allowed for user", function () {
|
it("should not be authenticated when domain is not allowed for user", function () {
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.first_factor = true;
|
authSession.first_factor = true;
|
||||||
authSession.second_factor = true;
|
authSession.second_factor = true;
|
||||||
|
@ -167,7 +168,7 @@ describe("test /verify endpoint", function () {
|
||||||
|
|
||||||
it("should be authenticated when first factor is validated and second factor is not", function () {
|
it("should be authenticated when first factor is validated and second factor is not", function () {
|
||||||
mocks.accessController.isAccessAllowedMock.returns(true);
|
mocks.accessController.isAccessAllowedMock.returns(true);
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.first_factor = true;
|
authSession.first_factor = true;
|
||||||
authSession.userid = "user1";
|
authSession.userid = "user1";
|
||||||
|
@ -181,7 +182,7 @@ describe("test /verify endpoint", function () {
|
||||||
|
|
||||||
it("should be rejected with 401 when first factor is not validated", function () {
|
it("should be rejected with 401 when first factor is not validated", function () {
|
||||||
mocks.accessController.isAccessAllowedMock.returns(true);
|
mocks.accessController.isAccessAllowedMock.returns(true);
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
authSession.first_factor = false;
|
authSession.first_factor = false;
|
||||||
return VerifyGet.default(vars)(req as express.Request, res as any);
|
return VerifyGet.default(vars)(req as express.Request, res as any);
|
||||||
|
@ -197,9 +198,9 @@ describe("test /verify endpoint", function () {
|
||||||
mocks.config.session.inactivity = 200000;
|
mocks.config.session.inactivity = 200000;
|
||||||
mocks.accessController.isAccessAllowedMock.returns(true);
|
mocks.accessController.isAccessAllowedMock.returns(true);
|
||||||
const currentTime = new Date().getTime() - 1000;
|
const currentTime = new Date().getTime() - 1000;
|
||||||
AuthenticationSession.reset(req as any);
|
AuthenticationSessionHandler.reset(req as any);
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
authSession.first_factor = true;
|
authSession.first_factor = true;
|
||||||
authSession.second_factor = true;
|
authSession.second_factor = true;
|
||||||
authSession.userid = "myuser";
|
authSession.userid = "myuser";
|
||||||
|
@ -208,7 +209,7 @@ describe("test /verify endpoint", function () {
|
||||||
return VerifyGet.default(vars)(req as express.Request, res as any);
|
return VerifyGet.default(vars)(req as express.Request, res as any);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return AuthenticationSession.get(req as any);
|
return AuthenticationSessionHandler.get(req as any, vars.logger);
|
||||||
})
|
})
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
Assert(authSession.last_activity_datetime > currentTime);
|
Assert(authSession.last_activity_datetime > currentTime);
|
||||||
|
@ -219,9 +220,9 @@ describe("test /verify endpoint", function () {
|
||||||
mocks.config.session.inactivity = 1;
|
mocks.config.session.inactivity = 1;
|
||||||
mocks.accessController.isAccessAllowedMock.returns(true);
|
mocks.accessController.isAccessAllowedMock.returns(true);
|
||||||
const currentTime = new Date().getTime() - 1000;
|
const currentTime = new Date().getTime() - 1000;
|
||||||
AuthenticationSession.reset(req as any);
|
AuthenticationSessionHandler.reset(req as any);
|
||||||
return AuthenticationSession.get(req as any)
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
||||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
.then(function (authSession) {
|
||||||
authSession.first_factor = true;
|
authSession.first_factor = true;
|
||||||
authSession.second_factor = true;
|
authSession.second_factor = true;
|
||||||
authSession.userid = "myuser";
|
authSession.userid = "myuser";
|
||||||
|
@ -230,7 +231,7 @@ describe("test /verify endpoint", function () {
|
||||||
return VerifyGet.default(vars)(req as express.Request, res as any);
|
return VerifyGet.default(vars)(req as express.Request, res as any);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return AuthenticationSession.get(req as any);
|
return AuthenticationSessionHandler.get(req as any, vars.logger);
|
||||||
})
|
})
|
||||||
.then(function (authSession) {
|
.then(function (authSession) {
|
||||||
Assert.equal(authSession.first_factor, false);
|
Assert.equal(authSession.first_factor, false);
|
||||||
|
|
17
server/types/AuthenticationSession.ts
Normal file
17
server/types/AuthenticationSession.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import U2f = require("u2f");
|
||||||
|
|
||||||
|
export interface AuthenticationSession {
|
||||||
|
userid: string;
|
||||||
|
first_factor: boolean;
|
||||||
|
second_factor: boolean;
|
||||||
|
last_activity_datetime: number;
|
||||||
|
identity_check?: {
|
||||||
|
challenge: string;
|
||||||
|
userid: string;
|
||||||
|
};
|
||||||
|
register_request?: U2f.Request;
|
||||||
|
sign_request?: U2f.Request;
|
||||||
|
email: string;
|
||||||
|
groups: string[];
|
||||||
|
redirect?: string;
|
||||||
|
}
|
4
shared/ErrorMessage.ts
Normal file
4
shared/ErrorMessage.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
export interface ErrorMessage {
|
||||||
|
error: string;
|
||||||
|
}
|
4
shared/RedirectionMessage.ts
Normal file
4
shared/RedirectionMessage.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
export interface RedirectionMessage {
|
||||||
|
redirect: string;
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ Feature: User is redirected when factors are already validated
|
||||||
Then I'm redirected to "https://auth.test.local:8080/secondfactor?redirect=https%3A%2F%2Fpublic.test.local%3A8080%2Fsecret.html"
|
Then I'm redirected to "https://auth.test.local:8080/secondfactor?redirect=https%3A%2F%2Fpublic.test.local%3A8080%2Fsecret.html"
|
||||||
|
|
||||||
@need-registered-user-john
|
@need-registered-user-john
|
||||||
Scenario: User who has validated second factor and access auth portal should be redirected to "Already logged in page"
|
Scenario: User who has validated second factor and access auth portal should be redirected to "Already logged in page" and redirected to default URL declared in configuration
|
||||||
When I visit "https://public.test.local:8080/secret.html"
|
When I visit "https://public.test.local:8080/secret.html"
|
||||||
And I'm redirected to "https://auth.test.local:8080/?redirect=https%3A%2F%2Fpublic.test.local%3A8080%2Fsecret.html"
|
And I'm redirected to "https://auth.test.local:8080/?redirect=https%3A%2F%2Fpublic.test.local%3A8080%2Fsecret.html"
|
||||||
And I login with user "john" and password "password"
|
And I login with user "john" and password "password"
|
||||||
|
@ -19,6 +19,8 @@ Feature: User is redirected when factors are already validated
|
||||||
And I'm redirected to "https://public.test.local:8080/secret.html"
|
And I'm redirected to "https://public.test.local:8080/secret.html"
|
||||||
And I visit "https://auth.test.local:8080"
|
And I visit "https://auth.test.local:8080"
|
||||||
Then I'm redirected to "https://auth.test.local:8080/loggedin"
|
Then I'm redirected to "https://auth.test.local:8080/loggedin"
|
||||||
|
And I sleep for 5 seconds
|
||||||
|
And I'm redirected to "https://home.test.local:8080/"
|
||||||
|
|
||||||
@need-registered-user-john
|
@need-registered-user-john
|
||||||
Scenario: User who has validated second factor and access auth portal with rediction param should be redirected to that URL
|
Scenario: User who has validated second factor and access auth portal with rediction param should be redirected to that URL
|
||||||
|
|
|
@ -41,3 +41,11 @@ Feature: User is correctly redirected
|
||||||
And I use "Sec0" as TOTP token handle
|
And I use "Sec0" as TOTP token handle
|
||||||
And I click on "TOTP"
|
And I click on "TOTP"
|
||||||
Then I'm redirected to "https://public.test.local:8080/secret.html"
|
Then I'm redirected to "https://public.test.local:8080/secret.html"
|
||||||
|
|
||||||
|
@need-registered-user-john
|
||||||
|
Scenario: User is redirected to default URL defined in configuration when authentication is successful
|
||||||
|
When I visit "https://auth.test.local:8080"
|
||||||
|
And I login with user "john" and password "password"
|
||||||
|
And I use "REGISTERED" as TOTP token handle
|
||||||
|
And I click on "TOTP"
|
||||||
|
Then I'm redirected to "https://home.test.local:8080/"
|
Loading…
Reference in New Issue
Block a user