public void EvaluatePolicy_IsOriginAllowedReturnsFalse_ReturnsInvalidResult() { // Arrange var corsService = new CorsService(new TestCorsOptions()); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy() { IsOriginAllowed = origin => false }; policy.Origins.Add("example.com"); // Act var result = corsService.EvaluatePolicy(requestContext, policy); // Assert Assert.Null(result.AllowedOrigin); Assert.False(result.VaryByOrigin); }
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); }
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); }
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); }
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); }
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); var writeList = sink.Writes.ToList(); Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[0].State.ToString()); Assert.Equal("Policy execution successful.", writeList[1].State.ToString()); }
public void EvaluatePolicy_PreflightRequest_NoPreflightMaxAge_NoPreflightMaxAgeSet() { // Arrange var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy { PreflightMaxAge = null }; policy.Origins.Add(CorsConstants.AnyOrigin); policy.Methods.Add("*"); // Act var result = corsService.EvaluatePolicy(requestContext, policy); // Assert Assert.Null(result.PreflightMaxAge); }
public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportCredentials_EmitsOriginHeader() { // Arrange var corsService = GetCorsService(); 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); }
public async Task PreFlight_MatchesPolicy_SetsResponseHeaders() { // Arrange var policy = new CorsPolicy(); policy.Origins.Add("http://localhost:5001"); policy.Methods.Add("PUT"); policy.Headers.Add("Header1"); policy.ExposedHeaders.Add("AllowedHeader"); var hostBuilder = new WebHostBuilder() .Configure(app => { app.UseCors("customPolicy"); app.Run(async context => { await context.Response.WriteAsync("Cross origin response"); }); }) .ConfigureServices(services => { services.AddCors(options => { options.AddPolicy("customPolicy", policy); }); }); using (var server = new TestServer(hostBuilder)) { // Act // Preflight request. var response = await server.CreateRequest("/") .AddHeader(CorsConstants.Origin, "http://localhost:5001") .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT") .SendAsync(CorsConstants.PreflightHttpMethod); // Assert response.EnsureSuccessStatusCode(); Assert.Equal(2, response.Headers.Count()); Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); Assert.Equal("PUT", response.Headers.GetValues(CorsConstants.AccessControlAllowMethods).FirstOrDefault()); } }
public void EaluatePolicy_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); }
private bool IsOriginAllowed(CorsPolicy policy, StringValues origin) { if (StringValues.IsNullOrEmpty(origin)) { _logger.RequestDoesNotHaveOriginHeader(); return(false); } var originString = origin.ToString(); _logger.RequestHasOriginHeader(originString); if (policy.AllowAnyOrigin || policy.IsOriginAllowed(originString)) { _logger.PolicySuccess(); return(true); } _logger.PolicyFailure(); _logger.OriginNotAllowed(originString); return(false); }
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()); }
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); }
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); var writeList = sink.Writes.ToList(); Assert.Equal("The request is a preflight request.", writeList[0].State.ToString()); Assert.Equal("The request does not have an origin header.", writeList[1].State.ToString()); }
public void EvaluatePolicy_CaseInsensitivePreflightRequest_ReturnsAllowedMethods(string method) { // Arrange var corsService = GetCorsService(); var requestContext = GetHttpContext( method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: method); 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(new[] { "PUT", "DELETE" }, result.AllowedMethods); }
public async Task GetsNamedPolicy(string policyName) { // Arrange var options = new CorsOptions(); var policy = new CorsPolicy(); options.AddPolicy(policyName, policy); var corsOptions = new TestCorsOptions { Value = options }; var policyProvider = new DefaultCorsPolicyProvider(corsOptions); // Act var actualPolicy = await policyProvider.GetPolicyAsync(new DefaultHttpContext(), policyName); // Assert Assert.Same(policy, actualPolicy); }
public void EvaluatePolicy_ManyExposedHeaders_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"); policy.ExposedHeaders.Add("bar"); policy.ExposedHeaders.Add("baz"); // Act var result = corsService.EvaluatePolicy(requestContext, policy); // Assert Assert.Equal(3, result.AllowedExposedHeaders.Count); Assert.Contains("foo", result.AllowedExposedHeaders); Assert.Contains("bar", result.AllowedExposedHeaders); Assert.Contains("baz", result.AllowedExposedHeaders); }
public void EvaluatePolicy_PreflightRequest_WithCredentials_ReflectsHeaders() { // Arrange var corsService = GetCorsService(); var httpContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy(); policy.Origins.Add("http://example.com"); policy.Methods.Add("*"); policy.Headers.Add("*"); policy.SupportsCredentials = true; // Act var result = corsService.EvaluatePolicy(httpContext, policy); // Assert Assert.NotNull(result); Assert.Equal(new[] { "PUT" }, result.AllowedMethods); Assert.Empty(result.AllowedHeaders); Assert.True(result.SupportsCredentials); }
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); }
public async Task PreFlight_MatchesPolicy_OnCaseInsensitiveOptionsMethod(string preflightMethod) { // Arrange var policy = new CorsPolicy(); policy.Origins.Add(OriginUrl); policy.Methods.Add("PUT"); var hostBuilder = new WebHostBuilder() .Configure(app => { app.UseCors("customPolicy"); app.Run(async context => { await context.Response.WriteAsync("Cross origin response"); }); }) .ConfigureServices(services => { services.AddCors(options => { options.AddPolicy("customPolicy", policy); }); }); using (var server = new TestServer(hostBuilder)) { // Act // Preflight request. var response = await server.CreateRequest("/") .AddHeader(CorsConstants.Origin, OriginUrl) .SendAsync(preflightMethod); // Assert response.EnsureSuccessStatusCode(); Assert.Single(response.Headers); Assert.Equal(OriginUrl, response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); } }
public void EvaluatePolicy_PreflightRequest_AllowAllHeaders_ReflectsRequestHeaders() { // Arrange var corsService = GetCorsService(); 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(new[] { "foo", "bar" }, result.AllowedHeaders); Assert.Equal(new[] { "PUT" }, result.AllowedMethods); }
public void AddDefaultPolicy_UsingPolicyBuilder_SetsDefaultPolicyName() { // Arrange var corsOptions = new CorsOptions(); CorsPolicy expectedPolicy = null; // Act corsOptions.AddPolicy("policy1", policyBuilder => { policyBuilder.AllowAnyOrigin().Build(); }); corsOptions.AddDefaultPolicy(policyBuilder => { expectedPolicy = policyBuilder.AllowAnyOrigin().Build(); }); corsOptions.AddPolicy("policy3", new CorsPolicy()); // Assert var actualPolicy = corsOptions.GetPolicy(corsOptions.DefaultPolicyName); Assert.Same(expectedPolicy, actualPolicy); }
public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result) { var origin = context.Request.Headers[CorsConstants.Origin]; if (StringValues.IsNullOrEmpty(origin) || !policy.AllowAnyOrigin && !policy.Origins.Contains(origin)) { return; } var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; if (StringValues.IsNullOrEmpty(accessControlRequestMethod)) { return; } var requestHeaders = context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders); if (!policy.AllowAnyMethod && !policy.Methods.Contains(accessControlRequestMethod)) { return; } if (!policy.AllowAnyHeader && requestHeaders != null && !requestHeaders.All(header => CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase) || policy.Headers.Contains(header, StringComparer.OrdinalIgnoreCase))) { return; } AddOriginToResult(origin, policy, result); result.SupportsCredentials = policy.SupportsCredentials; result.PreflightMaxAge = policy.PreflightMaxAge; result.AllowedMethods.Add(accessControlRequestMethod); AddHeaderValues(result.AllowedHeaders, requestHeaders); }
public void ConstructorWithPolicy_HavingNullPreflightMaxAge_AddsTheGivenPolicy() { // Arrange var originalPolicy = new CorsPolicy(); originalPolicy.Origins.Add("http://existing.com"); // Act var builder = new CorsPolicyBuilder(originalPolicy); // Assert var corsPolicy = builder.Build(); Assert.Null(corsPolicy.PreflightMaxAge); Assert.False(corsPolicy.AllowAnyHeader); Assert.False(corsPolicy.AllowAnyMethod); Assert.False(corsPolicy.AllowAnyOrigin); Assert.NotSame(originalPolicy.Origins, corsPolicy.Origins); Assert.Equal(originalPolicy.Origins, corsPolicy.Origins); Assert.Empty(corsPolicy.Headers); Assert.Empty(corsPolicy.Methods); Assert.Empty(corsPolicy.ExposedHeaders); }
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); }
private void AddOriginToResult(string origin, CorsPolicy policy, CorsResult result) { if (policy.AllowAnyOrigin) { if (policy.SupportsCredentials) { result.AllowedOrigin = origin; result.VaryByOrigin = true; } else { result.AllowedOrigin = CorsConstants.AnyOrigin; } } else if (policy.IsOriginAllowed(origin)) { result.AllowedOrigin = origin; if (policy.Origins.Count > 1) { result.VaryByOrigin = true; } } }
/// <summary> /// Instantiates a new <see cref="CorsMiddleware"/>. /// </summary> /// <param name="next">The next middleware in the pipeline.</param> /// <param name="corsService">An instance of <see cref="ICorsService"/>.</param> /// <param name="policy">An instance of the <see cref="CorsPolicy"/> which can be applied.</param> public CorsMiddleware( RequestDelegate next, ICorsService corsService, CorsPolicy policy) { if (next == null) { throw new ArgumentNullException(nameof(next)); } if (corsService == null) { throw new ArgumentNullException(nameof(corsService)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } _next = next; _corsService = corsService; _policy = policy; }
public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result) { var origin = context.Request.Headers[CorsConstants.Origin]; if (!IsOriginAllowed(policy, origin)) { return; } var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; if (StringValues.IsNullOrEmpty(accessControlRequestMethod)) { return; } var requestHeaders = context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders); if (!policy.AllowAnyMethod) { var found = false; for (var i = 0; i < policy.Methods.Count; i++) { var method = policy.Methods[i]; if (string.Equals(method, accessControlRequestMethod, StringComparison.OrdinalIgnoreCase)) { found = true; break; } } if (!found) { _logger?.PolicyFailure(); _logger?.AccessControlMethodNotAllowed(accessControlRequestMethod); return; } } if (!policy.AllowAnyHeader && requestHeaders != null) { foreach (var requestHeader in requestHeaders) { if (!CorsConstants.SimpleRequestHeaders.Contains(requestHeader, StringComparer.OrdinalIgnoreCase) && !policy.Headers.Contains(requestHeader, StringComparer.OrdinalIgnoreCase)) { _logger?.PolicyFailure(); _logger?.RequestHeaderNotAllowed(requestHeader); return; } } } AddOriginToResult(origin, policy, result); result.SupportsCredentials = policy.SupportsCredentials; result.PreflightMaxAge = policy.PreflightMaxAge; result.AllowedMethods.Add(accessControlRequestMethod); AddHeaderValues(result.AllowedHeaders, requestHeaders); _logger?.PolicySuccess(); }
public async Task PreFlight_MatchesPolicy_SetsResponseHeaders() { // Arrange var policy = new CorsPolicy(); policy.Origins.Add(OriginUrl); policy.Methods.Add("PUT"); policy.Headers.Add("Header1"); policy.ExposedHeaders.Add("AllowedHeader"); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseCors("customPolicy"); app.Run(async context => { await context.Response.WriteAsync("Cross origin response"); }); }) .ConfigureServices(services => { services.AddCors(options => { options.AddPolicy("customPolicy", policy); }); }); }).Build(); await host.StartAsync(); using (var server = host.GetTestServer()) { // Act // Preflight request. var response = await server.CreateRequest("/") .AddHeader(CorsConstants.Origin, OriginUrl) .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT") .SendAsync(CorsConstants.PreflightHttpMethod); // Assert response.EnsureSuccessStatusCode(); Assert.Collection( response.Headers.OrderBy(h => h.Key), kvp => { Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key); Assert.Equal(new[] { "Header1" }, kvp.Value); }, kvp => { Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key); Assert.Equal(new[] { "PUT" }, kvp.Value); }, kvp => { Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); Assert.Equal(new[] { OriginUrl }, kvp.Value); }); } }
public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result) { PopulateResult(context, policy, result); }