Commit a105f264 authored by Jason Williams's avatar Jason Williams Committed by GitHub
Browse files

Restores our CSRF token handling (#238)

Addresses Issue #216 
parent 6cde839b
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -31,6 +31,11 @@ namespace Microsoft.Tools.WindowsDevicePortal
        /// </summary>
        private static readonly string ContentTypeHeaderName = "Content-Type";

        /// <summary>
        /// Header name for a CSRF-Token.
        /// </summary>
        private static readonly string CsrfTokenName = "CSRF-Token";

        /// <summary>
        /// Header name for a User-Agent.
        /// </summary>
@@ -41,6 +46,39 @@ namespace Microsoft.Tools.WindowsDevicePortal
        /// </summary>
        private static readonly string UserAgentValue = "WindowsDevicePortalWrapper";

        /// <summary>
        /// CSRF token retrieved by GET calls and used on subsequent POST/DELETE/PUT calls.
        /// This token is intended to prevent a security vulnerability from cross site forgery.
        /// </summary>
        private string csrfToken = string.Empty;

        /// <summary>
        /// Applies the CSRF token to the HTTP client.
        /// </summary>
        /// <param name="client">The HTTP client on which to have the header set.</param>
        /// <param name="method">The HTTP method (ex: POST) that will be called on the client.</param>
        private void ApplyCSRFHeader(
            HttpClient client,
            HttpMethods method)
        {
            string headerName = "X-" + CsrfTokenName;
            string headerValue = this.csrfToken;

            if (string.Compare(method.ToString(), "get", true) == 0)
            {
                headerName = CsrfTokenName;
                headerValue = string.IsNullOrEmpty(this.csrfToken) ? "Fetch" : headerValue;
            }

#if WINDOWS_UWP
            HttpRequestHeaderCollection headers = client.DefaultRequestHeaders;
#else
            HttpRequestHeaders headers = client.DefaultRequestHeaders;
#endif // WINDOWS_UWP

            headers.Add(headerName, headerValue);
        }

        /// <summary>
        /// Applies any needed headers to the HTTP client.
        /// </summary>
@@ -51,6 +89,7 @@ namespace Microsoft.Tools.WindowsDevicePortal
            HttpMethods method)
        {
            this.ApplyUserAgentHeader(client);
            this.ApplyCSRFHeader(client, method);
        }

        /// <summary>
@@ -76,5 +115,38 @@ namespace Microsoft.Tools.WindowsDevicePortal

            headers.Add(UserAgentName, userAgentValue);
        }

        /// <summary>
        /// Retrieves the CSRF token from the HTTP response and stores it.
        /// </summary>
        /// <param name="response">The HTTP response from which to retrieve the header.</param>
        private void RetrieveCsrfToken(HttpResponseMessage response)
        {
            // If the response sets a CSRF token, store that for future requests.
#if WINDOWS_UWP
            string cookie;
            if (response.Headers.TryGetValue("Set-Cookie", out cookie))
            {
                string csrfTokenNameWithEquals = CsrfTokenName + "=";
                if (cookie.StartsWith(csrfTokenNameWithEquals))
                {
                    this.csrfToken = cookie.Substring(csrfTokenNameWithEquals.Length);
                }
            }
#else
            IEnumerable<string> cookies;
            if (response.Headers.TryGetValues("Set-Cookie", out cookies))
            {
                foreach (string cookie in cookies)
                {
                    string csrfTokenNameWithEquals = CsrfTokenName + "=";
                    if (cookie.StartsWith(csrfTokenNameWithEquals))
                    {
                        this.csrfToken = cookie.Substring(csrfTokenNameWithEquals.Length);
                    }
                }
            }
#endif
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ namespace Microsoft.Tools.WindowsDevicePortal
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    this.RetrieveCsrfToken(response);

                    if (response.Content != null)
                    {
                        using (IHttpContent messageContent = response.Content)
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ namespace Microsoft.Tools.WindowsDevicePortal
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    this.RetrieveCsrfToken(response);

                    using (IHttpContent messageContent = response.Content)
                    {
                        dataBuffer = await messageContent.ReadAsBufferAsync();
+2 −0
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ namespace Microsoft.Tools.WindowsDevicePortal
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    this.RetrieveCsrfToken(response);

                    if (response.Content != null)
                    {
                        using (IHttpContent messageContent = response.Content)
+2 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ namespace Microsoft.Tools.WindowsDevicePortal
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    this.RetrieveCsrfToken(response);

                    if (response.Content != null)
                    {
                        using (IHttpContent messageContent = response.Content)
Loading