Fix endpoints redirection on errors
From this commit on, api endpoints reply with a 401 error code and non api endpoints redirect to /error/40X. This commit also fixes missing restrictions on /loggedin (the "already logged in page). This was not a security issue, though. The change also makes error pages automatically redirect the user after few seconds based on the referrer or the default_redirection_url if provided in the configuration. Warning: The old /verify endpoint of the REST API has moved to /api/verify. You will need to update your nginx configuration to take this change into account.pull/187/head
parent
837884ef0d
commit
6b78240d39
|
@ -86,7 +86,7 @@ http {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header Content-Length "";
|
proxy_set_header Content-Length "";
|
||||||
|
|
||||||
proxy_pass http://authelia/verify;
|
proxy_pass http://authelia/api/verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
@ -143,7 +143,7 @@ http {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header Content-Length "";
|
proxy_set_header Content-Length "";
|
||||||
|
|
||||||
proxy_pass http://authelia/verify;
|
proxy_pass http://authelia/api/verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
@ -183,7 +183,7 @@ http {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header Content-Length "";
|
proxy_set_header Content-Length "";
|
||||||
|
|
||||||
proxy_pass http://authelia/verify;
|
proxy_pass http://authelia/api/verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
@ -223,7 +223,7 @@ http {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header Content-Length "";
|
proxy_set_header Content-Length "";
|
||||||
|
|
||||||
proxy_pass http://authelia/verify;
|
proxy_pass http://authelia/api/verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
@ -263,7 +263,7 @@ http {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header Content-Length "";
|
proxy_set_header Content-Length "";
|
||||||
|
|
||||||
proxy_pass http://authelia/verify;
|
proxy_pass http://authelia/api/verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
|
|
@ -5,10 +5,17 @@ import { IRequestLogger } from "./logging/IRequestLogger";
|
||||||
function replyWithError(req: express.Request, res: express.Response,
|
function replyWithError(req: express.Request, res: express.Response,
|
||||||
code: number, logger: IRequestLogger, body?: Object): (err: Error) => void {
|
code: number, logger: IRequestLogger, body?: Object): (err: Error) => void {
|
||||||
return function (err: Error): void {
|
return function (err: Error): void {
|
||||||
logger.error(req, "Reply with error %d: %s", code, err.message);
|
if (req.originalUrl.startsWith("/api/") || code == 200) {
|
||||||
logger.debug(req, "%s", err.stack);
|
logger.error(req, "Reply with error %d: %s", code, err.message);
|
||||||
res.status(code);
|
logger.debug(req, "%s", err.stack);
|
||||||
res.send(body);
|
res.status(code);
|
||||||
|
res.send(body);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.error(req, "Redirect to error %d: %s", code, err.message);
|
||||||
|
logger.debug(req, "%s", err.stack);
|
||||||
|
res.redirect("/error/" + code);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,69 +7,84 @@ import Exceptions = require("./Exceptions");
|
||||||
import fs = require("fs");
|
import fs = require("fs");
|
||||||
import ejs = require("ejs");
|
import ejs = require("ejs");
|
||||||
import { IUserDataStore } from "./storage/IUserDataStore";
|
import { IUserDataStore } from "./storage/IUserDataStore";
|
||||||
import express = require("express");
|
import Express = require("express");
|
||||||
import ErrorReplies = require("./ErrorReplies");
|
import ErrorReplies = require("./ErrorReplies");
|
||||||
import { AuthenticationSessionHandler } from "./AuthenticationSessionHandler";
|
import { AuthenticationSessionHandler } from "./AuthenticationSessionHandler";
|
||||||
import { AuthenticationSession } from "../../types/AuthenticationSession";
|
import { AuthenticationSession } from "../../types/AuthenticationSession";
|
||||||
import { ServerVariables } from "./ServerVariables";
|
import { ServerVariables } from "./ServerVariables";
|
||||||
|
|
||||||
import Identity = require("../../types/Identity");
|
import Identity = require("../../types/Identity");
|
||||||
import { IdentityValidationDocument } from "./storage/IdentityValidationDocument";
|
import { IdentityValidationDocument }
|
||||||
|
from "./storage/IdentityValidationDocument";
|
||||||
|
|
||||||
const filePath = __dirname + "/../resources/email-template.ejs";
|
const filePath = __dirname + "/../resources/email-template.ejs";
|
||||||
const email_template = fs.readFileSync(filePath, "utf8");
|
const email_template = fs.readFileSync(filePath, "utf8");
|
||||||
|
|
||||||
// IdentityValidator allows user to go through a identity validation process in two steps:
|
// IdentityValidator allows user to go through a identity validation process
|
||||||
|
// in two steps:
|
||||||
// - Request an operation to be performed (password reset, registration).
|
// - Request an operation to be performed (password reset, registration).
|
||||||
// - Confirm operation with email.
|
// - Confirm operation with email.
|
||||||
|
|
||||||
export interface IdentityValidable {
|
export interface IdentityValidable {
|
||||||
challenge(): string;
|
challenge(): string;
|
||||||
preValidationInit(req: express.Request): BluebirdPromise<Identity.Identity>;
|
preValidationInit(req: Express.Request): BluebirdPromise<Identity.Identity>;
|
||||||
postValidationInit(req: express.Request): BluebirdPromise<void>;
|
postValidationInit(req: Express.Request): BluebirdPromise<void>;
|
||||||
|
|
||||||
// Serves a page after identity check request
|
// Serves a page after identity check request
|
||||||
preValidationResponse(req: express.Request, res: express.Response): void;
|
preValidationResponse(req: Express.Request, res: Express.Response): void;
|
||||||
// Serves the page if identity validated
|
// Serves the page if identity validated
|
||||||
postValidationResponse(req: express.Request, res: express.Response): void;
|
postValidationResponse(req: Express.Request, res: Express.Response): void;
|
||||||
mailSubject(): string;
|
mailSubject(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAndSaveToken(userid: string, challenge: string, userDataStore: IUserDataStore)
|
function createAndSaveToken(userid: string, challenge: string,
|
||||||
|
userDataStore: IUserDataStore)
|
||||||
: BluebirdPromise<string> {
|
: BluebirdPromise<string> {
|
||||||
const five_minutes = 4 * 60 * 1000;
|
const five_minutes = 4 * 60 * 1000;
|
||||||
const token = randomstring.generate({ length: 64 });
|
const token = randomstring.generate({ length: 64 });
|
||||||
const that = this;
|
const that = this;
|
||||||
|
|
||||||
return userDataStore.produceIdentityValidationToken(userid, token, challenge, five_minutes)
|
return userDataStore.produceIdentityValidationToken(userid, token, challenge,
|
||||||
|
five_minutes)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return BluebirdPromise.resolve(token);
|
return BluebirdPromise.resolve(token);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function consumeToken(token: string, challenge: string, userDataStore: IUserDataStore)
|
function consumeToken(token: string, challenge: string,
|
||||||
|
userDataStore: IUserDataStore)
|
||||||
: BluebirdPromise<IdentityValidationDocument> {
|
: BluebirdPromise<IdentityValidationDocument> {
|
||||||
return userDataStore.consumeIdentityValidationToken(token, challenge);
|
return userDataStore.consumeIdentityValidationToken(token, challenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function register(app: express.Application, pre_validation_endpoint: string,
|
export function register(app: Express.Application,
|
||||||
post_validation_endpoint: string, handler: IdentityValidable, vars: ServerVariables) {
|
pre_validation_endpoint: string,
|
||||||
app.get(pre_validation_endpoint, get_start_validation(handler, post_validation_endpoint, vars));
|
post_validation_endpoint: string,
|
||||||
app.get(post_validation_endpoint, get_finish_validation(handler, vars));
|
handler: IdentityValidable,
|
||||||
|
vars: ServerVariables) {
|
||||||
|
|
||||||
|
app.get(pre_validation_endpoint,
|
||||||
|
get_start_validation(handler, post_validation_endpoint, vars));
|
||||||
|
app.get(post_validation_endpoint,
|
||||||
|
get_finish_validation(handler, vars));
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIdentityToken(req: express.Request, identityToken: string): BluebirdPromise<void> {
|
function checkIdentityToken(req: Express.Request, identityToken: string)
|
||||||
|
: BluebirdPromise<void> {
|
||||||
if (!identityToken)
|
if (!identityToken)
|
||||||
return BluebirdPromise.reject(new Exceptions.AccessDeniedError("No identity token provided"));
|
return BluebirdPromise.reject(
|
||||||
|
new Exceptions.AccessDeniedError("No identity token provided"));
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_finish_validation(handler: IdentityValidable,
|
export function get_finish_validation(handler: IdentityValidable,
|
||||||
vars: ServerVariables)
|
vars: ServerVariables)
|
||||||
: express.RequestHandler {
|
: Express.RequestHandler {
|
||||||
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return function (req: Express.Request, res: Express.Response)
|
||||||
|
: BluebirdPromise<void> {
|
||||||
let authSession: AuthenticationSession;
|
let authSession: AuthenticationSession;
|
||||||
const identityToken = objectPath.get<express.Request, string>(req, "query.identity_token");
|
const identityToken = objectPath.get<Express.Request, string>(
|
||||||
|
req, "query.identity_token");
|
||||||
vars.logger.debug(req, "Identity token provided is %s", identityToken);
|
vars.logger.debug(req, "Identity token provided is %s", identityToken);
|
||||||
|
|
||||||
return checkIdentityToken(req, identityToken)
|
return checkIdentityToken(req, identityToken)
|
||||||
|
@ -78,7 +93,8 @@ export function get_finish_validation(handler: IdentityValidable,
|
||||||
return handler.postValidationInit(req);
|
return handler.postValidationInit(req);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return consumeToken(identityToken, handler.challenge(), vars.userDataStore);
|
return consumeToken(identityToken, handler.challenge(),
|
||||||
|
vars.userDataStore);
|
||||||
})
|
})
|
||||||
.then(function (doc: IdentityValidationDocument) {
|
.then(function (doc: IdentityValidationDocument) {
|
||||||
authSession.identity_check = {
|
authSession.identity_check = {
|
||||||
|
@ -95,8 +111,9 @@ export function get_finish_validation(handler: IdentityValidable,
|
||||||
export function get_start_validation(handler: IdentityValidable,
|
export function get_start_validation(handler: IdentityValidable,
|
||||||
postValidationEndpoint: string,
|
postValidationEndpoint: string,
|
||||||
vars: ServerVariables)
|
vars: ServerVariables)
|
||||||
: express.RequestHandler {
|
: Express.RequestHandler {
|
||||||
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
return function (req: Express.Request, res: Express.Response)
|
||||||
|
: BluebirdPromise<void> {
|
||||||
let identity: Identity.Identity;
|
let identity: Identity.Identity;
|
||||||
|
|
||||||
return handler.preValidationInit(req)
|
return handler.preValidationInit(req)
|
||||||
|
@ -104,20 +121,24 @@ export function get_start_validation(handler: IdentityValidable,
|
||||||
identity = id;
|
identity = id;
|
||||||
const email = identity.email;
|
const email = identity.email;
|
||||||
const userid = identity.userid;
|
const userid = identity.userid;
|
||||||
vars.logger.info(req, "Start identity validation of user \"%s\"", userid);
|
vars.logger.info(req, "Start identity validation of user \"%s\"",
|
||||||
|
userid);
|
||||||
|
|
||||||
if (!(email && userid))
|
if (!(email && userid))
|
||||||
return BluebirdPromise.reject(new Exceptions.IdentityError(
|
return BluebirdPromise.reject(new Exceptions.IdentityError(
|
||||||
"Missing user id or email address"));
|
"Missing user id or email address"));
|
||||||
|
|
||||||
return createAndSaveToken(userid, handler.challenge(), vars.userDataStore);
|
return createAndSaveToken(userid, handler.challenge(),
|
||||||
|
vars.userDataStore);
|
||||||
})
|
})
|
||||||
.then(function (token: string) {
|
.then(function (token: string) {
|
||||||
const host = req.get("Host");
|
const host = req.get("Host");
|
||||||
const link_url = util.format("https://%s%s?identity_token=%s", host,
|
const link_url = util.format("https://%s%s?identity_token=%s", host,
|
||||||
postValidationEndpoint, token);
|
postValidationEndpoint, token);
|
||||||
vars.logger.info(req, "Notification sent to user \"%s\"", identity.userid);
|
vars.logger.info(req, "Notification sent to user \"%s\"",
|
||||||
return vars.notifier.notify(identity.email, handler.mailSubject(), link_url);
|
identity.userid);
|
||||||
|
return vars.notifier.notify(identity.email, handler.mailSubject(),
|
||||||
|
link_url);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
handler.preValidationResponse(req, res);
|
handler.preValidationResponse(req, res);
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
|
import redirector from "../redirector";
|
||||||
|
import { ServerVariables } from "../../../ServerVariables";
|
||||||
|
|
||||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
export default function (vars: ServerVariables) {
|
||||||
res.render("errors/401");
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
|
const redirectionUrl = redirector(req, vars);
|
||||||
|
res.render("errors/401", {
|
||||||
|
redirection_url: redirectionUrl
|
||||||
|
});
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
|
import redirector from "../redirector";
|
||||||
|
import { ServerVariables } from "../../../ServerVariables";
|
||||||
|
|
||||||
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
export default function (vars: ServerVariables) {
|
||||||
res.render("errors/403");
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
||||||
|
const redirectionUrl = redirector(req, vars);
|
||||||
|
res.render("errors/403", {
|
||||||
|
redirection_url: redirectionUrl
|
||||||
|
});
|
||||||
return BluebirdPromise.resolve();
|
return BluebirdPromise.resolve();
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import Express = require("express");
|
||||||
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
|
|
||||||
|
export default function (req: Express.Request, vars: ServerVariables): string {
|
||||||
|
let redirectionUrl: string;
|
||||||
|
|
||||||
|
if (req.headers && req.headers["referer"])
|
||||||
|
redirectionUrl = "" + req.headers["referer"];
|
||||||
|
else if (vars.config.default_redirection_url)
|
||||||
|
redirectionUrl = vars.config.default_redirection_url;
|
||||||
|
|
||||||
|
return redirectionUrl;
|
||||||
|
}
|
|
@ -101,17 +101,21 @@ function setupU2f(app: Express.Application, vars: ServerVariables) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupResetPassword(app: Express.Application, vars: ServerVariables) {
|
function setupResetPassword(app: Express.Application, vars: ServerVariables) {
|
||||||
IdentityCheckMiddleware.register(app, Endpoints.RESET_PASSWORD_IDENTITY_START_GET,
|
IdentityCheckMiddleware.register(app,
|
||||||
|
Endpoints.RESET_PASSWORD_IDENTITY_START_GET,
|
||||||
Endpoints.RESET_PASSWORD_IDENTITY_FINISH_GET,
|
Endpoints.RESET_PASSWORD_IDENTITY_FINISH_GET,
|
||||||
new ResetPasswordIdentityHandler(vars.logger, vars.ldapEmailsRetriever), vars);
|
new ResetPasswordIdentityHandler(vars.logger, vars.ldapEmailsRetriever),
|
||||||
|
vars);
|
||||||
|
|
||||||
app.get(Endpoints.RESET_PASSWORD_REQUEST_GET, ResetPasswordRequestPost.default);
|
app.get(Endpoints.RESET_PASSWORD_REQUEST_GET,
|
||||||
app.post(Endpoints.RESET_PASSWORD_FORM_POST, ResetPasswordFormPost.default(vars));
|
ResetPasswordRequestPost.default);
|
||||||
|
app.post(Endpoints.RESET_PASSWORD_FORM_POST,
|
||||||
|
ResetPasswordFormPost.default(vars));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupErrors(app: Express.Application) {
|
function setupErrors(app: Express.Application, vars: ServerVariables) {
|
||||||
app.get(Endpoints.ERROR_401_GET, Error401Get.default);
|
app.get(Endpoints.ERROR_401_GET, Error401Get.default(vars));
|
||||||
app.get(Endpoints.ERROR_403_GET, Error403Get.default);
|
app.get(Endpoints.ERROR_403_GET, Error403Get.default(vars));
|
||||||
app.get(Endpoints.ERROR_404_GET, Error404Get.default);
|
app.get(Endpoints.ERROR_404_GET, Error404Get.default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +128,7 @@ export class RestApi {
|
||||||
vars.config.authentication_methods),
|
vars.config.authentication_methods),
|
||||||
RequireValidatedFirstFactor.middleware(vars.logger),
|
RequireValidatedFirstFactor.middleware(vars.logger),
|
||||||
SecondFactorGet.default(vars));
|
SecondFactorGet.default(vars));
|
||||||
|
|
||||||
app.get(Endpoints.LOGOUT_GET, LogoutGet.default);
|
app.get(Endpoints.LOGOUT_GET, LogoutGet.default);
|
||||||
|
|
||||||
app.get(Endpoints.VERIFY_GET, VerifyGet.default(vars));
|
app.get(Endpoints.VERIFY_GET, VerifyGet.default(vars));
|
||||||
|
@ -132,8 +137,10 @@ export class RestApi {
|
||||||
setupTotp(app, vars);
|
setupTotp(app, vars);
|
||||||
setupU2f(app, vars);
|
setupU2f(app, vars);
|
||||||
setupResetPassword(app, vars);
|
setupResetPassword(app, vars);
|
||||||
setupErrors(app);
|
setupErrors(app, vars);
|
||||||
|
|
||||||
app.get(Endpoints.LOGGED_IN, LoggedIn.default(vars));
|
app.get(Endpoints.LOGGED_IN,
|
||||||
|
RequireValidatedFirstFactor.middleware(vars.logger),
|
||||||
|
LoggedIn.default(vars));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,9 @@ block form-header
|
||||||
|
|
||||||
block content
|
block content
|
||||||
img(class="header-img" src="/img/warning.png" alt="warning")
|
img(class="header-img" src="/img/warning.png" alt="warning")
|
||||||
p Please <a href="/">log in</a> to access this resource.
|
if redirection_url
|
||||||
|
p You are not authorized to access this resource.<br/><br/>
|
||||||
|
| Please click <a href=#{redirection_url}>here</a> if you are not
|
||||||
|
| redirected in few seconds.
|
||||||
|
else
|
||||||
|
p You are not authorized to access this resource.
|
|
@ -8,4 +8,9 @@ block form-header
|
||||||
|
|
||||||
block content
|
block content
|
||||||
img(class="header-img" src="/img/warning.png" alt="warning")
|
img(class="header-img" src="/img/warning.png" alt="warning")
|
||||||
p You are not authorized to access this resource.
|
if redirection_url
|
||||||
|
p You don't have enough privileges to access this resource.<br/><br/>
|
||||||
|
| Please click <a href=#{redirection_url}>here</a> if you are not
|
||||||
|
| redirected in few seconds.
|
||||||
|
else
|
||||||
|
p You don't have enough privileges to access this resource.
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
import sinon = require("sinon");
|
import sinon = require("sinon");
|
||||||
import IdentityValidator = require("../src/lib/IdentityCheckMiddleware");
|
import IdentityValidator = require("../src/lib/IdentityCheckMiddleware");
|
||||||
import { AuthenticationSessionHandler } from "../src/lib/AuthenticationSessionHandler";
|
import { AuthenticationSessionHandler }
|
||||||
|
from "../src/lib/AuthenticationSessionHandler";
|
||||||
import { AuthenticationSession } from "../types/AuthenticationSession";
|
import { AuthenticationSession } from "../types/AuthenticationSession";
|
||||||
import { UserDataStore } from "../src/lib/storage/UserDataStore";
|
import { UserDataStore } from "../src/lib/storage/UserDataStore";
|
||||||
import exceptions = require("../src/lib/Exceptions");
|
import exceptions = require("../src/lib/Exceptions");
|
||||||
|
@ -13,7 +14,8 @@ import ExpressMock = require("./mocks/express");
|
||||||
import NotifierMock = require("./mocks/Notifier");
|
import NotifierMock = require("./mocks/Notifier");
|
||||||
import IdentityValidatorMock = require("./mocks/IdentityValidator");
|
import IdentityValidatorMock = require("./mocks/IdentityValidator");
|
||||||
import { RequestLoggerStub } from "./mocks/RequestLoggerStub";
|
import { RequestLoggerStub } from "./mocks/RequestLoggerStub";
|
||||||
import { ServerVariablesMock, ServerVariablesMockBuilder } from "./mocks/ServerVariablesMockBuilder";
|
import { ServerVariablesMock, ServerVariablesMockBuilder }
|
||||||
|
from "./mocks/ServerVariablesMockBuilder";
|
||||||
|
|
||||||
|
|
||||||
describe("test identity check process", function () {
|
describe("test identity check process", function () {
|
||||||
|
@ -36,17 +38,18 @@ describe("test identity check process", function () {
|
||||||
|
|
||||||
identityValidable = IdentityValidatorMock.IdentityValidableMock();
|
identityValidable = IdentityValidatorMock.IdentityValidableMock();
|
||||||
|
|
||||||
|
|
||||||
req.headers = {};
|
req.headers = {};
|
||||||
req.session = {};
|
req.originalUrl = "/non-api/xxx";
|
||||||
req.session = {};
|
req.session = {};
|
||||||
|
|
||||||
req.query = {};
|
req.query = {};
|
||||||
req.app = {};
|
req.app = {};
|
||||||
|
|
||||||
mocks.notifier.notifyStub.returns(BluebirdPromise.resolve());
|
mocks.notifier.notifyStub.returns(BluebirdPromise.resolve());
|
||||||
mocks.userDataStore.produceIdentityValidationTokenStub.returns(Promise.resolve());
|
mocks.userDataStore.produceIdentityValidationTokenStub
|
||||||
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(Promise.resolve({ userId: "user" }));
|
.returns(Promise.resolve());
|
||||||
|
mocks.userDataStore.consumeIdentityValidationTokenStub
|
||||||
|
.returns(Promise.resolve({ userId: "user" }));
|
||||||
|
|
||||||
app = express();
|
app = express();
|
||||||
app_get = sinon.stub(app, "get");
|
app_get = sinon.stub(app, "get");
|
||||||
|
@ -58,112 +61,142 @@ describe("test identity check process", function () {
|
||||||
app_post.restore();
|
app_post.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("test start GET", test_start_get_handler);
|
describe("test start GET", function () {
|
||||||
describe("test finish GET", test_finish_get_handler);
|
it("should redirect to error 401 if pre validation initialization \
|
||||||
|
throws a first factor error", function () {
|
||||||
|
identityValidable.preValidationInit.returns(BluebirdPromise.reject(
|
||||||
|
new exceptions.FirstFactorValidationError(
|
||||||
|
"Error during prevalidation")));
|
||||||
|
const callback = IdentityValidator.get_start_validation(
|
||||||
|
identityValidable, "/endpoint", vars);
|
||||||
|
|
||||||
function test_start_get_handler() {
|
return callback(req as any, res as any, undefined)
|
||||||
it("should send 401 if pre validation initialization throws a first factor error", function () {
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.reject(new exceptions.FirstFactorValidationError("Error during prevalidation")));
|
.catch(function () {
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
|
});
|
||||||
return callback(req as any, res as any, undefined)
|
});
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
|
||||||
.catch(function () {
|
|
||||||
Assert.equal(res.status.getCall(0).args[0], 401);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should send 401 if email is missing in provided identity", function () {
|
it("should send 401 if email is missing in provided identity", function () {
|
||||||
const identity = { userid: "abc" };
|
const identity = { userid: "abc" };
|
||||||
|
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
identityValidable.preValidationInit
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
.returns(BluebirdPromise.resolve(identity));
|
||||||
|
const callback = IdentityValidator
|
||||||
|
.get_start_validation(identityValidable, "/endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(function () {
|
||||||
|
return BluebirdPromise.reject("Should fail");
|
||||||
|
})
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
Assert.equal(res.status.getCall(0).args[0], 401);
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should send 401 if userid is missing in provided identity", function () {
|
it("should send 401 if userid is missing in provided identity",
|
||||||
const endpoint = "/protected";
|
function () {
|
||||||
const identity = { email: "abc@example.com" };
|
const endpoint = "/protected";
|
||||||
|
const identity = { email: "abc@example.com" };
|
||||||
|
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
identityValidable.preValidationInit
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
.returns(BluebirdPromise.resolve(identity));
|
||||||
|
const callback = IdentityValidator
|
||||||
|
.get_start_validation(identityValidable, "/endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
.then(function () {
|
||||||
.catch(function (err: Error) {
|
return BluebirdPromise.reject(new Error("It should fail"));
|
||||||
Assert.equal(res.status.getCall(0).args[0], 401);
|
})
|
||||||
return BluebirdPromise.resolve();
|
.catch(function (err: Error) {
|
||||||
});
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should issue a token, send an email and return 204", function () {
|
it("should issue a token, send an email and return 204", function () {
|
||||||
const endpoint = "/protected";
|
const endpoint = "/protected";
|
||||||
const identity = { userid: "user", email: "abc@example.com" };
|
const identity = { userid: "user", email: "abc@example.com" };
|
||||||
req.get = sinon.stub().withArgs("Host").returns("localhost");
|
req.get = sinon.stub().withArgs("Host").returns("localhost");
|
||||||
|
|
||||||
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
identityValidable.preValidationInit
|
||||||
const callback = IdentityValidator.get_start_validation(identityValidable, "/finish_endpoint", vars);
|
.returns(BluebirdPromise.resolve(identity));
|
||||||
|
const callback = IdentityValidator
|
||||||
|
.get_start_validation(identityValidable, "/finish_endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert(mocks.notifier.notifyStub.calledOnce);
|
Assert(mocks.notifier.notifyStub.calledOnce);
|
||||||
Assert(mocks.userDataStore.produceIdentityValidationTokenStub.calledOnce);
|
Assert(mocks.userDataStore.produceIdentityValidationTokenStub
|
||||||
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[0], "user");
|
.calledOnce);
|
||||||
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[3], 240000);
|
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub
|
||||||
|
.getCall(0).args[0], "user");
|
||||||
|
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub
|
||||||
|
.getCall(0).args[3], 240000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
function test_finish_get_handler() {
|
|
||||||
|
|
||||||
|
describe("test finish GET", function () {
|
||||||
it("should send 401 if no identity_token is provided", function () {
|
it("should send 401 if no identity_token is provided", function () {
|
||||||
|
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
const callback = IdentityValidator
|
||||||
|
.get_finish_validation(identityValidable, vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(function () {
|
||||||
|
return BluebirdPromise.reject("Should fail");
|
||||||
|
})
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
Assert.equal(res.status.getCall(0).args[0], 401);
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call postValidation if identity_token is provided and still valid", function () {
|
it("should call postValidation if identity_token is provided and still \
|
||||||
req.query.identity_token = "token";
|
valid", function () {
|
||||||
|
req.query.identity_token = "token";
|
||||||
|
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
const callback = IdentityValidator
|
||||||
return callback(req as any, res as any, undefined);
|
.get_finish_validation(identityValidable, vars);
|
||||||
});
|
return callback(req as any, res as any, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
it("should return 401 if identity_token is provided but invalid", function () {
|
it("should return 401 if identity_token is provided but invalid",
|
||||||
req.query.identity_token = "token";
|
function () {
|
||||||
|
req.query.identity_token = "token";
|
||||||
|
|
||||||
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.reject(new Error("Invalid token")));
|
mocks.userDataStore.consumeIdentityValidationTokenStub
|
||||||
|
.returns(BluebirdPromise.reject(new Error("Invalid token")));
|
||||||
|
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
const callback = IdentityValidator
|
||||||
return callback(req as any, res as any, undefined)
|
.get_finish_validation(identityValidable, vars);
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
return callback(req as any, res as any, undefined)
|
||||||
.catch(function () {
|
.then(function () {
|
||||||
Assert.equal(res.status.getCall(0).args[0], 401);
|
return BluebirdPromise.reject("Should fail");
|
||||||
});
|
})
|
||||||
});
|
.catch(function () {
|
||||||
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should set the identity_check session object even if session does not exist yet", function () {
|
it("should set the identity_check session object even if session does \
|
||||||
req.query.identity_token = "token";
|
not exist yet", function () {
|
||||||
|
req.query.identity_token = "token";
|
||||||
|
|
||||||
req.session = {};
|
req.session = {};
|
||||||
const authSession: AuthenticationSession = AuthenticationSessionHandler.get(req as any, vars.logger);
|
const authSession =
|
||||||
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
AuthenticationSessionHandler.get(req as any, vars.logger);
|
||||||
|
const callback = IdentityValidator
|
||||||
|
.get_finish_validation(identityValidable, vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(function () {
|
||||||
.catch(function () {
|
return BluebirdPromise.reject("Should fail");
|
||||||
Assert.equal(authSession.identity_check.userid, "user");
|
})
|
||||||
return BluebirdPromise.resolve();
|
.catch(function () {
|
||||||
});
|
Assert.equal(authSession.identity_check.userid, "user");
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,6 +9,7 @@ export interface RequestMock {
|
||||||
headers?: any;
|
headers?: any;
|
||||||
get?: any;
|
get?: any;
|
||||||
query?: any;
|
query?: any;
|
||||||
|
originalUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResponseMock {
|
export interface ResponseMock {
|
||||||
|
@ -51,6 +52,7 @@ export interface ResponseMock {
|
||||||
|
|
||||||
export function RequestMock(): RequestMock {
|
export function RequestMock(): RequestMock {
|
||||||
return {
|
return {
|
||||||
|
originalUrl: "/non-api/xxx",
|
||||||
app: {
|
app: {
|
||||||
get: sinon.stub()
|
get: sinon.stub()
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,18 +2,60 @@ import Sinon = require("sinon");
|
||||||
import Express = require("express");
|
import Express = require("express");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import Get401 from "../../../../src/lib/routes/error/401/get";
|
import Get401 from "../../../../src/lib/routes/error/401/get";
|
||||||
|
import { ServerVariables } from "../../../../src/lib/ServerVariables";
|
||||||
|
import { ServerVariablesMockBuilder, ServerVariablesMock }
|
||||||
|
from "../../../mocks/ServerVariablesMockBuilder";
|
||||||
|
|
||||||
describe("Server error 401", function () {
|
describe("Server error 401", function () {
|
||||||
it("should render the page", function () {
|
let vars: ServerVariables;
|
||||||
const req = {} as Express.Request;
|
let mocks: ServerVariablesMock;
|
||||||
const res = {
|
let req: any;
|
||||||
render: Sinon.stub()
|
let res: any;
|
||||||
};
|
let renderSpy: Sinon.SinonSpy;
|
||||||
|
|
||||||
return Get401(req, res as any)
|
beforeEach(function () {
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
vars = s.variables;
|
||||||
|
mocks = s.mocks;
|
||||||
|
|
||||||
|
renderSpy = Sinon.spy();
|
||||||
|
req = {
|
||||||
|
headers: {}
|
||||||
|
};
|
||||||
|
res = {
|
||||||
|
render: renderSpy
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set redirection url to the default redirection url", function () {
|
||||||
|
vars.config.default_redirection_url = "http://default-redirection";
|
||||||
|
return Get401(vars)(req, res as any)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert(res.render.calledOnce);
|
Assert(renderSpy.calledOnce);
|
||||||
Assert(res.render.calledWith("errors/401"));
|
Assert(renderSpy.calledWithExactly("errors/401", {
|
||||||
|
redirection_url: "http://default-redirection"
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set redirection url to the referer", function () {
|
||||||
|
req.headers["referer"] = "http://redirection";
|
||||||
|
return Get401(vars)(req, res as any)
|
||||||
|
.then(function () {
|
||||||
|
Assert(renderSpy.calledOnce);
|
||||||
|
Assert(renderSpy.calledWithExactly("errors/401", {
|
||||||
|
redirection_url: "http://redirection"
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render without redirecting the user", function () {
|
||||||
|
return Get401(vars)(req, res as any)
|
||||||
|
.then(function () {
|
||||||
|
Assert(renderSpy.calledOnce);
|
||||||
|
Assert(renderSpy.calledWithExactly("errors/401", {
|
||||||
|
redirection_url: undefined
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -2,18 +2,60 @@ import Sinon = require("sinon");
|
||||||
import Express = require("express");
|
import Express = require("express");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import Get403 from "../../../../src/lib/routes/error/403/get";
|
import Get403 from "../../../../src/lib/routes/error/403/get";
|
||||||
|
import { ServerVariables } from "../../../../src/lib/ServerVariables";
|
||||||
|
import { ServerVariablesMockBuilder, ServerVariablesMock }
|
||||||
|
from "../../../mocks/ServerVariablesMockBuilder";
|
||||||
|
|
||||||
describe("Server error 403", function () {
|
describe("Server error 403", function () {
|
||||||
it("should render the page", function () {
|
let vars: ServerVariables;
|
||||||
const req = {} as Express.Request;
|
let mocks: ServerVariablesMock;
|
||||||
const res = {
|
let req: any;
|
||||||
render: Sinon.stub()
|
let res: any;
|
||||||
};
|
let renderSpy: Sinon.SinonSpy;
|
||||||
|
|
||||||
return Get403(req, res as any)
|
beforeEach(function () {
|
||||||
|
const s = ServerVariablesMockBuilder.build();
|
||||||
|
vars = s.variables;
|
||||||
|
mocks = s.mocks;
|
||||||
|
|
||||||
|
renderSpy = Sinon.spy();
|
||||||
|
req = {
|
||||||
|
headers: {}
|
||||||
|
};
|
||||||
|
res = {
|
||||||
|
render: renderSpy
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set redirection url to the default redirection url", function () {
|
||||||
|
vars.config.default_redirection_url = "http://default-redirection";
|
||||||
|
return Get403(vars)(req, res as any)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Assert(res.render.calledOnce);
|
Assert(renderSpy.calledOnce);
|
||||||
Assert(res.render.calledWith("errors/403"));
|
Assert(renderSpy.calledWithExactly("errors/403", {
|
||||||
|
redirection_url: "http://default-redirection"
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set redirection url to the referer", function () {
|
||||||
|
req.headers["referer"] = "http://redirection";
|
||||||
|
return Get403(vars)(req, res as any)
|
||||||
|
.then(function () {
|
||||||
|
Assert(renderSpy.calledOnce);
|
||||||
|
Assert(renderSpy.calledWithExactly("errors/403", {
|
||||||
|
redirection_url: "http://redirection"
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render without redirecting the user", function () {
|
||||||
|
return Get403(vars)(req, res as any)
|
||||||
|
.then(function () {
|
||||||
|
Assert(renderSpy.calledOnce);
|
||||||
|
Assert(renderSpy.calledWithExactly("errors/403", {
|
||||||
|
redirection_url: undefined
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -34,6 +34,7 @@ describe("test the first factor validation route", function () {
|
||||||
mocks.regulator.markStub.returns(BluebirdPromise.resolve());
|
mocks.regulator.markStub.returns(BluebirdPromise.resolve());
|
||||||
|
|
||||||
req = {
|
req = {
|
||||||
|
originalUrl: "/api/firstfactor",
|
||||||
body: {
|
body: {
|
||||||
username: "username",
|
username: "username",
|
||||||
password: "password"
|
password: "password"
|
||||||
|
|
|
@ -18,6 +18,7 @@ describe("test reset password identity check", function () {
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = {
|
req = {
|
||||||
|
originalUrl: "/non-api/xxx",
|
||||||
query: {
|
query: {
|
||||||
userid: "user"
|
userid: "user"
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,6 +20,7 @@ describe("test reset password route", function () {
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = {
|
req = {
|
||||||
|
originalUrl: "/api/password-reset",
|
||||||
body: {
|
body: {
|
||||||
userid: "user"
|
userid: "user"
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,7 @@ describe("test totp route", function () {
|
||||||
mocks = s.mocks;
|
mocks = s.mocks;
|
||||||
const app_get = Sinon.stub();
|
const app_get = Sinon.stub();
|
||||||
req = {
|
req = {
|
||||||
|
originalUrl: "/api/totp-register",
|
||||||
app: {},
|
app: {},
|
||||||
body: {
|
body: {
|
||||||
token: "abc"
|
token: "abc"
|
||||||
|
|
|
@ -20,6 +20,7 @@ describe("test u2f routes: register", function () {
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
|
req.originalUrl = "/api/xxxx";
|
||||||
req.app = {};
|
req.app = {};
|
||||||
req.session = {
|
req.session = {
|
||||||
auth: {
|
auth: {
|
||||||
|
|
|
@ -16,6 +16,7 @@ describe("test u2f routes: register_request", function () {
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
|
req.originalUrl = "/api/xxxx";
|
||||||
req.app = {};
|
req.app = {};
|
||||||
req.session = {
|
req.session = {
|
||||||
auth: {
|
auth: {
|
||||||
|
|
|
@ -20,6 +20,7 @@ describe("test u2f routes: sign", function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
req.app = {};
|
req.app = {};
|
||||||
|
req.originalUrl = "/api/xxxx";
|
||||||
|
|
||||||
const s = ServerVariablesMockBuilder.build();
|
const s = ServerVariablesMockBuilder.build();
|
||||||
mocks = s.mocks;
|
mocks = s.mocks;
|
||||||
|
|
|
@ -20,6 +20,7 @@ describe("test u2f routes: sign_request", function () {
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
|
req.originalUrl = "/api/xxxx";
|
||||||
req.app = {};
|
req.app = {};
|
||||||
req.session = {
|
req.session = {
|
||||||
auth: {
|
auth: {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import ExpressMock = require("../../mocks/express");
|
||||||
import { ServerVariables } from "../../../src/lib/ServerVariables";
|
import { ServerVariables } from "../../../src/lib/ServerVariables";
|
||||||
import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../mocks/ServerVariablesMockBuilder";
|
import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../mocks/ServerVariablesMockBuilder";
|
||||||
|
|
||||||
describe("test /verify endpoint", function () {
|
describe("test /api/verify endpoint", function () {
|
||||||
let req: ExpressMock.RequestMock;
|
let req: ExpressMock.RequestMock;
|
||||||
let res: ExpressMock.ResponseMock;
|
let res: ExpressMock.ResponseMock;
|
||||||
let mocks: ServerVariablesMock;
|
let mocks: ServerVariablesMock;
|
||||||
|
@ -22,6 +22,7 @@ describe("test /verify endpoint", function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
req = ExpressMock.RequestMock();
|
req = ExpressMock.RequestMock();
|
||||||
res = ExpressMock.ResponseMock();
|
res = ExpressMock.ResponseMock();
|
||||||
|
req.originalUrl = "/api/xxxx";
|
||||||
req.query = {
|
req.query = {
|
||||||
redirect: "http://redirect.url"
|
redirect: "http://redirect.url"
|
||||||
};
|
};
|
||||||
|
@ -174,7 +175,7 @@ describe("test /verify endpoint", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("inactivity period", function () {
|
describe("inactivity period", function () {
|
||||||
it("should update last inactivity period on requests on /verify", function () {
|
it("should update last inactivity period on requests on /api/verify", function () {
|
||||||
mocks.config.session.inactivity = 200000;
|
mocks.config.session.inactivity = 200000;
|
||||||
mocks.accessController.isAccessAllowedMock.returns(true);
|
mocks.accessController.isAccessAllowedMock.returns(true);
|
||||||
const currentTime = new Date().getTime() - 1000;
|
const currentTime = new Date().getTime() - 1000;
|
||||||
|
|
|
@ -264,7 +264,7 @@ export const FIRST_FACTOR_GET = "/";
|
||||||
export const SECOND_FACTOR_GET = "/secondfactor";
|
export const SECOND_FACTOR_GET = "/secondfactor";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /verify Verify user authentication
|
* @api {get} /api/verify Verify user authentication
|
||||||
* @apiName VerifyAuthentication
|
* @apiName VerifyAuthentication
|
||||||
* @apiGroup Verification
|
* @apiGroup Verification
|
||||||
* @apiVersion 1.0.0
|
* @apiVersion 1.0.0
|
||||||
|
@ -279,7 +279,7 @@ export const SECOND_FACTOR_GET = "/secondfactor";
|
||||||
* are set. Remote-User contains the user id of the currently logged in user and Remote-Groups
|
* are set. Remote-User contains the user id of the currently logged in user and Remote-Groups
|
||||||
* a comma separated list of assigned groups.
|
* a comma separated list of assigned groups.
|
||||||
*/
|
*/
|
||||||
export const VERIFY_GET = "/verify";
|
export const VERIFY_GET = "/api/verify";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /logout Serves logout page
|
* @api {get} /logout Serves logout page
|
||||||
|
|
|
@ -48,4 +48,23 @@ Feature: User is correctly redirected
|
||||||
And I login with user "john" and password "password"
|
And I login with user "john" and password "password"
|
||||||
And I use "REGISTERED" as TOTP token handle
|
And I use "REGISTERED" as TOTP token handle
|
||||||
And I click on "Sign in"
|
And I click on "Sign in"
|
||||||
Then I'm redirected to "https://home.test.local:8080/"
|
Then I'm redirected to "https://home.test.local:8080/"
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: User is redirected when hitting an error 401
|
||||||
|
When I visit "https://auth.test.local:8080/secondfactor/u2f/identity/finish"
|
||||||
|
Then I'm redirected to "https://auth.test.local:8080/error/401"
|
||||||
|
And I sleep for 5 seconds
|
||||||
|
And I'm redirected to "https://home.test.local:8080/"
|
||||||
|
|
||||||
|
@need-registered-user-harry
|
||||||
|
Scenario: User is redirected when hitting an error 403
|
||||||
|
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 "Sign in"
|
||||||
|
And I'm redirected to "https://home.test.local:8080/"
|
||||||
|
When I visit "https://admin.test.local:8080/secret.html"
|
||||||
|
Then I'm redirected to "https://auth.test.local:8080/error/403"
|
||||||
|
And I sleep for 5 seconds
|
||||||
|
And I'm redirected to "https://home.test.local:8080/"
|
|
@ -8,6 +8,7 @@ Feature: Non authenticated users have no access to certain pages
|
||||||
| https://auth.test.local:8080/secondfactor/u2f/identity/finish | 401 | GET |
|
| https://auth.test.local:8080/secondfactor/u2f/identity/finish | 401 | GET |
|
||||||
| https://auth.test.local:8080/secondfactor/totp/identity/start | 401 | GET |
|
| https://auth.test.local:8080/secondfactor/totp/identity/start | 401 | GET |
|
||||||
| https://auth.test.local:8080/secondfactor/totp/identity/finish | 401 | GET |
|
| https://auth.test.local:8080/secondfactor/totp/identity/finish | 401 | GET |
|
||||||
|
| https://auth.test.local:8080/loggedin | 401 | GET |
|
||||||
| https://auth.test.local:8080/api/totp | 401 | POST |
|
| https://auth.test.local:8080/api/totp | 401 | POST |
|
||||||
| https://auth.test.local:8080/api/u2f/sign_request | 401 | GET |
|
| https://auth.test.local:8080/api/u2f/sign_request | 401 | GET |
|
||||||
| https://auth.test.local:8080/api/u2f/sign | 401 | POST |
|
| https://auth.test.local:8080/api/u2f/sign | 401 | POST |
|
||||||
|
|
Loading…
Reference in New Issue