From 6bf0d6e1755309651a84c8b25b71d29e82bfb4f8 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 28 Aug 2017 20:36:56 +0200 Subject: [PATCH] U4-10363 417 missing token error due to invalid cookie name Manually parse the cookie header instead of using the buggy extension method --- .../Filters/AngularAntiForgeryHelper.cs | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs b/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs index 962183f7ef..0f2a7ac442 100644 --- a/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs +++ b/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Linq; -using System.Net.Http; using System.Net.Http.Headers; using System.Web.Helpers; using Umbraco.Core; @@ -30,8 +28,6 @@ namespace Umbraco.Web.WebApi.Filters /// public const string AngularHeadername = "X-XSRF-TOKEN"; - - /// /// Returns 2 tokens - one for the cookie value and one that angular should set as the header value /// @@ -68,8 +64,8 @@ namespace Umbraco.Web.WebApi.Filters return true; } - internal static bool ValidateHeaders( - KeyValuePair>[] requestHeaders, + internal static bool ValidateHeaders( + KeyValuePair>[] requestHeaders, string cookieToken, out string failedReason) { @@ -86,7 +82,7 @@ namespace Umbraco.Web.WebApi.Filters .Select(z => z.Value) .SelectMany(z => z) .FirstOrDefault(); - + // both header and cookie must be there if (cookieToken == null || headerToken == null) { @@ -111,15 +107,41 @@ namespace Umbraco.Web.WebApi.Filters /// public static bool ValidateHeaders(HttpRequestHeaders requestHeaders, out string failedReason) { - var cookieToken = requestHeaders - .GetCookies() - .Select(c => c[CsrfValidationCookieName]) - .FirstOrDefault(); + var cookieToken = GetCookie(requestHeaders, CsrfValidationCookieName); return ValidateHeaders( requestHeaders.ToDictionary(x => x.Key, x => x.Value).ToArray(), - cookieToken == null ? null : cookieToken.Value, + cookieToken == null ? null : cookieToken, out failedReason); } + + /// + /// Retrieves an individual cookie from the cookies collection + /// Adapted from: https://stackoverflow.com/a/29057304/5018 + /// + /// + /// + /// + private static string GetCookie(HttpRequestHeaders requestHeaders, string cookieName) + { + var cookieRequestHeader = requestHeaders.Where(h => h.Key.Equals("Cookie", StringComparison.InvariantCultureIgnoreCase)).ToArray(); + if (cookieRequestHeader.Any() == false) + return null; + + var cookiesHeader = cookieRequestHeader.FirstOrDefault(); + if (cookiesHeader.Value == null) + return null; + + var cookiesHeaderValue = cookiesHeader.Value.FirstOrDefault(); + if (cookiesHeaderValue == null) + return null; + + var cookieCollection = cookiesHeaderValue.Split(';'); + var cookiePair = cookieCollection.FirstOrDefault(c => c.Trim().StartsWith(cookieName, StringComparison.InvariantCultureIgnoreCase)); + if (cookiePair == null) + return null; + + return cookiePair.Trim().Substring(cookieName.Length + 1); + } } } \ No newline at end of file