Example #1
0
        public void ApplyResult_ManyAllowExposedHeaders_ExposedHeadersHeaderAdded()
        {
            // Arrange
            var result = new CorsResult();

            result.AllowedExposedHeaders.Add("foo");
            result.AllowedExposedHeaders.Add("bar");
            result.AllowedExposedHeaders.Add("baz");

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Contains("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys);
            var value = Assert.Single(httpContext.Response.Headers.Values);

            Assert.Equal(new[] { "foo,bar,baz" }, value);
            string[] exposedHeaderValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Expose-Headers");
            Assert.Equal(3, exposedHeaderValues.Length);
            Assert.Contains("foo", exposedHeaderValues);
            Assert.Contains("bar", exposedHeaderValues);
            Assert.Contains("baz", exposedHeaderValues);
        }
Example #2
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);
            }
        }
Example #3
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);
        }
Example #4
0
        public void ApplyResult_SimpleRequests_IgnoresFiltering()
        {
            // Arrange
            var result = new CorsResult();

            result.AllowedHeaders.Add("Content-Type");
            result.AllowedHeaders.Add("Date");
            result.AllowedMethods.Add("GET");
            result.AllowedMethods.Add("PUT");

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());


            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            string[] arMethods = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowMethods);
            Assert.Contains("GET", arMethods);
            Assert.Contains("PUT", arMethods);
            string[] arHeaders = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowHeaders);
            Assert.Contains("Content-Type", arHeaders);
            Assert.Contains("Date", arHeaders);
        }
Example #5
0
        public void ApplyResult_SomeSimpleAllowMethods_AllowMethodsHeaderAddedForNonSimpleMethods()
        {
            // Arrange
            var result = new CorsResult();

            result.AllowedMethods.Add("PUT");
            result.AllowedMethods.Add("get");
            result.AllowedMethods.Add("DELETE");
            result.AllowedMethods.Add("POST");

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Contains("Access-Control-Allow-Methods", httpContext.Response.Headers.Keys);
            var value = Assert.Single(httpContext.Response.Headers.Values);

            Assert.Equal(new[] { "PUT,DELETE" }, value);
            string[] methods = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Allow-Methods");
            Assert.Equal(2, methods.Length);
            Assert.Contains("PUT", methods);
            Assert.Contains("DELETE", methods);
        }
Example #6
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));
            }
        }
Example #7
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);
        }
Example #8
0
        public void ApplyResult_ReturnsNoHeaders_ByDefault()
        {
            // Arrange
            var result      = new CorsResult();
            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Empty(httpContext.Response.Headers);
        }
Example #9
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);
        }
Example #10
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);
        }
Example #11
0
        public void ApplyResult_PreflightMaxAge_MaxAgeHeaderAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                PreflightMaxAge = TimeSpan.FromSeconds(30)
            };
            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Equal("30", httpContext.Response.Headers["Access-Control-Max-Age"]);
        }
Example #12
0
        public void ApplyResult_OneAllowExposedHeaders_ExposedHeadersHeaderAdded()
        {
            // Arrange
            var result = new CorsResult();

            result.AllowedExposedHeaders.Add("foo");

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Equal("foo", httpContext.Response.Headers["Access-Control-Expose-Headers"]);
        }
Example #13
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);
        }
Example #14
0
        public void ApplyResult_OneAllowMethods_AllowMethodsHeaderAdded()
        {
            // Arrange
            var result = new CorsResult();

            result.AllowedMethods.Add("PUT");

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Equal("PUT", httpContext.Response.Headers["Access-Control-Allow-Methods"]);
        }
Example #15
0
        public void ApplyResult_NoAllowExposedHeaders_ExposedHeadersHeaderNotAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                // AllowExposedHeaders is empty by default
            };

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.DoesNotContain("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys);
        }
Example #16
0
        public void ApplyResult_AddVaryHeader_VaryHeaderAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                VaryByOrigin = true
            };

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Equal("Origin", httpContext.Response.Headers["Vary"]);
        }
