Beispiel #1
0
        private async Task InvokeCore(HttpContext context)
        {
            var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName);

            if (corsPolicy == null)
            {
                Logger?.NoCorsPolicyFound();
                await _next(context);

                return;
            }

            var corsResult = CorsService.EvaluatePolicy(context, corsPolicy);

            if (corsResult.IsPreflightRequest)
            {
                CorsService.ApplyResult(corsResult, context.Response);

                // Since there is a policy which was identified,
                // always respond to preflight requests.
                context.Response.StatusCode = StatusCodes.Status204NoContent;
                return;
            }
            else
            {
                context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult));
                await _next(context);
            }
        }
Beispiel #2
0
        public void EvaluatePolicy_PreflightRequest_HeadersRequested_NotAllHeaderMatches_ReturnsInvalidResult()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(
                method: "OPTIONS",
                origin: "http://example.com",
                accessControlRequestMethod: "PUT",
                accessControlRequestHeaders: new[] { "match", "noMatch" });
            var policy = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Methods.Add("*");
            policy.Headers.Add("match");
            policy.Headers.Add("foo");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Empty(result.AllowedHeaders);
            Assert.Empty(result.AllowedMethods);
            Assert.Empty(result.AllowedExposedHeaders);
            Assert.Null(result.AllowedOrigin);
        }
Beispiel #3
0
        private Task EvaluateAndApplyPolicy(HttpContext context, CorsPolicy corsPolicy)
        {
            if (corsPolicy == null)
            {
                Logger.NoCorsPolicyFound();
                return(_next(context));
            }

            var corsResult = CorsService.EvaluatePolicy(context, corsPolicy);

            if (corsResult.IsPreflightRequest)
            {
                CorsService.ApplyResult(corsResult, context.Response);

                // Since there is a policy which was identified,
                // always respond to preflight requests.
                context.Response.StatusCode = StatusCodes.Status204NoContent;
                return(Task.CompletedTask);
            }
            else
            {
                context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult));
                return(_next(context));
            }
        }
Beispiel #4
0
        public void EvaluatePolicy_NoOrigin_ReturnsInvalidResult()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext("GET", origin: null);

            // Act
            var result = corsService.EvaluatePolicy(requestContext, new CorsPolicy());

            // Assert
            Assert.Null(result.AllowedOrigin);
            Assert.False(result.VaryByOrigin);
        }
Beispiel #5
0
        public void EvaluatePolicy_EmptyOriginsPolicy_ReturnsInvalidResult()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(origin: "http://example.com");
            var policy         = new CorsPolicy();

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Null(result.AllowedOrigin);
            Assert.False(result.VaryByOrigin);
        }
Beispiel #6
0
        public void EvaluatePolicy_NoExposedHeaders_NoAllowExposedHeaders()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(origin: "http://example.com");
            var policy         = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Empty(result.AllowedExposedHeaders);
        }
Beispiel #7
0
        public void EvaluatePolicy_PreflightRequest_MethodNotAllowed_ReturnsInvalidResult()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
            var policy         = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Methods.Add("GET");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Empty(result.AllowedMethods);
        }
Beispiel #8
0
        public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicySucceeded()
        {
            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var corsService    = new CorsService(new TestCorsOptions(), loggerFactory);
            var requestContext = GetHttpContext(origin: "http://allowed.example.com");
            var policy         = new CorsPolicy();

            policy.Origins.Add("http://allowed.example.com");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", sink.Writes[0].State.ToString());
            Assert.Equal("Policy execution successful.", sink.Writes[1].State.ToString());
        }
Beispiel #9
0
        public void EvaluatePolicy_MultiOriginsPolicy_ReturnsVaryByOriginHeader()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(origin: "http://example.com");
            var policy         = new CorsPolicy();

            policy.Origins.Add("http://example.com");
            policy.Origins.Add("http://example-two.com");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.NotNull(result.AllowedOrigin);
            Assert.True(result.VaryByOrigin);
        }
Beispiel #10
0
        public void EvaluatePolicy_OneExposedHeaders_HeadersAllowed()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(origin: "http://example.com");
            var policy         = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.ExposedHeaders.Add("foo");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal(1, result.AllowedExposedHeaders.Count);
            Assert.Contains("foo", result.AllowedExposedHeaders);
        }
Beispiel #11
0
        public void EvaluatePolicy_LoggingForPreflightRequests_DoesNotHaveOriginHeader()
        {
            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var corsService    = new CorsService(new TestCorsOptions(), loggerFactory);
            var requestContext = GetHttpContext(method: "OPTIONS", origin: null, accessControlRequestMethod: "PUT");
            var policy         = new CorsPolicy();

            policy.Origins.Add("http://allowed.example.com");
            policy.Methods.Add("PUT");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            Assert.Equal("The request is a preflight request.", sink.Writes[0].State.ToString());
            Assert.Equal("The request does not have an origin header.", sink.Writes[1].State.ToString());
        }
