197 lines · 8.5 KB · C#
RawDownload
//******************************************************************************************************//  AntiForgeryWorker.cs - Gbtc////  Copyright © 2018, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this//  file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  02/15/2018 - J. Ritchie Carroll//       Generated original version of source code.////****************************************************************************************************** #region [ Contributor License Agreements ] // Derived from AspNetWebStack (https://github.com/aspnet/AspNetWebStack) // Copyright (c) .NET Foundation. All rights reserved.// See NOTICE.txt file in Source folder for more information. #endregion using System;using System.Collections.Generic;using System.Diagnostics.CodeAnalysis;using System.Net.Http;using System.Security.Principal;using System.Web.Mvc;using GSF.Security; namespace GSF.Web.Security.AntiCsrf{    internal sealed class AntiForgeryWorker    {        private readonly ReadOnlyAntiForgeryConfig m_config = new ReadOnlyAntiForgeryConfig();        private readonly AntiForgeryTokenStore m_tokenStore = new AntiForgeryTokenStore();        private readonly TokenValidator m_validator = new TokenValidator();         private void CheckSSLConfig(HttpRequestMessage request)        {            if (m_config.RequireSSL && !request.RequestUri.Scheme.Equals("https"))                throw new InvalidOperationException("The anti-forgery system has the configuration value AntiForgeryConfig.RequireSsl = true, but the current request is not an SSL request.");        }         private AntiForgeryToken DeserializeToken(string serializedToken)        {            return !string.IsNullOrEmpty(serializedToken) ? AntiForgeryTokenSerializer.Deserialize(serializedToken) : null;        }         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Caller will just regenerate token in case of failure.")]        private AntiForgeryToken DeserializeTokenNoThrow(string serializedToken)        {            try            {                return DeserializeToken(serializedToken);            }            catch            {                // ignore failures since we'll just generate a new token                return null;            }        }         private static IIdentity ExtractIdentity(HttpRequestMessage request)        {            SecurityPrincipal securityPrincipal = request.GetRequestContext().Principal as SecurityPrincipal;            return securityPrincipal?.Identity;        }         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Caller will just regenerate token in case of failure.")]        private AntiForgeryToken GetCookieTokenNoThrow(HttpRequestMessage request)        {            try            {                return m_tokenStore.GetCookieToken(request);            }            catch            {                // ignore failures since we'll just generate a new token                return null;            }        }         // [ ENTRY POINT ]        // Generates an anti-XSRF token pair for the current user. The return        // value is the hidden input form element that should be rendered in        // the <form>. This method has a side effect: it may set a response        // cookie.        public TagBuilder GetFormInputElement(HttpResponseMessage response)        {            CheckSSLConfig(response.RequestMessage);             AntiForgeryToken oldCookieToken = GetCookieTokenNoThrow(response.RequestMessage);            AntiForgeryToken newCookieToken, formToken;             GetTokens(response.RequestMessage, oldCookieToken, out newCookieToken, out formToken);             // If a new cookie was generated, persist it.            if (newCookieToken != null)                m_tokenStore.SaveCookieToken(response, newCookieToken);             if (!m_config.SuppressXFrameOptionsHeader)            {                // Adding X-Frame-Options header to prevent ClickJacking. See                // http://tools.ietf.org/html/draft-ietf-websec-x-frame-options-10                // for more information.                const string FrameHeaderName = "X-Frame-Options";                 if (!response.Headers.Contains(FrameHeaderName))                    response.Headers.Add(FrameHeaderName, "SAMEORIGIN");            }             // <input type="hidden" name="__AntiForgeryToken" value="..." />            TagBuilder retVal = new TagBuilder("input");             retVal.Attributes["type"] = "hidden";            retVal.Attributes["name"] = m_config.FormFieldName;            retVal.Attributes["value"] = AntiForgeryTokenSerializer.Serialize(formToken);             return retVal;        }         // [ ENTRY POINT ]        // Generates a (cookie, form) serialized token pair for the current user.        // The caller may specify an existing cookie value if one exists. If the        // 'new cookie value' out param is non-null, the caller *must* persist        // the new value to cookie storage since the original value was null or        // invalid. This method is side-effect free.        public void GetTokens(HttpRequestMessage request, string serializedOldCookieToken, out string serializedNewCookieToken, out string serializedFormToken)        {            CheckSSLConfig(request);             AntiForgeryToken oldCookieToken = DeserializeTokenNoThrow(serializedOldCookieToken);            AntiForgeryToken newCookieToken, formToken;            GetTokens(request, oldCookieToken, out newCookieToken, out formToken);             serializedNewCookieToken = Serialize(newCookieToken);            serializedFormToken = Serialize(formToken);        }         private void GetTokens(HttpRequestMessage request, AntiForgeryToken oldCookieToken, out AntiForgeryToken newCookieToken, out AntiForgeryToken formToken)        {            newCookieToken = null;             // Need to make sure we're always operating with a good cookie token.            if (!m_validator.IsCookieTokenValid(oldCookieToken))                oldCookieToken = newCookieToken = m_validator.GenerateCookieToken();             //Contract.Assert(m_validator.IsCookieTokenValid(oldCookieToken));            formToken = m_validator.GenerateFormToken(request, ExtractIdentity(request), oldCookieToken);        }         private string Serialize(AntiForgeryToken token)        {            return token != null ? AntiForgeryTokenSerializer.Serialize(token) : null;        }         // [ ENTRY POINT ]        // Given an HttpContext, validates that the anti-XSRF tokens contained        // in the cookies & form are OK for this request.        public void Validate(HttpRequestMessage request)        {            CheckSSLConfig(request);             // Extract cookie & form tokens            AntiForgeryToken cookieToken = m_tokenStore.GetCookieToken(request);            AntiForgeryToken formToken = m_tokenStore.GetFormToken(request);             // Validate            m_validator.ValidateTokens(request, ExtractIdentity(request), cookieToken, formToken);        }         // [ ENTRY POINT ]        // Given the serialized string representations of a cookie & form token,        // validates that the pair is OK for this request.        public void Validate(HttpRequestMessage request, string cookieToken, string formToken)        {            CheckSSLConfig(request);             // Extract cookie & form tokens            AntiForgeryToken deserializedCookieToken = DeserializeToken(cookieToken);            AntiForgeryToken deserializedFormToken = DeserializeToken(formToken);             // Validate            m_validator.ValidateTokens(request, ExtractIdentity(request), deserializedCookieToken, deserializedFormToken);        }    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t