import BluebirdPromise = require("bluebird"); import Express = require("express"); import Exceptions = require("../../Exceptions"); import ErrorReplies = require("../../ErrorReplies"); import { ServerVariables } from "../../ServerVariables"; import GetWithSessionCookieMethod from "./get_session_cookie"; import GetWithBasicAuthMethod from "./get_basic_auth"; import Constants = require("../../../../../shared/constants"); import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; import { AuthenticationSession } from "../../../../types/AuthenticationSession"; import GetHeader from "../../utils/GetHeader"; const REMOTE_USER = "Remote-User"; const REMOTE_GROUPS = "Remote-Groups"; function verifyWithSelectedMethod(req: Express.Request, res: Express.Response, vars: ServerVariables, authSession: AuthenticationSession | undefined) : () => BluebirdPromise<{ username: string, groups: string[] }> { return function () { const authorization = GetHeader(req, Constants.HEADER_PROXY_AUTHORIZATION); if (authorization) { if (authorization.startsWith("Basic ")) { return GetWithBasicAuthMethod(req, res, vars, authorization); } else { throw new Error("The authorization header should be of the form 'Basic XXXXXX'"); } } else { if (authSession) { return GetWithSessionCookieMethod(req, res, vars, authSession); } else { throw new Error("No cookie detected."); } } }; } function setRedirectHeader(req: Express.Request, res: Express.Response) { return function () { const originalUrl = GetHeader(req, Constants.HEADER_X_ORIGINAL_URL); res.set(Constants.HEADER_REDIRECT, originalUrl); return BluebirdPromise.resolve(); }; } function setUserAndGroupsHeaders(res: Express.Response) { return function (u: { username: string, groups: string[] }) { res.setHeader(REMOTE_USER, u.username); res.setHeader(REMOTE_GROUPS, u.groups.join(",")); return BluebirdPromise.resolve(); }; } function replyWith200(res: Express.Response) { return function () { res.status(204); res.send(); }; } function getRedirectParam(req: Express.Request) { return req.query[Constants.REDIRECT_QUERY_PARAM] != "undefined" ? req.query[Constants.REDIRECT_QUERY_PARAM] : undefined; } export default function (vars: ServerVariables) { return function (req: Express.Request, res: Express.Response) : BluebirdPromise<void> { let authSession: AuthenticationSession | undefined; return new BluebirdPromise(function (resolve, reject) { authSession = AuthenticationSessionHandler.get(req, vars.logger); resolve(); }) .then(setRedirectHeader(req, res)) .then(verifyWithSelectedMethod(req, res, vars, authSession)) .then(setUserAndGroupsHeaders(res)) .then(replyWith200(res)) // The user is authenticated but has restricted access -> 403 .catch(Exceptions.NotAuthorizedError, ErrorReplies.replyWithError403(req, res, vars.logger)) .catch(Exceptions.NotAuthenticatedError, ErrorReplies.replyWithError401(req, res, vars.logger)) // The user is not yet authenticated -> 401 .catch((err) => { console.error(err); // This redirect parameter is used in Kubernetes to annotate the ingress with // the url to the authentication portal. const redirectUrl = getRedirectParam(req); if (redirectUrl) { ErrorReplies.redirectTo(redirectUrl, req, res, vars.logger)(err); } else { ErrorReplies.replyWithError401(req, res, vars.logger)(err); } }); }; }