Example #17
0
        public void ApplyResult_NoAllowCredentials_AllowCredentialsHeaderNotAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                SupportsCredentials = false
            };

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.DoesNotContain("Access-Control-Allow-Credentials", httpContext.Response.Headers.Keys);
        }
Example #18
0
        public void ApplyResult_NoAllowOrigin_AllowOriginHeaderNotAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                AllowedOrigin = null
            };

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.DoesNotContain("Access-Control-Allow-Origin", httpContext.Response.Headers.Keys);
        }
Example #19
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());
        }
Example #20
0
        public void ApplyResult_AllowOrigin_AllowOriginHeaderAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                AllowedOrigin = "http://example.com"
            };

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Equal("http://example.com", httpContext.Response.Headers["Access-Control-Allow-Origin"]);
        }
Example #21
0
        public void ApplyResult_NoPreflightMaxAge_MaxAgeHeaderNotAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                PreflightMaxAge = null
            };

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.DoesNotContain("Access-Control-Max-Age", httpContext.Response.Headers.Keys);
        }
Example #22
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);
        }
Example #23
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);
        }
Example #24
0
        public async Task Invoke_WithCustomPolicyProviderThatReturnsAsynchronously_Works()
        {
            // Arrange
            var corsService   = new CorsService(Options.Create(new CorsOptions()), NullLoggerFactory.Instance);
            var mockProvider  = new Mock <ICorsPolicyProvider>();
            var loggerFactory = NullLoggerFactory.Instance;
            var policy        = new CorsPolicyBuilder()
                                .WithOrigins(OriginUrl)
                                .WithHeaders("AllowedHeader")
                                .Build();

            mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny <HttpContext>(), It.IsAny <string>()))
            .ReturnsAsync(policy, TimeSpan.FromMilliseconds(10));

            var middleware = new CorsMiddleware(
                Mock.Of <RequestDelegate>(),
                corsService,
                loggerFactory,
                "DefaultPolicyName");

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = "OPTIONS";
            httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { OriginUrl });
            httpContext.Request.Headers.Add(CorsConstants.AccessControlRequestMethod, new[] { "PUT" });

            // Act
            await middleware.Invoke(httpContext, mockProvider.Object);

            // Assert
            var response = httpContext.Response;

            Assert.Collection(
                response.Headers.OrderBy(o => o.Key),
                kvp =>
            {
                Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key);
                Assert.Equal("AllowedHeader", Assert.Single(kvp.Value));
            },
                kvp =>
            {
                Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key);
                Assert.Equal(OriginUrl, Assert.Single(kvp.Value));
            });
        }
Example #25
0
        public void ApplyResult_AllowCredentials_AllowCredentialsHeaderAdded()
        {
            // Arrange
            var result = new CorsResult
            {
                SupportsCredentials = true
            };

            var service = new CorsService(new TestCorsOptions());

            // Act
            var httpContext = new DefaultHttpContext();

            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.Equal("true", httpContext.Response.Headers["Access-Control-Allow-Credentials"]);
        }
Example #26
0
        public void ApplyResult_SimpleAllowMethods_AllowMethodsHeaderNotAdded()
        {
            // Arrange
            var result = new CorsResult();

            result.AllowedMethods.Add("GET");
            result.AllowedMethods.Add("HEAD");
            result.AllowedMethods.Add("POST");

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.DoesNotContain("Access-Control-Allow-Methods", httpContext.Response.Headers.Keys);
        }
Example #27
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());
        }
Example #28
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);
        }
Example #29
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());
        }
Example #30
0
        public void ApplyResult_SimpleAllowHeaders_AllowHeadersHeaderNotAdded()
        {
            // Arrange
            var result = new CorsResult();

            result.AllowedHeaders.Add("Accept");
            result.AllowedHeaders.Add("Accept-Language");
            result.AllowedHeaders.Add("Content-Language");

            var httpContext = new DefaultHttpContext();
            var service     = new CorsService(new TestCorsOptions());

            // Act
            service.ApplyResult(result, httpContext.Response);

            // Assert
            Assert.DoesNotContain("Access-Control-Allow-Headers", httpContext.Response.Headers.Keys);
        }