Beispiel #12
0
        public void EvaluatePolicy_LoggingForNonPreflightRequests_DoesNotHaveOriginHeader()
        {
            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var corsService    = new CorsService(new TestCorsOptions(), loggerFactory);
            var requestContext = GetHttpContext(origin: null);
            var policy         = new CorsPolicy();

            policy.Origins.Add("http://allowed.example.com");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            var logMessage = Assert.Single(sink.Writes);

            Assert.Equal("The request does not have an origin header.", logMessage.State.ToString());
        }
Beispiel #13
0
        public void EvaluatePolicy_SupportsCredentials_AllowCredentialsReturnsTrue()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(origin: "http://example.com");
            var policy         = new CorsPolicy
            {
                SupportsCredentials = true
            };

            policy.Origins.Add(CorsConstants.AnyOrigin);

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.True(result.SupportsCredentials);
        }
Beispiel #14
0
        public void EvaluatePolicy_PreflightRequest_ListedMethod_ReturnsSubsetOfListedMethods()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
            var policy         = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Methods.Add("PUT");
            policy.Methods.Add("DELETE");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal(1, result.AllowedMethods.Count);
            Assert.Contains("PUT", result.AllowedMethods);
        }
Beispiel #15
0
        public void EvaluatePolicy_PreflightRequest_SupportsCredentials_AllowCredentialsReturnsTrue()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
            var policy         = new CorsPolicy
            {
                SupportsCredentials = true
            };

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Methods.Add("*");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.True(result.SupportsCredentials);
        }
Beispiel #16
0
        public void EvaluatePolicy_DoesCaseSensitiveComparison()
        {
            // Arrange
            var corsService = new CorsService(new TestCorsOptions());

            var policy = new CorsPolicy();

            policy.Methods.Add("POST");
            var httpContext = GetHttpContext(origin: null, accessControlRequestMethod: "post");

            // Act
            var result = corsService.EvaluatePolicy(httpContext, policy);

            // Assert
            Assert.Empty(result.AllowedHeaders);
            Assert.Empty(result.AllowedMethods);
            Assert.Empty(result.AllowedExposedHeaders);
            Assert.Null(result.AllowedOrigin);
        }
Beispiel #17
0
        public void TryValidateOrigin_DoesCaseSensitiveComparison()
        {
            // Arrange
            var corsService = new CorsService(new TestCorsOptions());

            var policy = new CorsPolicy();

            policy.Origins.Add("http://Example.com");
            var httpContext = GetHttpContext(origin: "http://example.com");

            // Act
            var result = corsService.EvaluatePolicy(httpContext, policy);

            // Assert
            Assert.Empty(result.AllowedHeaders);
            Assert.Empty(result.AllowedMethods);
            Assert.Empty(result.AllowedExposedHeaders);
            Assert.Null(result.AllowedOrigin);
        }
Beispiel #18
0
        public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportCredentials_EmitsWildcardForOrigin()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(origin: "http://example.com");

            var policy = new CorsPolicy
            {
                SupportsCredentials = false
            };

            policy.Origins.Add(CorsConstants.AnyOrigin);

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal("*", result.AllowedOrigin);
        }
Beispiel #19
0
        public void EvaluatePolicy_AllowAnyOrigin_SupportsCredentials_AddsSpecificOrigin()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(origin: "http://example.com");
            var policy         = new CorsPolicy
            {
                SupportsCredentials = true
            };

            policy.Origins.Add(CorsConstants.AnyOrigin);

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal("http://example.com", result.AllowedOrigin);
            Assert.True(result.VaryByOrigin);
        }
Beispiel #20
0
        public void EvaluatePolicy_PreflightRequest_PreflightMaxAge_PreflightMaxAgeSet()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
            var policy         = new CorsPolicy
            {
                PreflightMaxAge = TimeSpan.FromSeconds(10)
            };

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Methods.Add("*");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal(TimeSpan.FromSeconds(10), result.PreflightMaxAge);
        }
Beispiel #21
0
        public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicyFailed()
        {
            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var corsService    = new CorsService(new TestCorsOptions(), loggerFactory);
            var requestContext = GetHttpContext(origin: "http://example.com");
            var policy         = new CorsPolicy();

            policy.Origins.Add("http://allowed.example.com");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            var writeList = sink.Writes.ToList();

            Assert.Equal("The request has an origin header: 'http://example.com'.", writeList[0].State.ToString());
            Assert.Equal("CORS policy execution failed.", writeList[1].State.ToString());
            Assert.Equal("Request origin http://example.com does not have permission to access the resource.", writeList[2].State.ToString());
        }
