Merge pull request #89 from clems4ever/redis-connection-issue-logs
Make failing connection to redis more clear in the logspull/92/head
commit
ae5b647d23
|
@ -112,7 +112,7 @@ module.exports = function (grunt) {
|
|||
}
|
||||
},
|
||||
client: {
|
||||
files: ['src/client/**/*.ts', 'test/client/**/*.ts'],
|
||||
files: ['src/client/**/*.ts'],
|
||||
tasks: ['build-dev'],
|
||||
options: {
|
||||
interrupt: true,
|
||||
|
@ -120,7 +120,7 @@ module.exports = function (grunt) {
|
|||
}
|
||||
},
|
||||
server: {
|
||||
files: ['src/server/**/*.ts', 'test/server/**/*.ts'],
|
||||
files: ['src/server/**/*.ts'],
|
||||
tasks: ['build-dev', 'run:docker-restart', 'run:make-dev-views' ],
|
||||
options: {
|
||||
interrupt: true,
|
||||
|
|
|
@ -2,5 +2,7 @@ version: '2'
|
|||
services:
|
||||
mongo:
|
||||
image: mongo:3.4
|
||||
ports:
|
||||
- "27017:27017"
|
||||
networks:
|
||||
- example-network
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"object-path": "^0.11.3",
|
||||
"pug": "^2.0.0-rc.2",
|
||||
"randomstring": "^1.1.5",
|
||||
"redis": "^2.8.0",
|
||||
"speakeasy": "^2.0.0",
|
||||
"u2f": "^0.1.2",
|
||||
"winston": "^2.3.1",
|
||||
|
@ -63,6 +64,7 @@
|
|||
"@types/proxyquire": "^1.3.27",
|
||||
"@types/query-string": "^4.3.1",
|
||||
"@types/randomstring": "^1.1.5",
|
||||
"@types/redis": "^2.6.0",
|
||||
"@types/request": "0.0.46",
|
||||
"@types/selenium-webdriver": "^3.0.4",
|
||||
"@types/sinon": "^2.2.1",
|
||||
|
|
|
@ -11,52 +11,52 @@ import { QueryParametersRetriever } from "../QueryParametersRetriever";
|
|||
|
||||
|
||||
export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi) {
|
||||
const notifierTotp = new Notifier(".notification-totp", $);
|
||||
const notifierU2f = new Notifier(".notification-u2f", $);
|
||||
const notifierTotp = new Notifier(".notification-totp", $);
|
||||
const notifierU2f = new Notifier(".notification-u2f", $);
|
||||
|
||||
function onAuthenticationSuccess(data: any) {
|
||||
const redirectUrl = QueryParametersRetriever.get("redirect");
|
||||
if (redirectUrl)
|
||||
window.location.href = redirectUrl;
|
||||
else
|
||||
window.location.href = Endpoints.FIRST_FACTOR_GET;
|
||||
}
|
||||
function onAuthenticationSuccess(data: any) {
|
||||
const redirectUrl = QueryParametersRetriever.get("redirect");
|
||||
if (redirectUrl)
|
||||
window.location.href = redirectUrl;
|
||||
else
|
||||
window.location.href = Endpoints.FIRST_FACTOR_GET;
|
||||
}
|
||||
|
||||
function onSecondFactorTotpSuccess(data: any) {
|
||||
onAuthenticationSuccess(data);
|
||||
}
|
||||
function onSecondFactorTotpSuccess(data: any) {
|
||||
onAuthenticationSuccess(data);
|
||||
}
|
||||
|
||||
function onSecondFactorTotpFailure(err: Error) {
|
||||
notifierTotp.error("Problem with TOTP validation.");
|
||||
}
|
||||
function onSecondFactorTotpFailure(err: Error) {
|
||||
notifierTotp.error("Problem with TOTP validation.");
|
||||
}
|
||||
|
||||
function onU2fAuthenticationSuccess(data: any) {
|
||||
onAuthenticationSuccess(data);
|
||||
}
|
||||
function onU2fAuthenticationSuccess(data: any) {
|
||||
onAuthenticationSuccess(data);
|
||||
}
|
||||
|
||||
function onU2fAuthenticationFailure() {
|
||||
notifierU2f.error("Problem with U2F validation. Did you register before authenticating?");
|
||||
}
|
||||
function onU2fAuthenticationFailure() {
|
||||
notifierU2f.error("Problem with U2F validation. Did you register before authenticating?");
|
||||
}
|
||||
|
||||
function onTOTPFormSubmitted(): boolean {
|
||||
const token = $(Constants.TOTP_TOKEN_SELECTOR).val();
|
||||
jslogger.debug("TOTP token is %s", token);
|
||||
function onTOTPFormSubmitted(): boolean {
|
||||
const token = $(Constants.TOTP_TOKEN_SELECTOR).val();
|
||||
jslogger.debug("TOTP token is %s", token);
|
||||
|
||||
TOTPValidator.validate(token, $)
|
||||
.then(onSecondFactorTotpSuccess)
|
||||
.catch(onSecondFactorTotpFailure);
|
||||
return false;
|
||||
}
|
||||
TOTPValidator.validate(token, $)
|
||||
.then(onSecondFactorTotpSuccess)
|
||||
.catch(onSecondFactorTotpFailure);
|
||||
return false;
|
||||
}
|
||||
|
||||
function onU2FFormSubmitted(): boolean {
|
||||
jslogger.debug("Start U2F authentication");
|
||||
U2FValidator.validate($, notifierU2f, U2fApi)
|
||||
.then(onU2fAuthenticationSuccess, onU2fAuthenticationFailure);
|
||||
return false;
|
||||
}
|
||||
function onU2FFormSubmitted(): boolean {
|
||||
jslogger.debug("Start U2F authentication");
|
||||
U2FValidator.validate($, notifierU2f, U2fApi)
|
||||
.then(onU2fAuthenticationSuccess, onU2fAuthenticationFailure);
|
||||
return false;
|
||||
}
|
||||
|
||||
$(window.document).ready(function () {
|
||||
$(Constants.TOTP_FORM_SELECTOR).on("submit", onTOTPFormSubmitted);
|
||||
$(Constants.U2F_FORM_SELECTOR).on("submit", onU2FFormSubmitted);
|
||||
});
|
||||
$(window.document).ready(function () {
|
||||
$(Constants.TOTP_FORM_SELECTOR).on("submit", onTOTPFormSubmitted);
|
||||
$(Constants.U2F_FORM_SELECTOR).on("submit", onU2FFormSubmitted);
|
||||
});
|
||||
}
|
|
@ -2,39 +2,54 @@
|
|||
|
||||
import express = require("express");
|
||||
import U2f = require("u2f");
|
||||
import { ServerVariablesHandler } from "./ServerVariablesHandler";
|
||||
import BluebirdPromise = require("bluebird");
|
||||
|
||||
export interface AuthenticationSession {
|
||||
userid: string;
|
||||
first_factor: boolean;
|
||||
second_factor: boolean;
|
||||
identity_check?: {
|
||||
challenge: string;
|
||||
userid: string;
|
||||
first_factor: boolean;
|
||||
second_factor: boolean;
|
||||
identity_check?: {
|
||||
challenge: string;
|
||||
userid: string;
|
||||
};
|
||||
register_request?: U2f.Request;
|
||||
sign_request?: U2f.Request;
|
||||
email: string;
|
||||
groups: string[];
|
||||
redirect?: string;
|
||||
};
|
||||
register_request?: U2f.Request;
|
||||
sign_request?: U2f.Request;
|
||||
email: string;
|
||||
groups: string[];
|
||||
redirect?: string;
|
||||
}
|
||||
|
||||
const INITIAL_AUTHENTICATION_SESSION: AuthenticationSession = {
|
||||
first_factor: false,
|
||||
second_factor: false,
|
||||
userid: undefined,
|
||||
email: undefined,
|
||||
groups: [],
|
||||
register_request: undefined,
|
||||
sign_request: undefined,
|
||||
identity_check: undefined,
|
||||
redirect: undefined
|
||||
};
|
||||
|
||||
export function reset(req: express.Request): void {
|
||||
const authSession: AuthenticationSession = {
|
||||
first_factor: false,
|
||||
second_factor: false,
|
||||
userid: undefined,
|
||||
email: undefined,
|
||||
groups: [],
|
||||
register_request: undefined,
|
||||
sign_request: undefined,
|
||||
identity_check: undefined,
|
||||
redirect: undefined
|
||||
};
|
||||
req.session.auth = authSession;
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
logger.debug("Authentication session %s is being reset.", req.sessionID);
|
||||
req.session.auth = Object.assign({}, INITIAL_AUTHENTICATION_SESSION, {});
|
||||
}
|
||||
|
||||
export function get(req: express.Request): AuthenticationSession {
|
||||
if (!req.session.auth)
|
||||
reset(req);
|
||||
return req.session.auth;
|
||||
export function get(req: express.Request): BluebirdPromise<AuthenticationSession> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
if (!req.session) {
|
||||
const errorMsg = "Something is wrong with session cookies. Please check Redis is running and Authelia can contact it.";
|
||||
logger.error(errorMsg);
|
||||
return BluebirdPromise.reject(new Error(errorMsg));
|
||||
}
|
||||
|
||||
if (!req.session.auth) {
|
||||
logger.debug("Authentication session %s was undefined. Resetting.", req.sessionID);
|
||||
reset(req);
|
||||
}
|
||||
|
||||
return BluebirdPromise.resolve(req.session.auth);
|
||||
}
|
|
@ -9,10 +9,11 @@ import AuthenticationSession = require("./AuthenticationSession");
|
|||
export function validate(req: express.Request): BluebirdPromise<void> {
|
||||
return FirstFactorValidator.validate(req)
|
||||
.then(function () {
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
return AuthenticationSession.get(req);
|
||||
})
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
if (!authSession.second_factor)
|
||||
return BluebirdPromise.reject("No second factor variable");
|
||||
|
||||
return BluebirdPromise.reject("No second factor variable.");
|
||||
return BluebirdPromise.resolve();
|
||||
});
|
||||
}
|
|
@ -6,9 +6,11 @@ import Exceptions = require("./Exceptions");
|
|||
import AuthenticationSession = require("./AuthenticationSession");
|
||||
|
||||
export function validate(req: express.Request): BluebirdPromise<void> {
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
if (!authSession.userid || !authSession.first_factor)
|
||||
return BluebirdPromise.reject(new Exceptions.FirstFactorValidationError("First factor has not been validated yet."));
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
if (!authSession.userid || !authSession.first_factor)
|
||||
return BluebirdPromise.reject(new Exceptions.FirstFactorValidationError("First factor has not been validated yet."));
|
||||
|
||||
return BluebirdPromise.resolve();
|
||||
return BluebirdPromise.resolve();
|
||||
});
|
||||
}
|
|
@ -10,7 +10,7 @@ import { IUserDataStore } from "./storage/IUserDataStore";
|
|||
import { Winston } from "../../types/Dependencies";
|
||||
import express = require("express");
|
||||
import ErrorReplies = require("./ErrorReplies");
|
||||
import { ServerVariablesHandler } from "./ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "./ServerVariablesHandler";
|
||||
import AuthenticationSession = require("./AuthenticationSession");
|
||||
|
||||
import Identity = require("../../types/Identity");
|
||||
|
@ -66,7 +66,7 @@ export function get_finish_validation(handler: IdentityValidable): express.Reque
|
|||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
const identityToken = objectPath.get<express.Request, string>(req, "query.identity_token");
|
||||
logger.info("GET identity_check: identity token provided is %s", identityToken);
|
||||
|
||||
|
@ -74,6 +74,12 @@ export function get_finish_validation(handler: IdentityValidable): express.Reque
|
|||
.then(function () {
|
||||
return handler.postValidationInit(req);
|
||||
})
|
||||
.then(function () {
|
||||
return AuthenticationSession.get(req);
|
||||
})
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
})
|
||||
.then(function () {
|
||||
return consumeToken(identityToken, handler.challenge(), userDataStore, logger);
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import express = require("express");
|
||||
import Express = require("express");
|
||||
import { UserDataStore } from "./storage/UserDataStore";
|
||||
import { Winston } from "../../types/Dependencies";
|
||||
|
||||
|
@ -23,22 +23,29 @@ import U2FSignRequestGet = require("./routes/secondfactor/u2f/sign_request/get")
|
|||
import U2FRegisterPost = require("./routes/secondfactor/u2f/register/post");
|
||||
import U2FRegisterRequestGet = require("./routes/secondfactor/u2f/register_request/get");
|
||||
|
||||
|
||||
import ResetPasswordFormPost = require("./routes/password-reset/form/post");
|
||||
import ResetPasswordRequestPost = require("./routes/password-reset/request/get");
|
||||
|
||||
import Error401Get = require("./routes/error/401/get");
|
||||
import Error403Get = require("./routes/error/403/get");
|
||||
import Error404Get = require("./routes/error/404/get");
|
||||
|
||||
import { ServerVariablesHandler } from "./ServerVariablesHandler";
|
||||
|
||||
import Endpoints = require("../endpoints");
|
||||
|
||||
function withLog(fn: (req: Express.Request, res: Express.Response) => void) {
|
||||
return function(req: Express.Request, res: Express.Response) {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
logger.info("Request %s handled on %s", req.method, req.originalUrl);
|
||||
fn(req, res);
|
||||
};
|
||||
}
|
||||
|
||||
export class RestApi {
|
||||
static setup(app: express.Application): void {
|
||||
app.get(Endpoints.FIRST_FACTOR_GET, FirstFactorGet.default);
|
||||
app.get(Endpoints.SECOND_FACTOR_GET, SecondFactorGet.default);
|
||||
app.get(Endpoints.LOGOUT_GET, LogoutGet.default);
|
||||
static setup(app: Express.Application): void {
|
||||
app.get(Endpoints.FIRST_FACTOR_GET, withLog(FirstFactorGet.default));
|
||||
app.get(Endpoints.SECOND_FACTOR_GET, withLog(SecondFactorGet.default));
|
||||
app.get(Endpoints.LOGOUT_GET, withLog(LogoutGet.default));
|
||||
|
||||
IdentityCheckMiddleware.register(app, Endpoints.SECOND_FACTOR_TOTP_IDENTITY_START_GET,
|
||||
Endpoints.SECOND_FACTOR_TOTP_IDENTITY_FINISH_GET, new TOTPRegistrationIdentityHandler());
|
||||
|
@ -49,25 +56,21 @@ export class RestApi {
|
|||
IdentityCheckMiddleware.register(app, Endpoints.RESET_PASSWORD_IDENTITY_START_GET,
|
||||
Endpoints.RESET_PASSWORD_IDENTITY_FINISH_GET, new ResetPasswordIdentityHandler());
|
||||
|
||||
app.get(Endpoints.RESET_PASSWORD_REQUEST_GET, ResetPasswordRequestPost.default);
|
||||
app.post(Endpoints.RESET_PASSWORD_FORM_POST, ResetPasswordFormPost.default);
|
||||
app.get(Endpoints.RESET_PASSWORD_REQUEST_GET, withLog(ResetPasswordRequestPost.default));
|
||||
app.post(Endpoints.RESET_PASSWORD_FORM_POST, withLog(ResetPasswordFormPost.default));
|
||||
|
||||
app.get(Endpoints.VERIFY_GET, VerifyGet.default);
|
||||
app.get(Endpoints.VERIFY_GET, withLog(VerifyGet.default));
|
||||
app.post(Endpoints.FIRST_FACTOR_POST, withLog(FirstFactorPost.default));
|
||||
app.post(Endpoints.SECOND_FACTOR_TOTP_POST, withLog(TOTPSignGet.default));
|
||||
|
||||
app.post(Endpoints.FIRST_FACTOR_POST, FirstFactorPost.default);
|
||||
app.get(Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, withLog(U2FSignRequestGet.default));
|
||||
app.post(Endpoints.SECOND_FACTOR_U2F_SIGN_POST, withLog(U2FSignPost.default));
|
||||
|
||||
app.get(Endpoints.SECOND_FACTOR_U2F_REGISTER_REQUEST_GET, withLog(U2FRegisterRequestGet.default));
|
||||
app.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, withLog(U2FRegisterPost.default));
|
||||
|
||||
app.post(Endpoints.SECOND_FACTOR_TOTP_POST, TOTPSignGet.default);
|
||||
|
||||
|
||||
app.get(Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, U2FSignRequestGet.default);
|
||||
app.post(Endpoints.SECOND_FACTOR_U2F_SIGN_POST, U2FSignPost.default);
|
||||
|
||||
app.get(Endpoints.SECOND_FACTOR_U2F_REGISTER_REQUEST_GET, U2FRegisterRequestGet.default);
|
||||
app.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, U2FRegisterPost.default);
|
||||
|
||||
app.get(Endpoints.ERROR_401_GET, Error401Get.default);
|
||||
app.get(Endpoints.ERROR_403_GET, Error403Get.default);
|
||||
app.get(Endpoints.ERROR_404_GET, Error404Get.default);
|
||||
app.get(Endpoints.ERROR_401_GET, withLog(Error401Get.default));
|
||||
app.get(Endpoints.ERROR_403_GET, withLog(Error403Get.default));
|
||||
app.get(Endpoints.ERROR_404_GET, withLog(Error404Get.default));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import ExpressSession = require("express-session");
|
||||
import { AppConfiguration } from "./Configuration";
|
||||
import { GlobalDependencies } from "../../../types/Dependencies";
|
||||
import Redis = require("redis");
|
||||
|
||||
export class SessionConfigurationBuilder {
|
||||
|
||||
|
@ -21,9 +22,16 @@ export class SessionConfigurationBuilder {
|
|||
let redisOptions;
|
||||
if (configuration.session.redis.host
|
||||
&& configuration.session.redis.port) {
|
||||
redisOptions = {
|
||||
const client = Redis.createClient({
|
||||
host: configuration.session.redis.host,
|
||||
port: configuration.session.redis.port
|
||||
});
|
||||
client.on("error", function (err: Error) {
|
||||
console.error("Redis error:", err);
|
||||
});
|
||||
redisOptions = {
|
||||
client: client,
|
||||
logErrors: true
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,21 +5,22 @@ import FirstFactorValidator = require("../FirstFactorValidator");
|
|||
import Exceptions = require("../Exceptions");
|
||||
import ErrorReplies = require("../ErrorReplies");
|
||||
import objectPath = require("object-path");
|
||||
import { ServerVariablesHandler } from "../ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../AuthenticationSession");
|
||||
|
||||
type Handler = (req: express.Request, res: express.Response) => BluebirdPromise<void>;
|
||||
|
||||
export default function (callback: Handler): Handler {
|
||||
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
logger.debug("AuthSession is %s", JSON.stringify(authSession));
|
||||
return FirstFactorValidator.validate(req)
|
||||
.then(function () {
|
||||
return callback(req, res);
|
||||
})
|
||||
.catch(Exceptions.FirstFactorValidationError, ErrorReplies.replyWithError401(res, logger));
|
||||
};
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (authSession) {
|
||||
return FirstFactorValidator.validate(req);
|
||||
})
|
||||
.then(function () {
|
||||
return callback(req, res);
|
||||
})
|
||||
.catch(Exceptions.FirstFactorValidationError, ErrorReplies.replyWithError401(res, logger));
|
||||
};
|
||||
}
|
|
@ -5,19 +5,29 @@ import winston = require("winston");
|
|||
import Endpoints = require("../../../endpoints");
|
||||
import AuthenticationValidator = require("../../AuthenticationValidator");
|
||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
||||
import BluebirdPromise = require("bluebird");
|
||||
|
||||
export default function (req: express.Request, res: express.Response) {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
|
||||
logger.debug("First factor: headers are %s", JSON.stringify(req.headers));
|
||||
logger.debug("First factor: headers are %s", JSON.stringify(req.headers));
|
||||
|
||||
AuthenticationValidator.validate(req)
|
||||
.then(function () {
|
||||
res.render("already-logged-in", { logout_endpoint: Endpoints.LOGOUT_GET });
|
||||
}, function () {
|
||||
res.render("firstfactor", {
|
||||
first_factor_post_endpoint: Endpoints.FIRST_FACTOR_POST,
|
||||
reset_password_request_endpoint: Endpoints.RESET_PASSWORD_REQUEST_GET
|
||||
});
|
||||
});
|
||||
return AuthenticationValidator.validate(req)
|
||||
.then(function () {
|
||||
const redirectUrl = req.query.redirect;
|
||||
if (redirectUrl) {
|
||||
res.redirect(redirectUrl);
|
||||
return BluebirdPromise.resolve();
|
||||
}
|
||||
else {
|
||||
res.render("already-logged-in", { logout_endpoint: Endpoints.LOGOUT_GET });
|
||||
return BluebirdPromise.resolve();
|
||||
}
|
||||
}, function () {
|
||||
res.render("firstfactor", {
|
||||
first_factor_post_endpoint: Endpoints.FIRST_FACTOR_POST,
|
||||
reset_password_request_endpoint: Endpoints.RESET_PASSWORD_REQUEST_GET
|
||||
});
|
||||
return BluebirdPromise.resolve();
|
||||
});
|
||||
}
|
|
@ -12,63 +12,67 @@ import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
|||
import AuthenticationSession = require("../../AuthenticationSession");
|
||||
|
||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const username: string = req.body.username;
|
||||
const password: string = req.body.password;
|
||||
const username: string = req.body.username;
|
||||
const password: string = req.body.password;
|
||||
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const ldap = ServerVariablesHandler.getLdapAuthenticator(req.app);
|
||||
const config = ServerVariablesHandler.getConfiguration(req.app);
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const ldap = ServerVariablesHandler.getLdapAuthenticator(req.app);
|
||||
const config = ServerVariablesHandler.getConfiguration(req.app);
|
||||
|
||||
if (!username || !password) {
|
||||
const err = new Error("No username or password");
|
||||
ErrorReplies.replyWithError401(res, logger)(err);
|
||||
return BluebirdPromise.reject(err);
|
||||
}
|
||||
if (!username || !password) {
|
||||
const err = new Error("No username or password");
|
||||
ErrorReplies.replyWithError401(res, logger)(err);
|
||||
return BluebirdPromise.reject(err);
|
||||
}
|
||||
|
||||
const regulator = ServerVariablesHandler.getAuthenticationRegulator(req.app);
|
||||
const accessController = ServerVariablesHandler.getAccessController(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
const regulator = ServerVariablesHandler.getAuthenticationRegulator(req.app);
|
||||
const accessController = ServerVariablesHandler.getAccessController(req.app);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
|
||||
logger.info("1st factor: Starting authentication of user \"%s\"", username);
|
||||
logger.debug("1st factor: Start bind operation against LDAP");
|
||||
logger.debug("1st factor: username=%s", username);
|
||||
logger.info("1st factor: Starting authentication of user \"%s\"", username);
|
||||
logger.debug("1st factor: Start bind operation against LDAP");
|
||||
logger.debug("1st factor: username=%s", username);
|
||||
|
||||
return regulator.regulate(username)
|
||||
.then(function () {
|
||||
logger.info("1st factor: No regulation applied.");
|
||||
return ldap.authenticate(username, password);
|
||||
})
|
||||
.then(function (groupsAndEmails: GroupsAndEmails) {
|
||||
logger.info("1st factor: LDAP binding successful. Retrieved information about user are %s",
|
||||
JSON.stringify(groupsAndEmails));
|
||||
authSession.userid = username;
|
||||
authSession.first_factor = true;
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
return regulator.regulate(username);
|
||||
})
|
||||
.then(function () {
|
||||
logger.info("1st factor: No regulation applied.");
|
||||
return ldap.authenticate(username, password);
|
||||
})
|
||||
.then(function (groupsAndEmails: GroupsAndEmails) {
|
||||
logger.info("1st factor: LDAP binding successful. Retrieved information about user are %s",
|
||||
JSON.stringify(groupsAndEmails));
|
||||
authSession.userid = username;
|
||||
authSession.first_factor = true;
|
||||
|
||||
const emails: string[] = groupsAndEmails.emails;
|
||||
const groups: string[] = groupsAndEmails.groups;
|
||||
const emails: string[] = groupsAndEmails.emails;
|
||||
const groups: string[] = groupsAndEmails.groups;
|
||||
|
||||
if (!emails || emails.length <= 0) {
|
||||
const errMessage = "No emails found. The user should have at least one email address to reset password.";
|
||||
logger.error("1s factor: %s", errMessage);
|
||||
return BluebirdPromise.reject(new Error(errMessage));
|
||||
}
|
||||
if (!emails || emails.length <= 0) {
|
||||
const errMessage = "No emails found. The user should have at least one email address to reset password.";
|
||||
logger.error("1s factor: %s", errMessage);
|
||||
return BluebirdPromise.reject(new Error(errMessage));
|
||||
}
|
||||
|
||||
authSession.email = emails[0];
|
||||
authSession.groups = groups;
|
||||
authSession.email = emails[0];
|
||||
authSession.groups = groups;
|
||||
|
||||
logger.debug("1st factor: Mark successful authentication to regulator.");
|
||||
regulator.mark(username, true);
|
||||
logger.debug("1st factor: Mark successful authentication to regulator.");
|
||||
regulator.mark(username, true);
|
||||
|
||||
res.status(204);
|
||||
res.send();
|
||||
return BluebirdPromise.resolve();
|
||||
})
|
||||
.catch(exceptions.LdapSearchError, ErrorReplies.replyWithError500(res, logger))
|
||||
.catch(exceptions.LdapBindError, function (err: Error) {
|
||||
regulator.mark(username, false);
|
||||
return ErrorReplies.replyWithError401(res, logger)(err);
|
||||
})
|
||||
.catch(exceptions.AuthenticationRegulationError, ErrorReplies.replyWithError403(res, logger))
|
||||
.catch(exceptions.DomainAccessDenied, ErrorReplies.replyWithError401(res, logger))
|
||||
.catch(ErrorReplies.replyWithError500(res, logger));
|
||||
res.status(204);
|
||||
res.send();
|
||||
return BluebirdPromise.resolve();
|
||||
})
|
||||
.catch(exceptions.LdapSearchError, ErrorReplies.replyWithError500(res, logger))
|
||||
.catch(exceptions.LdapBindError, function (err: Error) {
|
||||
regulator.mark(username, false);
|
||||
return ErrorReplies.replyWithError401(res, logger)(err);
|
||||
})
|
||||
.catch(exceptions.AuthenticationRegulationError, ErrorReplies.replyWithError403(res, logger))
|
||||
.catch(exceptions.DomainAccessDenied, ErrorReplies.replyWithError401(res, logger))
|
||||
.catch(ErrorReplies.replyWithError500(res, logger));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import express = require("express");
|
|||
import BluebirdPromise = require("bluebird");
|
||||
import objectPath = require("object-path");
|
||||
import exceptions = require("../../../Exceptions");
|
||||
import { ServerVariablesHandler } from "../../../ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "../../../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../../../AuthenticationSession");
|
||||
import ErrorReplies = require("../../../ErrorReplies");
|
||||
|
||||
|
@ -12,23 +12,27 @@ import Constants = require("./../constants");
|
|||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const ldapPasswordUpdater = ServerVariablesHandler.getLdapPasswordUpdater(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
const newPassword = objectPath.get<express.Request, string>(req, "body.password");
|
||||
|
||||
const userid = authSession.identity_check.userid;
|
||||
const challenge = authSession.identity_check.challenge;
|
||||
if (challenge != Constants.CHALLENGE) {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return;
|
||||
}
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
logger.info("POST reset-password: User %s wants to reset his/her password.",
|
||||
authSession.identity_check.userid);
|
||||
logger.info("POST reset-password: Challenge %s", authSession.identity_check.challenge);
|
||||
|
||||
logger.info("POST reset-password: User %s wants to reset his/her password", userid);
|
||||
if (authSession.identity_check.challenge != Constants.CHALLENGE) {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return BluebirdPromise.reject(new Error("Bad challenge."));
|
||||
}
|
||||
|
||||
return ldapPasswordUpdater.updatePassword(userid, newPassword)
|
||||
return ldapPasswordUpdater.updatePassword(authSession.identity_check.userid, newPassword);
|
||||
})
|
||||
.then(function () {
|
||||
logger.info("POST reset-password: Password reset for user '%s'", userid);
|
||||
logger.info("POST reset-password: Password reset for user '%s'",
|
||||
authSession.identity_check.userid);
|
||||
AuthenticationSession.reset(req);
|
||||
res.status(204);
|
||||
res.send();
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
|
||||
import express = require("express");
|
||||
import Express = require("express");
|
||||
import Endpoints = require("../../../endpoints");
|
||||
import FirstFactorBlocker = require("../FirstFactorBlocker");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
||||
|
||||
const TEMPLATE_NAME = "secondfactor";
|
||||
|
||||
export default FirstFactorBlocker.default(handler);
|
||||
|
||||
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
function handler(req: Express.Request, res: Express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
logger.debug("secondfactor request is coming from %s", req.originalUrl);
|
||||
res.render(TEMPLATE_NAME, {
|
||||
totp_identity_start_endpoint: Endpoints.SECOND_FACTOR_TOTP_IDENTITY_START_GET,
|
||||
u2f_identity_start_endpoint: Endpoints.SECOND_FACTOR_U2F_IDENTITY_START_GET
|
||||
|
|
|
@ -5,11 +5,15 @@ import winston = require("winston");
|
|||
import Endpoints = require("../../../endpoints");
|
||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../../AuthenticationSession");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
|
||||
export default function (req: express.Request, res: express.Response) {
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
const redirectUrl = req.query.redirect || Endpoints.FIRST_FACTOR_GET;
|
||||
res.json({
|
||||
redirection_url: redirectUrl
|
||||
});
|
||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
const redirectUrl = req.query.redirect || Endpoints.FIRST_FACTOR_GET;
|
||||
res.json({
|
||||
redirection_url: redirectUrl
|
||||
});
|
||||
return BluebirdPromise.resolve();
|
||||
});
|
||||
}
|
|
@ -9,7 +9,7 @@ import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationT
|
|||
import Constants = require("../constants");
|
||||
import Endpoints = require("../../../../../endpoints");
|
||||
import ErrorReplies = require("../../../../ErrorReplies");
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
||||
|
||||
import FirstFactorValidator = require("../../../../FirstFactorValidator");
|
||||
|
@ -21,19 +21,21 @@ export default class RegistrationHandler implements IdentityValidable {
|
|||
}
|
||||
|
||||
private retrieveIdentity(req: express.Request): BluebirdPromise<Identity> {
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
const userid = authSession.userid;
|
||||
const email = authSession.email;
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
const userid = authSession.userid;
|
||||
const email = authSession.email;
|
||||
|
||||
if (!(userid && email)) {
|
||||
return BluebirdPromise.reject(new Error("User ID or email is missing"));
|
||||
}
|
||||
if (!(userid && email)) {
|
||||
return BluebirdPromise.reject(new Error("User ID or email is missing"));
|
||||
}
|
||||
|
||||
const identity = {
|
||||
email: email,
|
||||
userid: userid
|
||||
};
|
||||
return BluebirdPromise.resolve(identity);
|
||||
const identity = {
|
||||
email: email,
|
||||
userid: userid
|
||||
};
|
||||
return BluebirdPromise.resolve(identity);
|
||||
});
|
||||
}
|
||||
|
||||
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
||||
|
@ -52,33 +54,34 @@ export default class RegistrationHandler implements IdentityValidable {
|
|||
return FirstFactorValidator.validate(req);
|
||||
}
|
||||
|
||||
postValidationResponse(req: express.Request, res: express.Response) {
|
||||
postValidationResponse(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
const userid = authSession.identity_check.userid;
|
||||
const challenge = authSession.identity_check.challenge;
|
||||
|
||||
const userid = authSession.identity_check.userid;
|
||||
const challenge = authSession.identity_check.challenge;
|
||||
if (challenge != Constants.CHALLENGE || !userid) {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return BluebirdPromise.reject(new Error("Bad challenge."));
|
||||
}
|
||||
|
||||
if (challenge != Constants.CHALLENGE || !userid) {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return;
|
||||
}
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
const totpGenerator = ServerVariablesHandler.getTOTPGenerator(req.app);
|
||||
const secret = totpGenerator.generate();
|
||||
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
const totpGenerator = ServerVariablesHandler.getTOTPGenerator(req.app);
|
||||
const secret = totpGenerator.generate();
|
||||
logger.debug("POST new-totp-secret: save the TOTP secret in DB");
|
||||
return userDataStore.saveTOTPSecret(userid, secret)
|
||||
.then(function () {
|
||||
objectPath.set(req, "session", undefined);
|
||||
|
||||
logger.debug("POST new-totp-secret: save the TOTP secret in DB");
|
||||
userDataStore.saveTOTPSecret(userid, secret)
|
||||
.then(function () {
|
||||
objectPath.set(req, "session", undefined);
|
||||
|
||||
res.render(Constants.TEMPLATE_NAME, {
|
||||
base32_secret: secret.base32,
|
||||
otpauth_url: secret.otpauth_url,
|
||||
login_endpoint: Endpoints.FIRST_FACTOR_GET
|
||||
});
|
||||
res.render(Constants.TEMPLATE_NAME, {
|
||||
base32_secret: secret.base32,
|
||||
otpauth_url: secret.otpauth_url,
|
||||
login_endpoint: Endpoints.FIRST_FACTOR_GET
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(ErrorReplies.replyWithError500(res, logger));
|
||||
}
|
||||
|
|
|
@ -16,17 +16,18 @@ const UNAUTHORIZED_MESSAGE = "Unauthorized access";
|
|||
export default FirstFactorBlocker(handler);
|
||||
|
||||
export function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
const userid = authSession.userid;
|
||||
logger.info("POST 2ndfactor totp: Initiate TOTP validation for user %s", userid);
|
||||
|
||||
const token = req.body.token;
|
||||
const totpValidator = ServerVariablesHandler.getTOTPValidator(req.app);
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
|
||||
logger.debug("POST 2ndfactor totp: Fetching secret for user %s", userid);
|
||||
return userDataStore.retrieveTOTPSecret(userid)
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
logger.info("POST 2ndfactor totp: Initiate TOTP validation for user %s", authSession.userid);
|
||||
return userDataStore.retrieveTOTPSecret(authSession.userid);
|
||||
})
|
||||
.then(function (doc: TOTPSecretDocument) {
|
||||
logger.debug("POST 2ndfactor totp: TOTP secret is %s", JSON.stringify(doc));
|
||||
return totpValidator.validate(token, doc.secret.base32);
|
||||
|
|
|
@ -20,20 +20,22 @@ export default class RegistrationHandler implements IdentityValidable {
|
|||
return CHALLENGE;
|
||||
}
|
||||
|
||||
private retrieveIdentity(req: express.Request) {
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
const userid = authSession.userid;
|
||||
const email = authSession.email;
|
||||
private retrieveIdentity(req: express.Request): BluebirdPromise<Identity> {
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
const userid = authSession.userid;
|
||||
const email = authSession.email;
|
||||
|
||||
if (!(userid && email)) {
|
||||
return BluebirdPromise.reject("User ID or email is missing");
|
||||
}
|
||||
if (!(userid && email)) {
|
||||
return BluebirdPromise.reject(new Error("User ID or email is missing"));
|
||||
}
|
||||
|
||||
const identity = {
|
||||
email: email,
|
||||
userid: userid
|
||||
};
|
||||
return BluebirdPromise.resolve(identity);
|
||||
const identity = {
|
||||
email: email,
|
||||
userid: userid
|
||||
};
|
||||
return BluebirdPromise.resolve(identity);
|
||||
});
|
||||
}
|
||||
|
||||
preValidationInit(req: express.Request): BluebirdPromise<Identity> {
|
||||
|
|
|
@ -18,53 +18,54 @@ export default FirstFactorBlocker(handler);
|
|||
|
||||
|
||||
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
const registrationRequest = authSession.register_request;
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
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;
|
||||
|
||||
if (!registrationRequest) {
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
const registrationRequest = authSession.register_request;
|
||||
|
||||
if (!registrationRequest) {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return BluebirdPromise.reject(new Error("No registration request"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!authSession.identity_check
|
||||
if (!authSession.identity_check
|
||||
|| authSession.identity_check.challenge != "u2f-register") {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return BluebirdPromise.reject(new Error("Bad challenge for registration request"));
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("U2F register: Finishing registration");
|
||||
logger.debug("U2F register: registrationRequest = %s", JSON.stringify(registrationRequest));
|
||||
logger.debug("U2F register: registrationResponse = %s", JSON.stringify(registrationResponse));
|
||||
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
||||
const userid = authSession.userid;
|
||||
const appid = u2f_common.extract_app_id(req);
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
return BluebirdPromise.resolve(u2f.checkRegistration(registrationRequest, registrationResponse));
|
||||
})
|
||||
.then(function (u2fResult: U2f.RegistrationResult | U2f.Error): BluebirdPromise<void> {
|
||||
if (objectPath.has(u2fResult, "errorCode"))
|
||||
return BluebirdPromise.reject(new Error("Error while registering."));
|
||||
|
||||
const registrationResponse: U2f.RegistrationData = req.body;
|
||||
|
||||
logger.info("U2F register: Finishing registration");
|
||||
logger.debug("U2F register: registrationRequest = %s", JSON.stringify(registrationRequest));
|
||||
logger.debug("U2F register: registrationResponse = %s", JSON.stringify(registrationResponse));
|
||||
|
||||
BluebirdPromise.resolve(u2f.checkRegistration(registrationRequest, registrationResponse))
|
||||
.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("U2F register: Store regisutration and reply");
|
||||
logger.debug("U2F register: registration = %s", JSON.stringify(registrationResult));
|
||||
const registration: U2FRegistration = {
|
||||
keyHandle: registrationResult.keyHandle,
|
||||
publicKey: registrationResult.publicKey
|
||||
};
|
||||
return userDataStore.saveU2FRegistration(userid, appid, registration);
|
||||
})
|
||||
.then(function () {
|
||||
authSession.identity_check = undefined;
|
||||
redirect(req, res);
|
||||
return BluebirdPromise.resolve();
|
||||
})
|
||||
.catch(ErrorReplies.replyWithError500(res, logger));
|
||||
const registrationResult: U2f.RegistrationResult = u2fResult as U2f.RegistrationResult;
|
||||
logger.info("U2F register: Store regisutration and reply");
|
||||
logger.debug("U2F register: registration = %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.replyWithError500(res, logger));
|
||||
}
|
||||
|
|
|
@ -8,29 +8,34 @@ import express = require("express");
|
|||
import U2f = require("u2f");
|
||||
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||
import ErrorReplies = require("../../../../ErrorReplies");
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
||||
|
||||
export default FirstFactorBlocker(handler);
|
||||
|
||||
function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
|
||||
if (!authSession.identity_check
|
||||
|| authSession.identity_check.challenge != "u2f-register") {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return;
|
||||
}
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
|
||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
||||
const appid: string = u2f_common.extract_app_id(req);
|
||||
if (!authSession.identity_check
|
||||
|| authSession.identity_check.challenge != "u2f-register") {
|
||||
res.status(403);
|
||||
res.send();
|
||||
return BluebirdPromise.reject(new Error("Bad challenge."));
|
||||
}
|
||||
|
||||
logger.debug("U2F register_request: headers=%s", JSON.stringify(req.headers));
|
||||
logger.info("U2F register_request: Starting registration for appId %s", appid);
|
||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
||||
const appid: string = u2f_common.extract_app_id(req);
|
||||
|
||||
return BluebirdPromise.resolve(u2f.request(appid))
|
||||
logger.debug("U2F register_request: headers=%s", JSON.stringify(req.headers));
|
||||
logger.info("U2F register_request: Starting registration for appId %s", appid);
|
||||
|
||||
return BluebirdPromise.resolve(u2f.request(appid));
|
||||
})
|
||||
.then(function (registrationRequest: U2f.Request) {
|
||||
logger.debug("U2F register_request: registrationRequest = %s", JSON.stringify(registrationRequest));
|
||||
authSession.register_request = registrationRequest;
|
||||
|
|
|
@ -11,7 +11,7 @@ import exceptions = require("../../../../Exceptions");
|
|||
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||
import redirect from "../../redirect";
|
||||
import ErrorReplies = require("../../../../ErrorReplies");
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
||||
|
||||
export default FirstFactorBlocker(handler);
|
||||
|
@ -19,17 +19,21 @@ export default FirstFactorBlocker(handler);
|
|||
export function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
|
||||
if (!authSession.sign_request) {
|
||||
const err = new Error("No sign request");
|
||||
ErrorReplies.replyWithError401(res, logger)(err);
|
||||
return BluebirdPromise.reject(err);
|
||||
}
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
if (!authSession.sign_request) {
|
||||
const err = new Error("No sign request");
|
||||
ErrorReplies.replyWithError401(res, logger)(err);
|
||||
return BluebirdPromise.reject(err);
|
||||
}
|
||||
|
||||
const userid = authSession.userid;
|
||||
const appid = u2f_common.extract_app_id(req);
|
||||
return userDataStore.retrieveU2FRegistration(userid, appid)
|
||||
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);
|
||||
|
|
|
@ -11,43 +11,46 @@ import exceptions = require("../../../../Exceptions");
|
|||
import { SignMessage } from "./SignMessage";
|
||||
import FirstFactorBlocker from "../../../FirstFactorBlocker";
|
||||
import ErrorReplies = require("../../../../ErrorReplies");
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "../../../../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../../../../AuthenticationSession");
|
||||
|
||||
export default FirstFactorBlocker(handler);
|
||||
|
||||
export function handler(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
const appId = u2f_common.extract_app_id(req);
|
||||
|
||||
const userId = authSession.userid;
|
||||
const appId = u2f_common.extract_app_id(req);
|
||||
return userDataStore.retrieveU2FRegistration(userId, appId)
|
||||
.then(function (doc: U2FRegistrationDocument): BluebirdPromise<SignMessage> {
|
||||
if (!doc)
|
||||
return BluebirdPromise.reject(new exceptions.AccessDeniedError("No U2F registration found"));
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
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 appId: string = u2f_common.extract_app_id(req);
|
||||
logger.info("U2F sign_request: Start authentication to app %s", appId);
|
||||
logger.debug("U2F sign_request: appId=%s, keyHandle=%s", appId, JSON.stringify(doc.registration.keyHandle));
|
||||
const u2f = ServerVariablesHandler.getU2F(req.app);
|
||||
const appId: string = u2f_common.extract_app_id(req);
|
||||
logger.info("U2F sign_request: Start authentication to app %s", appId);
|
||||
logger.debug("U2F sign_request: appId=%s, keyHandle=%s", appId, JSON.stringify(doc.registration.keyHandle));
|
||||
|
||||
const request = u2f.request(appId, doc.registration.keyHandle);
|
||||
const authenticationMessage: SignMessage = {
|
||||
request: request,
|
||||
keyHandle: doc.registration.keyHandle
|
||||
};
|
||||
return BluebirdPromise.resolve(authenticationMessage);
|
||||
})
|
||||
.then(function (authenticationMessage: SignMessage) {
|
||||
logger.info("U2F sign_request: Store authentication request and reply");
|
||||
logger.debug("U2F sign_request: authenticationRequest=%s", authenticationMessage);
|
||||
authSession.sign_request = authenticationMessage.request;
|
||||
res.json(authenticationMessage);
|
||||
return BluebirdPromise.resolve();
|
||||
})
|
||||
.catch(exceptions.AccessDeniedError, ErrorReplies.replyWithError401(res, logger))
|
||||
.catch(ErrorReplies.replyWithError500(res, logger));
|
||||
const request = u2f.request(appId, doc.registration.keyHandle);
|
||||
const authenticationMessage: SignMessage = {
|
||||
request: request,
|
||||
keyHandle: doc.registration.keyHandle
|
||||
};
|
||||
return BluebirdPromise.resolve(authenticationMessage);
|
||||
})
|
||||
.then(function (authenticationMessage: SignMessage) {
|
||||
logger.info("U2F sign_request: Store authentication request and reply");
|
||||
logger.debug("U2F sign_request: authenticationRequest=%s", authenticationMessage);
|
||||
authSession.sign_request = authenticationMessage.request;
|
||||
res.json(authenticationMessage);
|
||||
return BluebirdPromise.resolve();
|
||||
})
|
||||
.catch(exceptions.AccessDeniedError, ErrorReplies.replyWithError401(res, logger))
|
||||
.catch(ErrorReplies.replyWithError500(res, logger));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,18 +8,22 @@ import exceptions = require("../../Exceptions");
|
|||
import winston = require("winston");
|
||||
import AuthenticationValidator = require("../../AuthenticationValidator");
|
||||
import ErrorReplies = require("../../ErrorReplies");
|
||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
||||
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
|
||||
import AuthenticationSession = require("../../AuthenticationSession");
|
||||
|
||||
function verify_filter(req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||
const logger = ServerVariablesHandler.getLogger(req.app);
|
||||
const accessController = ServerVariablesHandler.getAccessController(req.app);
|
||||
const authSession = AuthenticationSession.get(req);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
|
||||
logger.debug("Verify: headers are %s", JSON.stringify(req.headers));
|
||||
res.set("Redirect", encodeURIComponent("https://" + req.headers["host"] + req.headers["x-original-uri"]));
|
||||
return AuthenticationSession.get(req)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
logger.debug("Verify: headers are %s", JSON.stringify(req.headers));
|
||||
res.set("Redirect", encodeURIComponent("https://" + req.headers["host"] + req.headers["x-original-uri"]));
|
||||
|
||||
return AuthenticationValidator.validate(req)
|
||||
return AuthenticationValidator.validate(req);
|
||||
})
|
||||
.then(function () {
|
||||
const username = authSession.userid;
|
||||
const groups = authSession.groups;
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
Feature: User has access restricted access to domains
|
||||
|
||||
@need-registered-user-john
|
||||
Scenario: User john has admin access
|
||||
When I register TOTP and login with user "john" and password "password"
|
||||
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 have access to:
|
||||
| url |
|
||||
| https://public.test.local:8080/secret.html |
|
||||
|
@ -11,8 +15,12 @@ Feature: User has access restricted access to domains
|
|||
| https://mx1.mail.test.local:8080/secret.html |
|
||||
| https://mx2.mail.test.local:8080/secret.html |
|
||||
|
||||
@need-registered-user-bob
|
||||
Scenario: User bob has restricted access
|
||||
When I register TOTP and login with user "bob" and password "password"
|
||||
When I visit "https://auth.test.local:8080"
|
||||
And I login with user "bob" and password "password"
|
||||
And I use "REGISTERED" as TOTP token handle
|
||||
And I click on "TOTP"
|
||||
Then I have access to:
|
||||
| url |
|
||||
| https://public.test.local:8080/secret.html |
|
||||
|
@ -24,8 +32,12 @@ Feature: User has access restricted access to domains
|
|||
| url |
|
||||
| https://secret1.test.local:8080/secret.html |
|
||||
|
||||
@need-registered-user-harry
|
||||
Scenario: User harry has restricted access
|
||||
When I register TOTP and login with user "harry" and password "password"
|
||||
When I visit "https://auth.test.local:8080"
|
||||
And I login with user "harry" and password "password"
|
||||
And I use "REGISTERED" as TOTP token handle
|
||||
And I click on "TOTP"
|
||||
Then I have access to:
|
||||
| url |
|
||||
| https://public.test.local:8080/secret.html |
|
||||
|
|
|
@ -14,7 +14,7 @@ Feature: User validate first factor
|
|||
And I click on "Sign in"
|
||||
Then I get a notification of type "error" with message "Authentication failed. Please double check your credentials."
|
||||
|
||||
Scenario: User succeeds TOTP second factor
|
||||
Scenario: User registers TOTP secret and succeeds authentication
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
And I login with user "john" and password "password"
|
||||
And I register a TOTP secret called "Sec0"
|
||||
|
@ -31,23 +31,6 @@ Feature: User validate first factor
|
|||
And I click on "TOTP"
|
||||
Then I get a notification of type "error" with message "Problem with TOTP validation."
|
||||
|
||||
Scenario: User logs out
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
And I login with user "john" and password "password"
|
||||
And I register a TOTP secret called "Sec0"
|
||||
And I visit "https://auth.test.local:8080/"
|
||||
And I login with user "john" and password "password"
|
||||
And I use "Sec0" as TOTP token handle
|
||||
When I visit "https://auth.test.local:8080/logout?redirect=https://www.google.fr"
|
||||
And I visit "https://secret.test.local:8080/secret.html"
|
||||
Then I'm redirected to "https://auth.test.local:8080/"
|
||||
|
||||
Scenario: Logout redirects user
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
And I login with user "john" and password "password"
|
||||
And I register a TOTP secret called "Sec0"
|
||||
And I visit "https://auth.test.local:8080/"
|
||||
And I login with user "john" and password "password"
|
||||
And I use "Sec0" as TOTP token handle
|
||||
Scenario: Logout redirects user to redirect URL given in parameter
|
||||
When I visit "https://auth.test.local:8080/logout?redirect=https://www.google.fr"
|
||||
Then I'm redirected to "https://www.google.fr"
|
||||
|
|
|
@ -5,19 +5,17 @@ Feature: User is correctly redirected
|
|||
When I click on the link to secret.test.local
|
||||
Then I'm redirected to "https://auth.test.local:8080/"
|
||||
|
||||
@need-registered-user-john
|
||||
Scenario: User is redirected to home page after several authentication tries
|
||||
Given I'm on https://auth.test.local:8080/
|
||||
And I login with user "john" and password "password"
|
||||
And I register a TOTP secret called "Sec0"
|
||||
And I visit "https://public.test.local:8080/secret.html"
|
||||
When I login with user "john" and password "badpassword"
|
||||
When I visit "https://public.test.local:8080/secret.html"
|
||||
And I login with user "john" and password "badpassword"
|
||||
And I clear field "username"
|
||||
And I login with user "john" and password "password"
|
||||
And I use "Sec0" as TOTP token handle
|
||||
And I use "REGISTERED" as TOTP token handle
|
||||
And I click on "TOTP"
|
||||
Then I'm redirected to "https://public.test.local:8080/secret.html"
|
||||
|
||||
Scenario: User Harry does not have access to https://secret.test.local:8080/secret.html and thus he must get an error 401
|
||||
Scenario: User Harry does not have access to https://secret.test.local:8080/secret.html and thus he must get an error 403
|
||||
When I register TOTP and login with user "harry" and password "password"
|
||||
And I visit "https://secret.test.local:8080/secret.html"
|
||||
Then I get an error 403
|
||||
|
@ -44,4 +42,4 @@ Feature: User is correctly redirected
|
|||
And I login with user "john" and password "password"
|
||||
And I use "Sec0" as TOTP token handle
|
||||
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"
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
Feature: Authelia regulates authentication to avoid brute force
|
||||
|
||||
@needs-test-config
|
||||
@need-registered-user-blackhat
|
||||
Scenario: Attacker tries too many authentication in a short period of time and get banned
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
And I login with user "blackhat" and password "password"
|
||||
And I register a TOTP secret called "Sec0"
|
||||
And I visit "https://auth.test.local:8080/"
|
||||
And I login with user "blackhat" and password "password" and I use TOTP token handle "Sec0"
|
||||
And I visit "https://auth.test.local:8080/logout?redirect=https://auth.test.local:8080/"
|
||||
And I visit "https://auth.test.local:8080/"
|
||||
And I set field "username" to "blackhat"
|
||||
And I set field "password" to "bad-password"
|
||||
And I click on "Sign in"
|
||||
|
@ -24,14 +19,9 @@ Feature: Authelia regulates authentication to avoid brute force
|
|||
Then I get a notification of type "error" with message "Authentication failed. Please double check your credentials."
|
||||
|
||||
@needs-test-config
|
||||
@need-registered-user-blackhat
|
||||
Scenario: User is unbanned after a configured amount of time
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
And I login with user "blackhat" and password "password"
|
||||
And I register a TOTP secret called "Sec0"
|
||||
And I visit "https://auth.test.local:8080/"
|
||||
And I login with user "blackhat" and password "password" and I use TOTP token handle "Sec0"
|
||||
And I visit "https://auth.test.local:8080/logout?redirect=https://auth.test.local:8080/"
|
||||
And I visit "https://auth.test.local:8080/"
|
||||
Given I visit "https://auth.test.local:8080/?redirect=https%3A%2F%2Fpublic.test.local%3A8080%2Fsecret.html"
|
||||
And I set field "username" to "blackhat"
|
||||
And I set field "password" to "bad-password"
|
||||
And I click on "Sign in"
|
||||
|
@ -45,7 +35,7 @@ Feature: Authelia regulates authentication to avoid brute force
|
|||
When I wait 6 seconds
|
||||
And I set field "password" to "password"
|
||||
And I click on "Sign in"
|
||||
And I use "Sec0" as TOTP token handle
|
||||
And I use "REGISTERED" as TOTP token handle
|
||||
And I click on "TOTP"
|
||||
Then I have access to:
|
||||
| url |
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
Feature: Authelia keeps user sessions despite the application restart
|
||||
|
||||
@need-authenticated-user-john
|
||||
Scenario: Session is still valid after Authelia restarts
|
||||
When I register TOTP and login with user "john" and password "password"
|
||||
And the application restarts
|
||||
When the application restarts
|
||||
Then I have access to:
|
||||
| url |
|
||||
| https://secret.test.local:8080/secret.html |
|
||||
|
||||
@need-registered-user-john
|
||||
Scenario: Secrets are stored even when Authelia restarts
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
And I login with user "john" and password "password"
|
||||
And I register a TOTP secret called "Sec0"
|
||||
When the application restarts
|
||||
And I visit "https://secret.test.local:8080/secret.html" and get redirected "https://auth.test.local:8080/?redirect=https%3A%2F%2Fsecret.test.local%3A8080%2Fsecret.html"
|
||||
And I login with user "john" and password "password"
|
||||
And I use "Sec0" as TOTP token handle
|
||||
And I use "REGISTERED" as TOTP token handle
|
||||
And I click on "TOTP"
|
||||
Then I have access to:
|
||||
| url |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Feature: Non authenticated users have no access to certain pages
|
||||
|
||||
Scenario Outline: User has no access to protected pages
|
||||
Scenario Outline: Anonymous user has no access to protected pages
|
||||
When I visit "<url>"
|
||||
Then I get an error <error code>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import Speakeasy = require("speakeasy");
|
|||
import CustomWorld = require("../support/world");
|
||||
|
||||
Cucumber.defineSupportCode(function ({ Given, When, Then }) {
|
||||
When(/^I visit "(https:\/\/[a-z0-9:.\/=?-]+)"$/, function (link: string) {
|
||||
When(/^I visit "(https:\/\/[a-zA-Z0-9:%.\/=?-]+)"$/, function (link: string) {
|
||||
return this.visit(link);
|
||||
});
|
||||
|
||||
|
|
|
@ -2,23 +2,90 @@ import Cucumber = require("cucumber");
|
|||
import fs = require("fs");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import ChildProcess = require("child_process");
|
||||
import { UserDataStore } from "../../../src/server/lib/storage/UserDataStore";
|
||||
import { CollectionFactoryFactory } from "../../../src/server/lib/storage/CollectionFactoryFactory";
|
||||
import { MongoConnector } from "../../../src/server/lib/connectors/mongo/MongoConnector";
|
||||
import { IMongoClient } from "../../../src/server/lib/connectors/mongo/IMongoClient";
|
||||
import { TOTPGenerator } from "../../../src/server/lib/TOTPGenerator";
|
||||
import Speakeasy = require("speakeasy");
|
||||
|
||||
Cucumber.defineSupportCode(function({ setDefaultTimeout }) {
|
||||
Cucumber.defineSupportCode(function ({ setDefaultTimeout }) {
|
||||
setDefaultTimeout(20 * 1000);
|
||||
});
|
||||
|
||||
Cucumber.defineSupportCode(function({ After, Before }) {
|
||||
Cucumber.defineSupportCode(function ({ After, Before }) {
|
||||
const exec = BluebirdPromise.promisify(ChildProcess.exec);
|
||||
|
||||
After(function() {
|
||||
After(function () {
|
||||
return this.driver.quit();
|
||||
});
|
||||
|
||||
Before({tags: "@needs-test-config", timeout: 15 * 1000}, function () {
|
||||
Before({ tags: "@needs-test-config", timeout: 20 * 1000 }, function () {
|
||||
return exec("./scripts/example-commit/dc-example.sh -f docker-compose.test.yml up -d authelia && sleep 2");
|
||||
});
|
||||
|
||||
After({tags: "@needs-test-config", timeout: 15 * 1000}, function () {
|
||||
After({ tags: "@needs-test-config", timeout: 20 * 1000 }, function () {
|
||||
return exec("./scripts/example-commit/dc-example.sh up -d authelia && sleep 2");
|
||||
});
|
||||
|
||||
function registerUser(context: any, username: string) {
|
||||
let secret: Speakeasy.Key;
|
||||
const mongoConnector = new MongoConnector("mongodb://localhost:27017/authelia");
|
||||
return mongoConnector.connect()
|
||||
.then(function (mongoClient: IMongoClient) {
|
||||
const collectionFactory = CollectionFactoryFactory.createMongo(mongoClient);
|
||||
const userDataStore = new UserDataStore(collectionFactory);
|
||||
|
||||
const generator = new TOTPGenerator(Speakeasy);
|
||||
secret = generator.generate();
|
||||
return userDataStore.saveTOTPSecret(username, secret);
|
||||
})
|
||||
.then(function () {
|
||||
context.totpSecrets["REGISTERED"] = secret.base32;
|
||||
});
|
||||
}
|
||||
|
||||
function declareNeedRegisteredUserHooks(username: string) {
|
||||
Before({ tags: "@need-registered-user-" + username, timeout: 15 * 1000 }, function () {
|
||||
return registerUser(this, username);
|
||||
});
|
||||
|
||||
After({ tags: "@need-registered-user-" + username, timeout: 15 * 1000 }, function () {
|
||||
this.totpSecrets["REGISTERED"] = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
function needAuthenticatedUser(context: any, username: string): BluebirdPromise<void> {
|
||||
return context.visit("https://auth.test.local:8080/")
|
||||
.then(function () {
|
||||
return registerUser(context, username);
|
||||
})
|
||||
.then(function () {
|
||||
return context.loginWithUserPassword(username, "password");
|
||||
})
|
||||
.then(function () {
|
||||
return context.useTotpTokenHandle("REGISTERED");
|
||||
})
|
||||
.then(function() {
|
||||
return context.clickOnButton("TOTP");
|
||||
});
|
||||
}
|
||||
|
||||
function declareNeedAuthenticatedUserHooks(username: string) {
|
||||
Before({ tags: "@need-authenticated-user-" + username, timeout: 15 * 1000 }, function () {
|
||||
return needAuthenticatedUser(this, username);
|
||||
});
|
||||
|
||||
After({ tags: "@need-authenticated-user-" + username, timeout: 15 * 1000 }, function () {
|
||||
this.totpSecrets["REGISTERED"] = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
function declareHooksForUser(username: string) {
|
||||
declareNeedRegisteredUserHooks(username);
|
||||
declareNeedAuthenticatedUserHooks(username);
|
||||
}
|
||||
|
||||
const users = ["harry", "john", "bob", "blackhat"];
|
||||
users.forEach(declareHooksForUser);
|
||||
});
|
|
@ -91,6 +91,9 @@ function CustomWorld() {
|
|||
};
|
||||
|
||||
this.useTotpTokenHandle = function (totpSecretHandle: string) {
|
||||
if (!this.totpSecrets[totpSecretHandle])
|
||||
throw new Error("No available TOTP token handle " + totpSecretHandle);
|
||||
|
||||
const token = Speakeasy.totp({
|
||||
secret: this.totpSecrets[totpSecretHandle],
|
||||
encoding: "base32"
|
||||
|
|
|
@ -155,9 +155,14 @@ describe("test identity check process", function () {
|
|||
req.query.identity_token = "token";
|
||||
|
||||
req.session = {};
|
||||
const authSession = AuthenticationSession.get(req as any);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
const callback = IdentityValidator.get_finish_validation(identityValidable);
|
||||
return callback(req as any, res as any, undefined)
|
||||
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
return callback(req as any, res as any, undefined);
|
||||
})
|
||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
||||
.catch(function () {
|
||||
assert.equal(authSession.identity_check.userid, "user");
|
||||
|
|
|
@ -45,6 +45,7 @@ describe("test the first factor validation route", function () {
|
|||
|
||||
req = {
|
||||
app: {
|
||||
get: sinon.stub().returns({ logger: winston })
|
||||
},
|
||||
body: {
|
||||
username: "username",
|
||||
|
@ -77,8 +78,12 @@ describe("test the first factor validation route", function () {
|
|||
emails: emails,
|
||||
groups: groups
|
||||
}));
|
||||
const authSession = AuthenticationSession.get(req as any);
|
||||
return FirstFactorPost.default(req as any, res as any)
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
return FirstFactorPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () {
|
||||
assert.equal("username", authSession.userid);
|
||||
assert(res.send.calledOnce);
|
||||
|
@ -94,13 +99,18 @@ describe("test the first factor validation route", function () {
|
|||
|
||||
it("should set first email address as user session variable", function () {
|
||||
const emails = ["test_ok@example.com"];
|
||||
const authSession = AuthenticationSession.get(req as any);
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
(serverVariables.ldapAuthenticator as any).authenticate.withArgs("username", "password")
|
||||
.returns(BluebirdPromise.resolve({
|
||||
emails: emails,
|
||||
groups: groups
|
||||
}));
|
||||
return FirstFactorPost.default(req as any, res as any)
|
||||
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
return FirstFactorPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () {
|
||||
assert.equal("test_ok@example.com", authSession.email);
|
||||
});
|
||||
|
|
|
@ -16,7 +16,6 @@ describe("test reset password route", function () {
|
|||
let req: ExpressMock.RequestMock;
|
||||
let res: ExpressMock.ResponseMock;
|
||||
let configuration: any;
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
let serverVariables: ServerVariablesMock.ServerVariablesMock;
|
||||
|
||||
beforeEach(function () {
|
||||
|
@ -25,7 +24,7 @@ describe("test reset password route", function () {
|
|||
userid: "user"
|
||||
},
|
||||
app: {
|
||||
get: Sinon.stub()
|
||||
get: Sinon.stub().returns({ logger: winston })
|
||||
},
|
||||
session: {},
|
||||
headers: {
|
||||
|
@ -34,11 +33,6 @@ describe("test reset password route", function () {
|
|||
};
|
||||
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
authSession.userid = "user";
|
||||
authSession.email = "user@example.com";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
|
||||
const options = {
|
||||
inMemoryOnly: true
|
||||
|
@ -65,54 +59,72 @@ describe("test reset password route", function () {
|
|||
} as any;
|
||||
|
||||
res = ExpressMock.ResponseMock();
|
||||
AuthenticationSession.get(req as any)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession.userid = "user";
|
||||
authSession.email = "user@example.com";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
});
|
||||
});
|
||||
|
||||
describe("test reset password post", () => {
|
||||
it("should update the password and reset auth_session for reauthentication", function () {
|
||||
authSession.identity_check = {
|
||||
userid: "user",
|
||||
challenge: "reset-password"
|
||||
};
|
||||
req.body = {};
|
||||
req.body.password = "new-password";
|
||||
|
||||
(serverVariables.ldapPasswordUpdater.updatePassword as sinon.SinonStub).returns(BluebirdPromise.resolve());
|
||||
return PasswordResetFormPost.default(req as any, res as any)
|
||||
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.identity_check = {
|
||||
userid: "user",
|
||||
challenge: "reset-password"
|
||||
};
|
||||
return PasswordResetFormPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () {
|
||||
const authSession = AuthenticationSession.get(req as any);
|
||||
return AuthenticationSession.get(req as any);
|
||||
}).then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
assert.equal(res.status.getCall(0).args[0], 204);
|
||||
assert.equal(authSession.first_factor, false);
|
||||
assert.equal(authSession.second_factor, false);
|
||||
assert.equal(_authSession.first_factor, false);
|
||||
assert.equal(_authSession.second_factor, false);
|
||||
return BluebirdPromise.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail if identity_challenge does not exist", function (done) {
|
||||
authSession.identity_check = {
|
||||
userid: "user",
|
||||
challenge: undefined
|
||||
};
|
||||
res.send = Sinon.spy(function () {
|
||||
assert.equal(res.status.getCall(0).args[0], 403);
|
||||
done();
|
||||
});
|
||||
PasswordResetFormPost.default(req as any, res as any);
|
||||
it("should fail if identity_challenge does not exist", function () {
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.identity_check = {
|
||||
userid: "user",
|
||||
challenge: undefined
|
||||
};
|
||||
return PasswordResetFormPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () {
|
||||
assert.equal(res.status.getCall(0).args[0], 403);
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail when ldap fails", function (done) {
|
||||
authSession.identity_check = {
|
||||
challenge: "reset-password",
|
||||
userid: "user"
|
||||
};
|
||||
it("should fail when ldap fails", function () {
|
||||
req.body = {};
|
||||
req.body.password = "new-password";
|
||||
|
||||
(serverVariables.ldapPasswordUpdater.updatePassword as Sinon.SinonStub).returns(BluebirdPromise.reject("Internal error with LDAP"));
|
||||
res.send = Sinon.spy(function () {
|
||||
assert.equal(res.status.getCall(0).args[0], 500);
|
||||
done();
|
||||
});
|
||||
PasswordResetFormPost.default(req as any, res as any);
|
||||
(serverVariables.ldapPasswordUpdater.updatePassword as Sinon.SinonStub)
|
||||
.returns(BluebirdPromise.reject("Internal error with LDAP"));
|
||||
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.identity_check = {
|
||||
challenge: "reset-password",
|
||||
userid: "user"
|
||||
};
|
||||
return PasswordResetFormPost.default(req as any, res as any);
|
||||
}).then(function () {
|
||||
assert.equal(res.status.getCall(0).args[0], 500);
|
||||
return BluebirdPromise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,11 +23,6 @@ describe("test totp register", function () {
|
|||
req.session = {};
|
||||
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
authSession.userid = "user";
|
||||
authSession.email = "user@example.com";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
|
||||
req.headers = {};
|
||||
req.headers.host = "localhost";
|
||||
|
@ -43,6 +38,15 @@ describe("test totp register", function () {
|
|||
mocks.userDataStore.saveTOTPSecretStub.returns(BluebirdPromise.resolve({}));
|
||||
|
||||
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);
|
||||
|
|
|
@ -23,6 +23,7 @@ describe("test totp route", function () {
|
|||
const app_get = sinon.stub();
|
||||
req = {
|
||||
app: {
|
||||
get: sinon.stub().returns({ logger: winston })
|
||||
},
|
||||
body: {
|
||||
token: "abc"
|
||||
|
@ -30,11 +31,6 @@ describe("test totp route", function () {
|
|||
session: {}
|
||||
};
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
authSession.userid = "user";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
|
||||
const mocks = ServerVariablesMock.mock(req.app);
|
||||
res = ExpressMock.ResponseMock();
|
||||
|
||||
|
@ -52,6 +48,14 @@ describe("test totp route", function () {
|
|||
mocks.logger = winston;
|
||||
mocks.totpValidator = totpValidator;
|
||||
mocks.config = config;
|
||||
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (_authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession = _authSession;
|
||||
authSession.userid = "user";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -23,11 +23,6 @@ describe("test register handler", function () {
|
|||
mocks.logger = winston;
|
||||
req.session = {};
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
authSession.userid = "user";
|
||||
authSession.email = "user@example.com";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
req.headers = {};
|
||||
req.headers.host = "localhost";
|
||||
|
||||
|
@ -44,6 +39,15 @@ describe("test register handler", function () {
|
|||
res.send = sinon.spy();
|
||||
res.json = 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);
|
||||
|
|
|
@ -17,7 +17,6 @@ describe("test u2f routes: register", function () {
|
|||
let req: ExpressMock.RequestMock;
|
||||
let res: ExpressMock.ResponseMock;
|
||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
|
||||
beforeEach(function () {
|
||||
req = ExpressMock.RequestMock();
|
||||
|
@ -26,16 +25,6 @@ describe("test u2f routes: register", function () {
|
|||
mocks.logger = winston;
|
||||
|
||||
req.session = {};
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
authSession.userid = "user";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
authSession.identity_check = {
|
||||
challenge: "u2f-register",
|
||||
userid: "user"
|
||||
};
|
||||
|
||||
req.headers = {};
|
||||
req.headers.host = "localhost";
|
||||
|
||||
|
@ -50,6 +39,18 @@ describe("test u2f routes: register", function () {
|
|||
res.send = sinon.spy();
|
||||
res.json = 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);
|
||||
|
@ -64,16 +65,22 @@ describe("test u2f routes: register", function () {
|
|||
};
|
||||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.checkRegistration.returns(BluebirdPromise.resolve(expectedStatus));
|
||||
|
||||
authSession.register_request = {
|
||||
appId: "app",
|
||||
challenge: "challenge",
|
||||
keyHandle: "key",
|
||||
version: "U2F_V2"
|
||||
};
|
||||
mocks.u2f = u2f_mock;
|
||||
return U2FRegisterPost.default(req as any, res as any)
|
||||
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.register_request = {
|
||||
appId: "app",
|
||||
challenge: "challenge",
|
||||
keyHandle: "key",
|
||||
version: "U2F_V2"
|
||||
};
|
||||
return U2FRegisterPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () {
|
||||
return AuthenticationSession.get(req as any);
|
||||
})
|
||||
.then(function (authSession) {
|
||||
assert.equal("user", mocks.userDataStore.saveU2FRegistrationStub.getCall(0).args[0]);
|
||||
assert.equal(authSession.identity_check, undefined);
|
||||
});
|
||||
|
@ -83,15 +90,19 @@ describe("test u2f routes: register", function () {
|
|||
const user_key_container = {};
|
||||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.checkRegistration.returns({ errorCode: 500 });
|
||||
|
||||
authSession.register_request = {
|
||||
appId: "app",
|
||||
challenge: "challenge",
|
||||
keyHandle: "key",
|
||||
version: "U2F_V2"
|
||||
};
|
||||
mocks.u2f = u2f_mock;
|
||||
return U2FRegisterPost.default(req as any, res as any)
|
||||
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.register_request = {
|
||||
appId: "app",
|
||||
challenge: "challenge",
|
||||
keyHandle: "key",
|
||||
version: "U2F_V2"
|
||||
};
|
||||
|
||||
return U2FRegisterPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||
.catch(function () {
|
||||
assert.equal(500, res.status.getCall(0).args[0]);
|
||||
|
@ -104,9 +115,12 @@ describe("test u2f routes: register", function () {
|
|||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.checkRegistration.returns(BluebirdPromise.resolve());
|
||||
|
||||
authSession.register_request = undefined;
|
||||
mocks.u2f = u2f_mock;
|
||||
return U2FRegisterPost.default(req as any, res as any)
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.register_request = undefined;
|
||||
return U2FRegisterPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||
.catch(function () {
|
||||
assert.equal(403, res.status.getCall(0).args[0]);
|
||||
|
@ -119,9 +133,12 @@ describe("test u2f routes: register", function () {
|
|||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.checkRegistration.returns(BluebirdPromise.resolve());
|
||||
|
||||
authSession.register_request = undefined;
|
||||
mocks.u2f = u2f_mock;
|
||||
return U2FRegisterPost.default(req as any, res as any)
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.register_request = undefined;
|
||||
return U2FRegisterPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||
.catch(function () {
|
||||
assert.equal(403, res.status.getCall(0).args[0]);
|
||||
|
@ -130,8 +147,11 @@ describe("test u2f routes: register", function () {
|
|||
});
|
||||
|
||||
it("should return forbidden error when identity has not been verified", function () {
|
||||
authSession.identity_check = undefined;
|
||||
return U2FRegisterPost.default(req as any, res as any)
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession) {
|
||||
authSession.identity_check = undefined;
|
||||
return U2FRegisterPost.default(req as any, res as any);
|
||||
})
|
||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
||||
.catch(function () {
|
||||
assert.equal(403, res.status.getCall(0).args[0]);
|
||||
|
|
|
@ -14,82 +14,84 @@ import ServerVariablesMock = require("../../../../mocks/ServerVariablesMock");
|
|||
import U2f = require("u2f");
|
||||
|
||||
describe("test u2f routes: register_request", function () {
|
||||
let req: ExpressMock.RequestMock;
|
||||
let res: ExpressMock.ResponseMock;
|
||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
let req: ExpressMock.RequestMock;
|
||||
let res: ExpressMock.ResponseMock;
|
||||
let mocks: ServerVariablesMock.ServerVariablesMock;
|
||||
let authSession: AuthenticationSession.AuthenticationSession;
|
||||
|
||||
beforeEach(function () {
|
||||
req = ExpressMock.RequestMock();
|
||||
req.app = {};
|
||||
mocks = ServerVariablesMock.mock(req.app);
|
||||
mocks.logger = winston;
|
||||
req.session = {};
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
beforeEach(function () {
|
||||
req = ExpressMock.RequestMock();
|
||||
req.app = {};
|
||||
mocks = ServerVariablesMock.mock(req.app);
|
||||
mocks.logger = winston;
|
||||
req.session = {};
|
||||
AuthenticationSession.reset(req as any);
|
||||
|
||||
req.headers = {};
|
||||
req.headers.host = "localhost";
|
||||
|
||||
const options = {
|
||||
inMemoryOnly: true
|
||||
};
|
||||
|
||||
|
||||
mocks.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||
|
||||
res = ExpressMock.ResponseMock();
|
||||
res.send = sinon.spy();
|
||||
res.json = 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"
|
||||
challenge: "u2f-register",
|
||||
userid: "user"
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
req.headers = {};
|
||||
req.headers.host = "localhost";
|
||||
describe("test registration request", () => {
|
||||
it("should send back the registration request and save it in the session", function () {
|
||||
const expectedRequest = {
|
||||
test: "abc"
|
||||
};
|
||||
const user_key_container = {};
|
||||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.request.returns(BluebirdPromise.resolve(expectedRequest));
|
||||
|
||||
const options = {
|
||||
inMemoryOnly: true
|
||||
};
|
||||
|
||||
|
||||
mocks.userDataStore.saveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||
mocks.userDataStore.retrieveU2FRegistrationStub.returns(BluebirdPromise.resolve({}));
|
||||
|
||||
res = ExpressMock.ResponseMock();
|
||||
res.send = sinon.spy();
|
||||
res.json = sinon.spy();
|
||||
res.status = sinon.spy();
|
||||
mocks.u2f = u2f_mock;
|
||||
return U2FRegisterRequestGet.default(req as any, res as any)
|
||||
.then(function () {
|
||||
assert.deepEqual(expectedRequest, res.json.getCall(0).args[0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("test registration request", () => {
|
||||
it("should send back the registration request and save it in the session", function () {
|
||||
const expectedRequest = {
|
||||
test: "abc"
|
||||
};
|
||||
const user_key_container = {};
|
||||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.request.returns(BluebirdPromise.resolve(expectedRequest));
|
||||
it("should return internal error on registration request", function (done) {
|
||||
res.send = sinon.spy(function (data: any) {
|
||||
assert.equal(500, res.status.getCall(0).args[0]);
|
||||
done();
|
||||
});
|
||||
const user_key_container = {};
|
||||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.request.returns(BluebirdPromise.reject("Internal error"));
|
||||
|
||||
mocks.u2f = u2f_mock;
|
||||
return U2FRegisterRequestGet.default(req as any, res as any)
|
||||
.then(function () {
|
||||
assert.deepEqual(expectedRequest, res.json.getCall(0).args[0]);
|
||||
});
|
||||
});
|
||||
mocks.u2f = u2f_mock;
|
||||
U2FRegisterRequestGet.default(req as any, res as any);
|
||||
});
|
||||
|
||||
it("should return internal error on registration request", function (done) {
|
||||
res.send = sinon.spy(function (data: any) {
|
||||
assert.equal(500, res.status.getCall(0).args[0]);
|
||||
done();
|
||||
});
|
||||
const user_key_container = {};
|
||||
const u2f_mock = U2FMock.U2FMock();
|
||||
u2f_mock.request.returns(BluebirdPromise.reject("Internal error"));
|
||||
|
||||
mocks.u2f = u2f_mock;
|
||||
U2FRegisterRequestGet.default(req as any, res as any);
|
||||
});
|
||||
|
||||
it("should return forbidden if identity has not been verified", function (done) {
|
||||
res.send = sinon.spy(function (data: any) {
|
||||
assert.equal(403, res.status.getCall(0).args[0]);
|
||||
done();
|
||||
});
|
||||
authSession.identity_check = undefined;
|
||||
U2FRegisterRequestGet.default(req as any, res as any);
|
||||
it("should return forbidden if identity has not been verified", function () {
|
||||
authSession.identity_check = undefined;
|
||||
return U2FRegisterRequestGet.default(req as any, res as any)
|
||||
.then(function () {
|
||||
assert.equal(403, res.status.getCall(0).args[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -27,14 +27,6 @@ describe("test u2f routes: sign", function () {
|
|||
|
||||
req.session = {};
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
authSession.userid = "user";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
authSession.identity_check = {
|
||||
challenge: "u2f-register",
|
||||
userid: "user"
|
||||
};
|
||||
req.headers = {};
|
||||
req.headers.host = "localhost";
|
||||
|
||||
|
@ -46,6 +38,18 @@ describe("test u2f routes: sign", function () {
|
|||
res.send = sinon.spy();
|
||||
res.json = 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 () {
|
||||
|
|
|
@ -31,14 +31,6 @@ describe("test u2f routes: sign_request", function () {
|
|||
req.session = {};
|
||||
|
||||
AuthenticationSession.reset(req as any);
|
||||
authSession = AuthenticationSession.get(req as any);
|
||||
authSession.userid = "user";
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = false;
|
||||
authSession.identity_check = {
|
||||
challenge: "u2f-register",
|
||||
userid: "user"
|
||||
};
|
||||
|
||||
req.headers = {};
|
||||
req.headers.host = "localhost";
|
||||
|
@ -51,6 +43,18 @@ describe("test u2f routes: sign_request", function () {
|
|||
res.send = sinon.spy();
|
||||
res.json = 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 () {
|
||||
|
|
|
@ -24,6 +24,9 @@ describe("test authentication token verification", function () {
|
|||
|
||||
req = ExpressMock.RequestMock();
|
||||
res = ExpressMock.ResponseMock();
|
||||
req.app = {
|
||||
get: sinon.stub().returns({ logger: winston })
|
||||
};
|
||||
req.session = {};
|
||||
AuthenticationSession.reset(req as any);
|
||||
req.headers = {};
|
||||
|
@ -37,12 +40,13 @@ describe("test authentication token verification", function () {
|
|||
it("should be already authenticated", function () {
|
||||
req.session = {};
|
||||
AuthenticationSession.reset(req as any);
|
||||
const authSession = AuthenticationSession.get(req as any);
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = true;
|
||||
authSession.userid = "myuser";
|
||||
|
||||
return VerifyGet.default(req as express.Request, res as any)
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = true;
|
||||
authSession.userid = "myuser";
|
||||
return VerifyGet.default(req as express.Request, res as any);
|
||||
})
|
||||
.then(function () {
|
||||
assert.equal(204, res.status.getCall(0).args[0]);
|
||||
});
|
||||
|
@ -113,23 +117,25 @@ describe("test authentication token verification", function () {
|
|||
});
|
||||
|
||||
it("should not be authenticated when domain is not allowed for user", function () {
|
||||
const authSession = AuthenticationSession.get(req as any);
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = true;
|
||||
authSession.userid = "myuser";
|
||||
return AuthenticationSession.get(req as any)
|
||||
.then(function (authSession: AuthenticationSession.AuthenticationSession) {
|
||||
authSession.first_factor = true;
|
||||
authSession.second_factor = true;
|
||||
authSession.userid = "myuser";
|
||||
|
||||
req.headers.host = "test.example.com";
|
||||
req.headers.host = "test.example.com";
|
||||
|
||||
accessController.isDomainAllowedForUser.returns(false);
|
||||
accessController.isDomainAllowedForUser.withArgs("test.example.com", "user", ["group1", "group2"]).returns(true);
|
||||
accessController.isDomainAllowedForUser.returns(false);
|
||||
accessController.isDomainAllowedForUser.withArgs("test.example.com", "user", ["group1", "group2"]).returns(true);
|
||||
|
||||
return test_unauthorized_403({
|
||||
first_factor: true,
|
||||
second_factor: true,
|
||||
userid: "user",
|
||||
groups: ["group1", "group2"],
|
||||
email: undefined
|
||||
});
|
||||
return test_unauthorized_403({
|
||||
first_factor: true,
|
||||
second_factor: true,
|
||||
userid: "user",
|
||||
groups: ["group1", "group2"],
|
||||
email: undefined
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue