예제 #1
0
        /// <summary>
        /// Modifies the HTTP request message pipeline to include a session identifier.
        /// </summary>
        /// <param name="request">The HTTP request message to send to the server.</param>
        /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
        /// <returns>HTTP response message.</returns>
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // Get existing session data from the request, if any
            CookieHeaderValue cookie             = request.Headers.GetCookies(SessionToken).FirstOrDefault();
            string            sessionCookieValue = cookie?[SessionToken].Value;
            Guid sessionID;

            // If session ID format is invalid, create a new one
            if (!Guid.TryParse(sessionCookieValue, out sessionID))
            {
                sessionID = Guid.NewGuid();
            }

            sessionCookieValue = sessionID.ToString();

            // Save session ID (as Guid) in the request properties
            request.Properties[SessionToken] = sessionID;

            // Continue processing the HTTP request
            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

            // Store session ID in response message cookie
            response.Headers.AddCookies(new[] { new CookieHeaderValue(SessionToken, sessionCookieValue)
                                                {
                                                    Path = "/"
                                                } });

            // Get authentication options associated with this request
            ReadonlyAuthenticationOptions options = request.GetAuthenticationOptions();

            // If requesting the AuthTest page using BASIC authentication, reissue the client's authentication token
            string authTestPage = options.AuthTestPage;

            if (request.RequestUri.LocalPath == authTestPage)
            {
                SecurityPrincipal securityPrincipal = request.GetRequestContext().Principal as SecurityPrincipal;
                SecurityIdentity  securityIdentity  = securityPrincipal?.Identity;
                ISecurityProvider securityProvider  = securityIdentity?.Provider;

                string username = securityIdentity?.Name;
                string password = securityProvider?.Password;

                if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
                {
                    string authenticationToken = IssueAuthenticationToken(username, password);

                    InvalidateAuthenticationToken(request);

                    response.Headers.AddCookies(new[]
                    {
                        new CookieHeaderValue(AuthenticationToken, authenticationToken)
                        {
                            Path   = request.RequestUri.LocalPath,
                            MaxAge = TimeSpan.FromDays(30.0D)
                        }
                    });
                }

                // AuthTest page should always have a valid request verification token
                request.ValidateRequestVerificationToken(options);
            }

            return(response);
        }
예제 #2
0
        /// <summary>
        /// Validates that the anti-forgery request verification token value comes from the user who submitted the data.
        /// </summary>
        /// <param name="request">HTTP request message.</param>
        /// <param name="options">Read-only authentication options for this <paramref name="request"/>.</param>
        /// <param name="formValidation">Flag that determines if form validation should be used.</param>
        public static void ValidateRequestVerificationToken(this HttpRequestMessage request, ReadonlyAuthenticationOptions options, bool formValidation = false)
        {
            if (formValidation)
            {
                // Form validation
                AntiForgery.Validate(request);
            }
            else
            {
                // Header validation
                string cookieToken = "";
                string formToken   = "";

                IEnumerable <string> tokenHeaders;

                if (request.Headers.TryGetValues(options.RequestVerificationToken, out tokenHeaders))
                {
                    string[] tokens = tokenHeaders.First().Split(':');

                    if (tokens.Length == 2)
                    {
                        cookieToken = tokens[0].Trim();
                        formToken   = tokens[1].Trim();
                    }
                }

                AntiForgery.Validate(request, cookieToken, formToken);
            }
        }
예제 #3
0
        /// <summary>
        /// Validates that the anti-forgery request verification token value comes from the user who submitted the data.
        /// </summary>
        /// <param name="request">HTTP request message.</param>
        /// <param name="options">Read-only authentication options for this <paramref name="request"/>.</param>
        /// <param name="formValidation">Flag that determines if form validation should be used.</param>
        public static void ValidateRequestVerificationToken(this HttpRequestMessage request, ReadonlyAuthenticationOptions options, bool formValidation = false)
        {
            bool tryGetTokens(string name, out Tuple <string, string> values)
            {
                if (request.Headers.TryGetValues(name, out IEnumerable <string> tokenHeaders))
                {
                    string[] tokens = tokenHeaders.First().Split(':');

                    switch (tokens.Length)
                    {
                    case 1:
                        values = new Tuple <string, string>(name, tokens[0].Trim());
                        return(true);

                    case 2:
                        values = new Tuple <string, string>(tokens[0].Trim(), tokens[1].Trim());
                        return(true);
                    }
                }

                values = default;
                return(false);
            }

            // Check for anti-forgery operation with AJAX requests, in these cases, do not perform form validation
            if (tryGetTokens(options.AjaxRequestVerificationToken, out Tuple <string, string> tokenValues) && tokenValues.Item2.ParseBoolean())
            {
                formValidation = false;
            }

            if (formValidation)
            {
                // Form validation
                AntiForgery.Validate(request);
            }
            else
            {
                // Header validation
                string cookieToken = "";
                string formToken   = "";

                if (tryGetTokens(options.RequestVerificationToken, out tokenValues))
                {
                    cookieToken = tokenValues.Item1;
                    formToken   = tokenValues.Item2;
                }

                AntiForgery.Validate(request, cookieToken, formToken);
            }
        }