Beispiel #22
0
        public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicyFailed(LogData logData)
        {
            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var corsService    = new CorsService(new TestCorsOptions(), loggerFactory);
            var requestContext = GetHttpContext(method: "OPTIONS", origin: logData.Origin, accessControlRequestMethod: logData.Method, accessControlRequestHeaders: logData.Headers);
            var policy         = new CorsPolicy();

            policy.Origins.Add("http://allowed.example.com");
            policy.Methods.Add("PUT");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            Assert.Equal("The request is a preflight request.", sink.Writes[0].State.ToString());
            Assert.Equal(logData.OriginLogMessage, sink.Writes[1].State.ToString());
            Assert.Equal(logData.PolicyLogMessage, sink.Writes[2].State.ToString());
            Assert.Equal(logData.FailureReason, sink.Writes[3].State.ToString());
        }
Beispiel #23
0
        public void EvaluatePolicy_CaseInsensitivePreflightRequest_OriginAllowed_ReturnsOrigin(string preflightMethod)
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(
                method: preflightMethod,
                origin: "http://example.com",
                accessControlRequestMethod: "PUT");
            var policy = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Origins.Add("http://example.com");
            policy.Methods.Add("*");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal("http://example.com", result.AllowedOrigin);
        }
Beispiel #24
0
        public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicySucceeded()
        {
            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var corsService    = new CorsService(new TestCorsOptions(), loggerFactory);
            var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://allowed.example.com", accessControlRequestMethod: "PUT");
            var policy         = new CorsPolicy();

            policy.Origins.Add("http://allowed.example.com");
            policy.Methods.Add("PUT");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            var writeList = sink.Writes.ToList();

            Assert.Equal("The request is a preflight request.", writeList[0].State.ToString());
            Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[1].State.ToString());
            Assert.Equal("CORS policy execution successful.", writeList[2].State.ToString());
        }
Beispiel #25
0
        public void EvaluatePolicy_PreflightRequest_IsOriginAllowedReturnsTrue_ReturnsOrigin()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(
                method: "OPTIONS",
                origin: "http://example.com",
                accessControlRequestMethod: "PUT");
            var policy = new CorsPolicy
            {
                IsOriginAllowed = origin => true
            };

            policy.Methods.Add("*");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal("http://example.com", result.AllowedOrigin);
        }
Beispiel #26
0
        public void EvaluatePolicy_PreflightRequest_HeadersRequested_AllowAllHeaders_ReturnsRequestedHeaders()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(
                method: "OPTIONS",
                origin: "http://example.com",
                accessControlRequestMethod: "PUT",
                accessControlRequestHeaders: new[] { "foo", "bar" });
            var policy = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Methods.Add("*");
            policy.Headers.Add("*");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal(2, result.AllowedHeaders.Count);
            Assert.Contains("foo", result.AllowedHeaders);
            Assert.Contains("bar", result.AllowedHeaders);
        }
Beispiel #27
0
        public void EvaluatePolicy_PreflightRequest_HeadersRequested_AllowSomeHeaders_ReturnsSubsetOfListedHeaders()
        {
            // Arrange
            var corsService    = new CorsService(new TestCorsOptions());
            var requestContext = GetHttpContext(
                method: "OPTIONS",
                origin: "http://example.com",
                accessControlRequestMethod: "PUT",
                accessControlRequestHeaders: new[] { "content-type", "accept" });
            var policy = new CorsPolicy();

            policy.Origins.Add(CorsConstants.AnyOrigin);
            policy.Methods.Add("*");
            policy.Headers.Add("foo");
            policy.Headers.Add("bar");
            policy.Headers.Add("Content-Type");

            // Act
            var result = corsService.EvaluatePolicy(requestContext, policy);

            // Assert
            Assert.Equal(2, result.AllowedHeaders.Count);
            Assert.Contains("Content-Type", result.AllowedHeaders, StringComparer.OrdinalIgnoreCase);
        }
