diff --git a/AutoCollection/HttpRequestParser.ts b/AutoCollection/HttpRequestParser.ts index d8e45a0d3..ed9ed6e9d 100644 --- a/AutoCollection/HttpRequestParser.ts +++ b/AutoCollection/HttpRequestParser.ts @@ -10,7 +10,8 @@ import CorrelationIdManager = require("../Library/CorrelationIdManager"); import Tracestate = require("../Library/Tracestate"); import Traceparent = require("../Library/Traceparent"); import { HttpRequest } from "../Library/Functions"; - +import Logging = require("../Library/Logging"); +import { HttpRequestCookieNames } from "../Declarations/Constants"; /** * Helper class to read data from the request/response objects and convert them into the telemetry contract @@ -127,9 +128,9 @@ class HttpRequestParser extends RequestParser { // don't override tags if they are already set newTags[HttpRequestParser.keys.locationIp] = tags[HttpRequestParser.keys.locationIp] || this._getIp(); - newTags[HttpRequestParser.keys.sessionId] = tags[HttpRequestParser.keys.sessionId] || this._getId("ai_session"); - newTags[HttpRequestParser.keys.userId] = tags[HttpRequestParser.keys.userId] || this._getId("ai_user"); - newTags[HttpRequestParser.keys.userAuthUserId] = tags[HttpRequestParser.keys.userAuthUserId] || this._getId("ai_authUser"); + newTags[HttpRequestParser.keys.sessionId] = tags[HttpRequestParser.keys.sessionId] || this._getId(HttpRequestCookieNames.SESSION); + newTags[HttpRequestParser.keys.userId] = tags[HttpRequestParser.keys.userId] || this._getId(HttpRequestCookieNames.USER); + newTags[HttpRequestParser.keys.userAuthUserId] = tags[HttpRequestParser.keys.userAuthUserId] || this._getId(HttpRequestCookieNames.AUTH_USER); newTags[HttpRequestParser.keys.operationName] = this.getOperationName(tags); newTags[HttpRequestParser.keys.operationParentId] = this.getOperationParentId(tags); newTags[HttpRequestParser.keys.operationId] = this.getOperationId(tags); @@ -247,6 +248,16 @@ class HttpRequestParser extends RequestParser { private _getId(name: string) { var cookie = (this.rawHeaders && this.rawHeaders["cookie"] && typeof this.rawHeaders["cookie"] === "string" && this.rawHeaders["cookie"]) || ""; + + if (name === HttpRequestCookieNames.AUTH_USER) { + try { + cookie = decodeURI(cookie); + } catch (error) { + // Failed to decode, ignore cookie + cookie = ""; + Logging.warn("Could not decode the auth cookie with error: ", Util.dumpObj(error)); + } + } var value = HttpRequestParser.parseId(Util.getCookie(name, cookie)); return value; } diff --git a/Declarations/Constants.ts b/Declarations/Constants.ts index 0fb669adc..d1f1ef1ea 100644 --- a/Declarations/Constants.ts +++ b/Declarations/Constants.ts @@ -185,6 +185,12 @@ export enum StatsbeatNetworkCategory { Quickpulse, } +export enum HttpRequestCookieNames { + SESSION = "ai_session", + USER = "ai_user", + AUTH_USER = "ai_authUser", +} + //Azure SDK Span Attributes export const AzNamespace = "az.namespace"; export const MicrosoftEventHub = "Microsoft.EventHub"; diff --git a/Tests/AutoCollection/HttpRequestParser.tests.ts b/Tests/AutoCollection/HttpRequestParser.tests.ts index a10ad9c1d..f38321201 100644 --- a/Tests/AutoCollection/HttpRequestParser.tests.ts +++ b/Tests/AutoCollection/HttpRequestParser.tests.ts @@ -202,7 +202,22 @@ describe("AutoCollection/HttpRequestParser", () => { headers: { host: "bing.com", "x-forwarded-for": "123.123.123.123", - "cookie": "ai_user=cookieUser|time;ai_session=cookieSession|time;ai_authUser=cookieAuthUser|time", + "cookie": `ai_user=cookieUser|time;ai_session=cookieSession|time;ai_authUser=${encodeURI("cookieAuthUser{}/test|time")}`, + "x-ms-request-id": "parentRequestId", + "x-ms-request-root-id": "operationId", + } + } + + const request2 = { + method: "GET", + url: "/search?q=test", + connection: { + encrypted: false + }, + headers: { + host: "bing.com", + "x-forwarded-for": "123.123.123.123", + "cookie": "ai_user=cookieUser|time;ai_session=cookieSession|time;ai_authUser=userAuthName|time", "x-ms-request-id": "parentRequestId", "x-ms-request-root-id": "operationId", } @@ -239,11 +254,19 @@ describe("AutoCollection/HttpRequestParser", () => { var newTags = helper.getRequestTags(originalTags); assert.equal(newTags[(HttpRequestParser).keys.locationIp], '123.123.123.123'); assert.equal(newTags[(HttpRequestParser).keys.userId], 'cookieUser'); - assert.equal(newTags[(HttpRequestParser).keys.userAuthUserId], 'cookieAuthUser'); + assert.equal(newTags[(HttpRequestParser).keys.userAuthUserId], 'cookieAuthUser{}/test'); assert.equal(newTags[(HttpRequestParser).keys.userAgent], undefined); assert.equal(newTags[(HttpRequestParser).keys.operationName], 'GET /search'); assert.equal(newTags[(HttpRequestParser).keys.operationId], 'operationId'); assert.equal(newTags[(HttpRequestParser).keys.operationParentId], 'parentRequestId'); }); + + it("should read non-encoded auth user values from headers", () => { + const helper = new HttpRequestParser(request2); + const originalTags: {[key: string]:string} = {}; + + var newTags = helper.getRequestTags(originalTags); + assert.equal(newTags[(HttpRequestParser).keys.userAuthUserId], 'userAuthName'); + }); }); });