Add a test checking forwarded headers on bypass-based resources.

This commit is contained in:
Clement Michaud 2019-04-10 21:56:55 +02:00 committed by Clément Michaud
parent c074270b54
commit 36d65c284e
9 changed files with 91 additions and 12 deletions

View File

@ -26,13 +26,13 @@ export default function (
authorizer: IAuthorizer,
domain: string, resource: string,
user: string, groups: string[], ip: string,
authenticationLevel: AuthenticationLevel): AuthorizationLevel {
authenticationLevel: AuthenticationLevel): void {
const authorizationLevel = authorizer
.authorization({domain, resource}, {user, groups}, ip);
if (authorizationLevel == AuthorizationLevel.BYPASS) {
return authorizationLevel;
return;
}
else if (user && authorizationLevel == AuthorizationLevel.DENY) {
throw new Exceptions.NotAuthorizedError(
@ -42,5 +42,4 @@ export default function (
throw new Exceptions.NotAuthenticatedError(Util.format(
"User '%s' is not sufficiently authorized to access %s%s.", (user) ? user : "unknown", domain, resource));
}
return authorizationLevel;
}

View File

@ -6,6 +6,7 @@ import CheckInactivity from "./CheckInactivity";
import { AuthenticationSession } from "../../../../types/AuthenticationSession";
import { Configuration } from "../../configuration/schema/Configuration";
import { RequestLoggerStub } from "../../logging/RequestLoggerStub.spec";
import { Level } from "../../authentication/Level";
describe('routes/verify/VerifyInactivity', function() {
@ -16,7 +17,9 @@ describe('routes/verify/VerifyInactivity', function() {
beforeEach(function() {
req = ExpressMock.RequestMock();
authSession = {} as any;
authSession = {
authentication_level: Level.TWO_FACTOR,
} as any;
configuration = {
session: {
domain: 'example.com',
@ -32,6 +35,11 @@ describe('routes/verify/VerifyInactivity', function() {
logger = new RequestLoggerStub();
});
it('should not throw if user is not authenticated', function() {
authSession.authentication_level = Level.NOT_AUTHENTICATED;
CheckInactivity(req, authSession, configuration, logger);
});
it('should not throw if inactivity timeout is disabled', function() {
delete configuration.session.inactivity;
CheckInactivity(req, authSession, configuration, logger);

View File

@ -3,11 +3,17 @@ import { AuthenticationSession } from "AuthenticationSession";
import { Configuration } from "../../configuration/schema/Configuration";
import { IRequestLogger } from "../../logging/IRequestLogger";
import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler";
import { Level } from "../../authentication/Level";
export default function(req: Express.Request,
authSession: AuthenticationSession,
configuration: Configuration, logger: IRequestLogger): void {
// If the user is not authenticated, we don't check inactivity.
if (authSession.authentication_level == Level.NOT_AUTHENTICATED) {
return;
}
// If inactivity is not specified, then inactivity timeout does not apply
if (!configuration.session.inactivity || authSession.keep_me_logged_in) {
return;

View File

@ -40,10 +40,8 @@ export default async function(req: Express.Request, res: Express.Response,
const uri = GetHeader(req, HEADER_X_ORIGINAL_URL);
const urlDecomposition = URLDecomposer.fromUrl(uri);
const authorizationLevel = CheckAuthorizations(vars.authorizer, urlDecomposition.domain, urlDecomposition.path,
username, groupsAndEmails.groups, req.ip, Level.ONE_FACTOR);
if (authorizationLevel > AuthorizationLevel.BYPASS) {
CheckAuthorizations(vars.authorizer, urlDecomposition.domain, urlDecomposition.path,
username, groupsAndEmails.groups, req.ip, Level.ONE_FACTOR);
setUserAndGroupsHeaders(res, username, groupsAndEmails.groups);
}
}

View File

@ -7,7 +7,6 @@ import GetHeader from "../../utils/GetHeader";
import {
HEADER_X_ORIGINAL_URL,
} from "../../../../../shared/constants";
import { Level as AuthorizationLevel } from "../../authorization/Level";
import setUserAndGroupsHeaders from "./SetUserAndGroupsHeaders";
import CheckAuthorizations from "./CheckAuthorizations";
import CheckInactivity from "./CheckInactivity";
@ -33,9 +32,8 @@ export default async function (req: Express.Request, res: Express.Response,
vars.logger.debug(req, "domain=%s, path=%s, user=%s, groups=%s, ip=%s", d.domain,
d.path, (username) ? username : "unknown", (groups instanceof Array && groups.length > 0) ? groups.join(",") : "unknown", req.ip);
const authorizationLevel = CheckAuthorizations(vars.authorizer, d.domain, d.path, username, groups, req.ip,
authSession.authentication_level);
CheckAuthorizations(vars.authorizer, d.domain, d.path, username, groups, req.ip, authSession.authentication_level);
CheckInactivity(req, authSession, vars.config, vars.logger);
setUserAndGroupsHeaders(res, username, groups);
}

View File

@ -0,0 +1,13 @@
import SeleniumWebDriver, { WebDriver } from "selenium-webdriver";
import Util from "util";
export default async function(driver: WebDriver, header: string, timeout: number = 5000) {
const el = await driver.wait(SeleniumWebDriver.until.elementLocated(
SeleniumWebDriver.By.tagName("body")), timeout);
const text = await el.getText();
const expectedLine = Util.format("\"%s\": ", header);
if (text.indexOf(expectedLine) >= 0) {
throw new Error("Header found.");
}
}

View File

@ -11,6 +11,7 @@ const dockerEnv = new DockerEnvironment([
'docker-compose.yml',
'example/compose/nginx/backend/docker-compose.yml',
'example/compose/nginx/portal/docker-compose.yml',
'example/compose/httpbin/docker-compose.yml',
'example/compose/smtp/docker-compose.yml',
'example/compose/duo-api/docker-compose.yml',
])

View File

@ -0,0 +1,52 @@
import Logout from "../../../helpers/Logout";
import { StartDriver, StopDriver } from "../../../helpers/context/WithDriver";
import VerifyForwardedHeaderIs from "../../../helpers/assertions/VerifyForwardedHeaderIs";
import LoginOneFactor from "../../../helpers/behaviors/LoginOneFactor";
import VisitPageAndWaitUrlIs from "../../../helpers/behaviors/VisitPageAndWaitUrlIs";
import VerifyButtonDoesNotExist from "../../../helpers/assertions/VerifyButtonDoesNotExist";
export default function() {
describe("Custom-Forwarded-User and Custom-Forwarded-Groups are correctly forwarded when available", function() {
this.timeout(100000);
describe("Headers are not forwarded for anonymous user", function() {
before(async function() {
this.driver = await StartDriver();
await VisitPageAndWaitUrlIs(this.driver, "https://public.example.com:8080/headers");
});
after(async function() {
await Logout(this.driver);
await StopDriver(this.driver);
});
it("should check header 'Custom-Forwarded-User' does not exist", async function() {
await VerifyButtonDoesNotExist(this.driver, 'Custom-Forwarded-User');
});
it("should check header 'Custom-Forwarded-Groups' does not exist", async function() {
await VerifyButtonDoesNotExist(this.driver, 'Custom-Forwarded-Groups');
});
});
describe("Headers are forwarded for authenticated user", function() {
before(async function() {
this.driver = await StartDriver();
await LoginOneFactor(this.driver, "john", "password", "https://public.example.com:8080/headers");
});
after(async function() {
await Logout(this.driver);
await StopDriver(this.driver);
});
it("should see header 'Custom-Forwarded-User' set to 'john'", async function() {
await VerifyForwardedHeaderIs(this.driver, 'Custom-Forwarded-User', 'john');
});
it("should see header 'Custom-Forwarded-Groups' set to 'admins,dev'", async function() {
await VerifyForwardedHeaderIs(this.driver, 'Custom-Forwarded-Groups', 'admins,dev');
});
});
});
}

View File

@ -2,6 +2,9 @@ import AutheliaSuite from "../../helpers/context/AutheliaSuite";
import { exec } from '../../helpers/utils/exec';
import BypassPolicy from "./scenarii/BypassPolicy";
import NoDefaultRedirectionUrl from "./scenarii/NoDefaultRedirectionUrl";
import CustomHeadersForwarded from "./scenarii/CustomHeadersForwarded";
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0 as any;
AutheliaSuite(__dirname, function() {
this.timeout(10000);
@ -12,4 +15,5 @@ AutheliaSuite(__dirname, function() {
describe('Bypass policy', BypassPolicy);
describe("No default redirection", NoDefaultRedirectionUrl);
describe("Custom headers forwarded on bypass", CustomHeadersForwarded);
});