From 274c6135c775cbab1e31a148903c1e3488041663 Mon Sep 17 00:00:00 2001 From: Amir Zarrinkafsh Date: Wed, 27 Mar 2019 17:57:16 +1100 Subject: [PATCH] Capture IP address and Target URL in Duo 2FA request --- .../lib/routes/secondfactor/duo-push/Post.spec.ts | 12 ++++++------ server/src/lib/routes/secondfactor/duo-push/Post.ts | 10 +++++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/server/src/lib/routes/secondfactor/duo-push/Post.spec.ts b/server/src/lib/routes/secondfactor/duo-push/Post.spec.ts index cd3fa1e4a..b71bb234b 100644 --- a/server/src/lib/routes/secondfactor/duo-push/Post.spec.ts +++ b/server/src/lib/routes/secondfactor/duo-push/Post.spec.ts @@ -24,11 +24,11 @@ describe("routes/secondfactor/duo-push/Post", function() { hostname: 'abc', integration_key: 'xyz', secret_key: 'secret', - } + }; req = ExpressMock.RequestMock(); res = ExpressMock.ResponseMock(); - }) + }); it("should raise authentication level of user", async function() { const mock = Sinon.stub(DuoApi, "Client"); @@ -37,7 +37,7 @@ describe("routes/secondfactor/duo-push/Post", function() { }); req.session.auth = { userid: 'john' - } + }; Assert.equal(req.session.auth.authentication_level, undefined); await Post(vars)(req, res as any); @@ -54,7 +54,7 @@ describe("routes/secondfactor/duo-push/Post", function() { }); req.session.auth = { userid: 'john' - } + }; vars.config.duo_api = undefined; Assert.equal(req.session.auth.authentication_level, undefined); @@ -72,7 +72,7 @@ describe("routes/secondfactor/duo-push/Post", function() { }); req.session.auth = { userid: 'john' - } + }; Assert.equal(req.session.auth.authentication_level, undefined); await Post(vars)(req, res as any); @@ -90,7 +90,7 @@ describe("routes/secondfactor/duo-push/Post", function() { }); req.session.auth = { userid: 'john' - } + }; Assert.equal(req.session.auth.authentication_level, undefined); const promise = Post(vars)(req, res as any) diff --git a/server/src/lib/routes/secondfactor/duo-push/Post.ts b/server/src/lib/routes/secondfactor/duo-push/Post.ts index f3891a8e8..a21ab3be4 100644 --- a/server/src/lib/routes/secondfactor/duo-push/Post.ts +++ b/server/src/lib/routes/secondfactor/duo-push/Post.ts @@ -6,6 +6,8 @@ import * as UserMessage from "../../../../../../shared/UserMessages"; import redirect from "../redirect"; import { Level } from "../../../authentication/Level"; import { DuoPushConfiguration } from "../../../configuration/schema/DuoPushConfiguration"; +import GetHeader from "../../../utils/GetHeader"; +import { HEADER_X_TARGET_URL } from "../../../../../../shared/constants"; const DuoApi = require("@duosecurity/duo_api"); interface DuoResponse { @@ -17,11 +19,13 @@ interface DuoResponse { stat: "OK" | "FAIL"; } -function triggerAuth(username: string, config: DuoPushConfiguration): Promise { +function triggerAuth(username: string, config: DuoPushConfiguration, req: Express.Request): Promise { return new Promise((resolve, reject) => { + const clientIP = req.ip; + const targetURL = GetHeader(req, HEADER_X_TARGET_URL); const client = new DuoApi.Client(config.integration_key, config.secret_key, config.hostname); const timer = setTimeout(() => reject(new Error("Call to duo push API timed out.")), 60000); - client.jsonApiCall("POST", "/auth/v2/auth", { username, factor: "push", device: "auto" }, (data: DuoResponse) => { + client.jsonApiCall("POST", "/auth/v2/auth", { username, ipaddr: clientIP, factor: "push", device: "auto", pushinfo: `target%20url=${targetURL}`}, (data: DuoResponse) => { clearTimeout(timer); resolve(data); }); @@ -37,7 +41,7 @@ export default function(vars: ServerVariables) { } const authSession = AuthenticationSessionHandler.get(req, vars.logger); - const authRes = await triggerAuth(authSession.userid, vars.config.duo_api); + const authRes = await triggerAuth(authSession.userid, vars.config.duo_api, req); if (authRes.response.result !== "allow") { throw new Error("User denied access."); }