2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
import sinon = require("sinon");
|
2017-10-06 22:09:42 +00:00
|
|
|
import IdentityValidator = require("../src/lib/IdentityCheckMiddleware");
|
2017-10-17 21:24:02 +00:00
|
|
|
import AuthenticationSessionHandler = require("../src/lib/AuthenticationSession");
|
|
|
|
import { AuthenticationSession } from "../types/AuthenticationSession";
|
2017-10-06 22:09:42 +00:00
|
|
|
import { UserDataStore } from "../src/lib/storage/UserDataStore";
|
|
|
|
import exceptions = require("../src/lib/Exceptions");
|
2017-10-17 21:24:02 +00:00
|
|
|
import { ServerVariables } from "../src/lib/ServerVariables";
|
2017-10-10 21:03:30 +00:00
|
|
|
import Assert = require("assert");
|
2017-05-25 13:09:29 +00:00
|
|
|
import express = require("express");
|
|
|
|
import BluebirdPromise = require("bluebird");
|
|
|
|
import ExpressMock = require("./mocks/express");
|
|
|
|
import NotifierMock = require("./mocks/Notifier");
|
|
|
|
import IdentityValidatorMock = require("./mocks/IdentityValidator");
|
2017-10-17 21:24:02 +00:00
|
|
|
import { RequestLoggerStub } from "./mocks/RequestLoggerStub";
|
|
|
|
import { ServerVariablesMock, ServerVariablesMockBuilder } from "./mocks/ServerVariablesMockBuilder";
|
2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
describe("test identity check process", function () {
|
|
|
|
let req: ExpressMock.RequestMock;
|
|
|
|
let res: ExpressMock.ResponseMock;
|
|
|
|
let app: express.Application;
|
|
|
|
let app_get: sinon.SinonStub;
|
|
|
|
let app_post: sinon.SinonStub;
|
|
|
|
let identityValidable: IdentityValidatorMock.IdentityValidableMock;
|
2017-10-17 21:24:02 +00:00
|
|
|
let mocks: ServerVariablesMock;
|
|
|
|
let vars: ServerVariables;
|
2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
beforeEach(function () {
|
2017-10-17 21:24:02 +00:00
|
|
|
const s = ServerVariablesMockBuilder.build();
|
|
|
|
mocks = s.mocks;
|
|
|
|
vars = s.variables;
|
|
|
|
|
2017-05-25 13:09:29 +00:00
|
|
|
req = ExpressMock.RequestMock();
|
|
|
|
res = ExpressMock.ResponseMock();
|
|
|
|
|
|
|
|
identityValidable = IdentityValidatorMock.IdentityValidableMock();
|
|
|
|
|
|
|
|
|
|
|
|
req.headers = {};
|
|
|
|
req.session = {};
|
|
|
|
req.session = {};
|
|
|
|
|
|
|
|
req.query = {};
|
|
|
|
req.app = {};
|
2017-07-19 19:06:12 +00:00
|
|
|
|
2017-10-17 21:24:02 +00:00
|
|
|
mocks.notifier.notifyStub.returns(BluebirdPromise.resolve());
|
2017-07-19 19:06:12 +00:00
|
|
|
mocks.userDataStore.produceIdentityValidationTokenStub.returns(Promise.resolve());
|
|
|
|
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(Promise.resolve({ userId: "user" }));
|
|
|
|
|
2017-05-25 13:09:29 +00:00
|
|
|
app = express();
|
|
|
|
app_get = sinon.stub(app, "get");
|
|
|
|
app_post = sinon.stub(app, "post");
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
app_get.restore();
|
|
|
|
app_post.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("test start GET", test_start_get_handler);
|
|
|
|
describe("test finish GET", test_finish_get_handler);
|
|
|
|
|
|
|
|
function test_start_get_handler() {
|
|
|
|
it("should send 401 if pre validation initialization throws a first factor error", function () {
|
|
|
|
identityValidable.preValidationInit.returns(BluebirdPromise.reject(new exceptions.FirstFactorValidationError("Error during prevalidation")));
|
2017-10-17 21:24:02 +00:00
|
|
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
return callback(req as any, res as any, undefined)
|
|
|
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
|
|
|
.catch(function () {
|
2017-10-10 21:03:30 +00:00
|
|
|
Assert.equal(res.status.getCall(0).args[0], 401);
|
2017-05-25 13:09:29 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-10-10 21:03:30 +00:00
|
|
|
it("should send 401 if email is missing in provided identity", function () {
|
2017-05-25 13:09:29 +00:00
|
|
|
const identity = { userid: "abc" };
|
|
|
|
|
|
|
|
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
2017-10-17 21:24:02 +00:00
|
|
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
return callback(req as any, res as any, undefined)
|
|
|
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
|
|
|
.catch(function () {
|
2017-10-10 21:03:30 +00:00
|
|
|
Assert.equal(res.status.getCall(0).args[0], 401);
|
2017-05-25 13:09:29 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-10-10 21:03:30 +00:00
|
|
|
it("should send 401 if userid is missing in provided identity", function () {
|
2017-05-25 13:09:29 +00:00
|
|
|
const endpoint = "/protected";
|
|
|
|
const identity = { email: "abc@example.com" };
|
|
|
|
|
|
|
|
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
2017-10-17 21:24:02 +00:00
|
|
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/endpoint", vars);
|
2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
return callback(req as any, res as any, undefined)
|
|
|
|
.then(function () { return BluebirdPromise.reject(new Error("It should fail")); })
|
|
|
|
.catch(function (err: Error) {
|
2017-10-10 21:03:30 +00:00
|
|
|
Assert.equal(res.status.getCall(0).args[0], 401);
|
2017-05-25 13:09:29 +00:00
|
|
|
return BluebirdPromise.resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should issue a token, send an email and return 204", function () {
|
|
|
|
const endpoint = "/protected";
|
|
|
|
const identity = { userid: "user", email: "abc@example.com" };
|
|
|
|
req.get = sinon.stub().withArgs("Host").returns("localhost");
|
|
|
|
|
|
|
|
identityValidable.preValidationInit.returns(BluebirdPromise.resolve(identity));
|
2017-10-17 21:24:02 +00:00
|
|
|
const callback = IdentityValidator.get_start_validation(identityValidable, "/finish_endpoint", vars);
|
2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
return callback(req as any, res as any, undefined)
|
|
|
|
.then(function () {
|
2017-10-17 21:24:02 +00:00
|
|
|
Assert(mocks.notifier.notifyStub.calledOnce);
|
2017-10-10 21:03:30 +00:00
|
|
|
Assert(mocks.userDataStore.produceIdentityValidationTokenStub.calledOnce);
|
|
|
|
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[0], "user");
|
|
|
|
Assert.equal(mocks.userDataStore.produceIdentityValidationTokenStub.getCall(0).args[3], 240000);
|
2017-05-25 13:09:29 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_finish_get_handler() {
|
2017-10-10 21:03:30 +00:00
|
|
|
it("should send 401 if no identity_token is provided", function () {
|
2017-05-25 13:09:29 +00:00
|
|
|
|
2017-10-17 21:24:02 +00:00
|
|
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
2017-05-25 13:09:29 +00:00
|
|
|
|
|
|
|
return callback(req as any, res as any, undefined)
|
|
|
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
|
|
|
.catch(function () {
|
2017-10-10 21:03:30 +00:00
|
|
|
Assert.equal(res.status.getCall(0).args[0], 401);
|
2017-05-25 13:09:29 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should call postValidation if identity_token is provided and still valid", function () {
|
|
|
|
req.query.identity_token = "token";
|
|
|
|
|
2017-10-17 21:24:02 +00:00
|
|
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
2017-05-25 13:09:29 +00:00
|
|
|
return callback(req as any, res as any, undefined);
|
|
|
|
});
|
|
|
|
|
2017-10-10 21:03:30 +00:00
|
|
|
it("should return 401 if identity_token is provided but invalid", function () {
|
2017-05-25 13:09:29 +00:00
|
|
|
req.query.identity_token = "token";
|
|
|
|
|
2017-07-19 19:06:12 +00:00
|
|
|
mocks.userDataStore.consumeIdentityValidationTokenStub.returns(BluebirdPromise.reject(new Error("Invalid token")));
|
2017-05-25 13:09:29 +00:00
|
|
|
|
2017-10-17 21:24:02 +00:00
|
|
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
2017-05-25 13:09:29 +00:00
|
|
|
return callback(req as any, res as any, undefined)
|
|
|
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
|
|
|
.catch(function () {
|
2017-10-10 21:03:30 +00:00
|
|
|
Assert.equal(res.status.getCall(0).args[0], 401);
|
2017-05-25 13:09:29 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should set the identity_check session object even if session does not exist yet", function () {
|
|
|
|
req.query.identity_token = "token";
|
|
|
|
|
|
|
|
req.session = {};
|
2017-10-17 21:24:02 +00:00
|
|
|
let authSession: AuthenticationSession;
|
|
|
|
const callback = IdentityValidator.get_finish_validation(identityValidable, vars);
|
2017-09-21 20:07:34 +00:00
|
|
|
|
2017-10-17 21:24:02 +00:00
|
|
|
return AuthenticationSessionHandler.get(req as any, vars.logger)
|
|
|
|
.then(function (_authSession) {
|
2017-09-21 20:07:34 +00:00
|
|
|
authSession = _authSession;
|
|
|
|
return callback(req as any, res as any, undefined);
|
|
|
|
})
|
2017-05-25 13:09:29 +00:00
|
|
|
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
|
|
|
.catch(function () {
|
2017-10-10 21:03:30 +00:00
|
|
|
Assert.equal(authSession.identity_check.userid, "user");
|
2017-05-25 13:09:29 +00:00
|
|
|
return BluebirdPromise.resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|