Beispiel #28
0
        private async Task InvokeCore(HttpContext context, ICorsPolicyProvider corsPolicyProvider)
        {
            // CORS policy resolution rules:
            //
            // 1. If there is an endpoint with IDisableCorsAttribute then CORS is not run
            // 2. If there is an endpoint with ICorsPolicyMetadata then use its policy or if
            //    there is an endpoint with IEnableCorsAttribute that has a policy name then
            //    fetch policy by name, prioritizing it above policy on middleware
            // 3. If there is no policy on middleware then use name on middleware

            var endpoint = context.GetEndpoint();

            // Get the most significant CORS metadata for the endpoint
            // For backwards compatibility reasons this is then downcast to Enable/Disable metadata
            var corsMetadata = endpoint?.Metadata.GetMetadata <ICorsMetadata>();

            if (corsMetadata is IDisableCorsAttribute)
            {
                var isOptionsRequest = string.Equals(
                    context.Request.Method,
                    CorsConstants.PreflightHttpMethod,
                    StringComparison.OrdinalIgnoreCase);

                var isCorsPreflightRequest = isOptionsRequest && context.Request.Headers.ContainsKey(CorsConstants.AccessControlRequestMethod);

                if (isCorsPreflightRequest)
                {
                    // If this is a preflight request, and we disallow CORS, complete the request
                    context.Response.StatusCode = StatusCodes.Status204NoContent;
                    return;
                }

                await _next(context);

                return;
            }

            var corsPolicy = _policy;
            var policyName = _corsPolicyName;

            if (corsMetadata is ICorsPolicyMetadata corsPolicyMetadata)
            {
                policyName = null;
                corsPolicy = corsPolicyMetadata.Policy;
            }
            else if (corsMetadata is IEnableCorsAttribute enableCorsAttribute &&
                     enableCorsAttribute.PolicyName != null)
            {
                // If a policy name has been provided on the endpoint metadata then prioritizing it above the static middleware policy
                policyName = enableCorsAttribute.PolicyName;
                corsPolicy = null;
            }

            if (corsPolicy == null)
            {
                // Resolve policy by name if the local policy is not being used
                corsPolicy = await corsPolicyProvider.GetPolicyAsync(context, policyName);
            }

            if (corsPolicy == null)
            {
                Logger?.NoCorsPolicyFound();
                await _next(context);

                return;
            }

            var corsResult = CorsService.EvaluatePolicy(context, corsPolicy);

            if (corsResult.IsPreflightRequest)
            {
                CorsService.ApplyResult(corsResult, context.Response);

                // Since there is a policy which was identified,
                // always respond to preflight requests.
                context.Response.StatusCode = StatusCodes.Status204NoContent;
                return;
            }
            else
            {
                context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult));
                await _next(context);
            }
        }
Beispiel #29
0
        private async Task InvokeCore(HttpContext context, ICorsPolicyProvider corsPolicyProvider)
        {
            // CORS policy resolution rules:
            //
            // 1. If there is an endpoint with IDisableCorsAttribute then CORS is not run
            // 2. If there is an endpoint with ICorsPolicyMetadata then use its policy or if
            //    there is an endpoint with IEnableCorsAttribute that has a policy name then
            //    fetch policy by name, prioritizing it above policy on middleware
            // 3. If there is no policy on middleware then use name on middleware

            // Flag to indicate to other systems, e.g. MVC, that CORS middleware was run for this request
            context.Items[CorsMiddlewareInvokedKey] = CorsMiddlewareInvokedValue;

            var endpoint = context.GetEndpoint();

            // Get the most significant CORS metadata for the endpoint
            // For backwards compatibility reasons this is then downcast to Enable/Disable metadata
            var corsMetadata = endpoint?.Metadata.GetMetadata <ICorsMetadata>();

            if (corsMetadata is IDisableCorsAttribute)
            {
                await _next(context);

                return;
            }

            var corsPolicy = _policy;
            var policyName = _corsPolicyName;

            if (corsMetadata is ICorsPolicyMetadata corsPolicyMetadata)
            {
                policyName = null;
                corsPolicy = corsPolicyMetadata.Policy;
            }
            else if (corsMetadata is IEnableCorsAttribute enableCorsAttribute &&
                     enableCorsAttribute.PolicyName != null)
            {
                // If a policy name has been provided on the endpoint metadata then prioritizing it above the static middleware policy
                policyName = enableCorsAttribute.PolicyName;
                corsPolicy = null;
            }

            if (corsPolicy == null)
            {
                // Resolve policy by name if the local policy is not being used
                corsPolicy = await corsPolicyProvider.GetPolicyAsync(context, policyName);
            }

            if (corsPolicy == null)
            {
                Logger?.NoCorsPolicyFound();
                await _next(context);

                return;
            }

            var corsResult = CorsService.EvaluatePolicy(context, corsPolicy);

            if (corsResult.IsPreflightRequest)
            {
                CorsService.ApplyResult(corsResult, context.Response);

                // Since there is a policy which was identified,
                // always respond to preflight requests.
                context.Response.StatusCode = StatusCodes.Status204NoContent;
                return;
            }
            else
            {
                context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult));
                await _next(context);
            }
        }