Merge pull request #9286 from dotnet-maestro-bot/merge/release/3.0-preview4-to-master
[automated] Merge branch 'release/3.0-preview4' => 'master'
This commit is contained in:
commit
9173c5adeb
|
|
@ -1,6 +1,18 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Authorization
|
||||||
|
{
|
||||||
|
public partial interface IAllowAnonymous
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public partial interface IAuthorizeData
|
||||||
|
{
|
||||||
|
string AuthenticationSchemes { get; set; }
|
||||||
|
string Policy { get; set; }
|
||||||
|
string Roles { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
namespace Microsoft.AspNetCore.Builder
|
namespace Microsoft.AspNetCore.Builder
|
||||||
{
|
{
|
||||||
public abstract partial class EndpointBuilder
|
public abstract partial class EndpointBuilder
|
||||||
|
|
@ -87,6 +99,12 @@ namespace Microsoft.AspNetCore.Builder.Extensions
|
||||||
public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) { throw null; }
|
public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) { throw null; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
|
{
|
||||||
|
public partial interface ICorsMetadata
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
namespace Microsoft.AspNetCore.Http
|
namespace Microsoft.AspNetCore.Http
|
||||||
{
|
{
|
||||||
public abstract partial class ConnectionInfo
|
public abstract partial class ConnectionInfo
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
namespace Microsoft.AspNetCore.Authorization
|
namespace Microsoft.AspNetCore.Authorization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marker interface to enable the <see cref="AllowAnonymousAttribute"/>.
|
/// Marker interface to allow access to anonymous users.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IAllowAnonymous
|
public interface IAllowAnonymous
|
||||||
{
|
{
|
||||||
|
|
@ -322,6 +322,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
public System.Collections.Generic.ICollection<Microsoft.AspNetCore.Routing.EndpointDataSource> EndpointDataSources { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
public System.Collections.Generic.ICollection<Microsoft.AspNetCore.Routing.EndpointDataSource> EndpointDataSources { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||||
public bool LowercaseQueryStrings { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
public bool LowercaseQueryStrings { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
public bool LowercaseUrls { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
public bool LowercaseUrls { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
|
public bool SuppressCheckForUnhandledSecurityMetadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
}
|
}
|
||||||
public partial class RouteValueEqualityComparer : System.Collections.Generic.IEqualityComparer<object>
|
public partial class RouteValueEqualityComparer : System.Collections.Generic.IEqualityComparer<object>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,34 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
internal sealed class EndpointMiddleware
|
internal sealed class EndpointMiddleware
|
||||||
{
|
{
|
||||||
|
internal const string AuthorizationMiddlewareInvokedKey = "__AuthorizationMiddlewareInvoked";
|
||||||
|
internal const string CorsMiddlewareInvokedKey = "__CorsMiddlewareInvoked";
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
|
private readonly RouteOptions _routeOptions;
|
||||||
|
|
||||||
public EndpointMiddleware(ILogger<EndpointMiddleware> logger, RequestDelegate next)
|
public EndpointMiddleware(
|
||||||
|
ILogger<EndpointMiddleware> logger,
|
||||||
|
RequestDelegate next,
|
||||||
|
IOptions<RouteOptions> routeOptions)
|
||||||
{
|
{
|
||||||
if (logger == null)
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
{
|
_next = next ?? throw new ArgumentNullException(nameof(next));
|
||||||
throw new ArgumentNullException(nameof(logger));
|
_routeOptions = routeOptions?.Value ?? throw new ArgumentNullException(nameof(routeOptions));
|
||||||
}
|
|
||||||
|
|
||||||
if (next == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(next));
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger = logger;
|
|
||||||
_next = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext httpContext)
|
public async Task Invoke(HttpContext httpContext)
|
||||||
|
|
@ -35,6 +36,24 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint = httpContext.Features.Get<IEndpointFeature>()?.Endpoint;
|
var endpoint = httpContext.Features.Get<IEndpointFeature>()?.Endpoint;
|
||||||
if (endpoint?.RequestDelegate != null)
|
if (endpoint?.RequestDelegate != null)
|
||||||
{
|
{
|
||||||
|
if (_routeOptions.SuppressCheckForUnhandledSecurityMetadata)
|
||||||
|
{
|
||||||
|
// User opted out of this check.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endpoint.Metadata.GetMetadata<IAuthorizeData>() != null &&
|
||||||
|
!httpContext.Items.ContainsKey(AuthorizationMiddlewareInvokedKey))
|
||||||
|
{
|
||||||
|
ThrowMissingAuthMiddlewareException(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endpoint.Metadata.GetMetadata<ICorsMetadata>() != null &&
|
||||||
|
!httpContext.Items.ContainsKey(CorsMiddlewareInvokedKey))
|
||||||
|
{
|
||||||
|
ThrowMissingCorsMiddlewareException(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
Log.ExecutingEndpoint(_logger, endpoint);
|
Log.ExecutingEndpoint(_logger, endpoint);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -52,6 +71,22 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
await _next(httpContext);
|
await _next(httpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ThrowMissingAuthMiddlewareException(Endpoint endpoint)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Endpoint {endpoint.DisplayName} contains authorization metadata, " +
|
||||||
|
"but a middleware was not found that supports authorization." +
|
||||||
|
Environment.NewLine +
|
||||||
|
"Configure your application startup by adding app.UseAuthorization() inside the call to Configure(..) in the application startup code.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ThrowMissingCorsMiddlewareException(Endpoint endpoint)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Endpoint {endpoint.DisplayName} contains CORS metadata, " +
|
||||||
|
"but a middleware was not found that supports CORS." +
|
||||||
|
Environment.NewLine +
|
||||||
|
"Configure your application startup by adding app.UseCors() inside the call to Configure(..) in the application startup code.");
|
||||||
|
}
|
||||||
|
|
||||||
private static class Log
|
private static class Log
|
||||||
{
|
{
|
||||||
private static readonly Action<ILogger, string, Exception> _executingEndpoint = LoggerMessage.Define<string>(
|
private static readonly Action<ILogger, string, Exception> _executingEndpoint = LoggerMessage.Define<string>(
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,26 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AppendTrailingSlash { get; set; }
|
public bool AppendTrailingSlash { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value that indicates if the check for unhandled security endpoint metadata is suppressed.
|
||||||
|
/// <para>
|
||||||
|
/// Endpoints can be associated with metadata such as authorization, or CORS, that needs to be
|
||||||
|
/// handled by a specific middleware to be actionable. If the middleware is not configured, such
|
||||||
|
/// metadata will go unhandled.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// When <see langword="false"/>, prior to the execution of the endpoint, routing will verify that
|
||||||
|
/// all known security-specific metadata has been handled.
|
||||||
|
/// Setting this property to <see langword="true"/> suppresses this check.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <value>Defaults to <see langword="false"/>.</value>
|
||||||
|
/// <remarks>
|
||||||
|
/// This check exists as a safeguard against accidental insecure configuration. You may suppress
|
||||||
|
/// this check if it does not match your application's requirements.
|
||||||
|
/// </remarks>
|
||||||
|
public bool SuppressCheckForUnhandledSecurityMetadata { get; set; }
|
||||||
|
|
||||||
private IDictionary<string, Type> _constraintTypeMap = GetDefaultConstraintMap();
|
private IDictionary<string, Type> _constraintTypeMap = GetDefaultConstraintMap();
|
||||||
|
|
||||||
public IDictionary<string, Type> ConstraintMap
|
public IDictionary<string, Type> ConstraintMap
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,23 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
public class EndpointMiddlewareTest
|
public class EndpointMiddlewareTest
|
||||||
{
|
{
|
||||||
|
private readonly IOptions<RouteOptions> RouteOptions = Options.Create(new RouteOptions());
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Invoke_NoFeature_NoOps()
|
public async Task Invoke_NoFeature_NoOps()
|
||||||
{
|
{
|
||||||
|
|
@ -24,7 +30,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next, RouteOptions);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await middleware.Invoke(httpContext);
|
await middleware.Invoke(httpContext);
|
||||||
|
|
@ -49,7 +55,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next, RouteOptions);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await middleware.Invoke(httpContext);
|
await middleware.Invoke(httpContext);
|
||||||
|
|
@ -81,7 +87,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next, RouteOptions);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await middleware.Invoke(httpContext);
|
await middleware.Invoke(httpContext);
|
||||||
|
|
@ -90,6 +96,146 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
Assert.True(invoked);
|
Assert.True(invoked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_WithEndpoint_ThrowsIfAuthAttributesWereFound_ButAuthMiddlewareNotInvoked()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "Endpoint Test contains authorization metadata, but a middleware was not found that supports authorization." +
|
||||||
|
Environment.NewLine +
|
||||||
|
"Configure your application startup by adding app.UseAuthorization() inside the call to Configure(..) in the application startup code.";
|
||||||
|
var httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
RequestServices = new ServiceProvider()
|
||||||
|
};
|
||||||
|
|
||||||
|
httpContext.Features.Set<IEndpointFeature>(new EndpointSelectorContext()
|
||||||
|
{
|
||||||
|
Endpoint = new Endpoint(_ => Task.CompletedTask, new EndpointMetadataCollection(Mock.Of<IAuthorizeData>()), "Test"),
|
||||||
|
});
|
||||||
|
|
||||||
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, _ => Task.CompletedTask, RouteOptions);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => middleware.Invoke(httpContext));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_WithEndpoint_WorksIfAuthAttributesWereFound_AndAuthMiddlewareInvoked()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
RequestServices = new ServiceProvider()
|
||||||
|
};
|
||||||
|
|
||||||
|
httpContext.Features.Set<IEndpointFeature>(new EndpointSelectorContext()
|
||||||
|
{
|
||||||
|
Endpoint = new Endpoint(_ => Task.CompletedTask, new EndpointMetadataCollection(Mock.Of<IAuthorizeData>()), "Test"),
|
||||||
|
});
|
||||||
|
|
||||||
|
httpContext.Items[EndpointMiddleware.AuthorizationMiddlewareInvokedKey] = true;
|
||||||
|
|
||||||
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, _ => Task.CompletedTask, RouteOptions);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
await middleware.Invoke(httpContext);
|
||||||
|
|
||||||
|
// If we got this far, we can sound the everything's OK alarm.
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_WithEndpoint_DoesNotThrowIfUnhandledAuthAttributesWereFound_ButSuppressedViaOptions()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
RequestServices = new ServiceProvider()
|
||||||
|
};
|
||||||
|
|
||||||
|
httpContext.Features.Set<IEndpointFeature>(new EndpointSelectorContext()
|
||||||
|
{
|
||||||
|
Endpoint = new Endpoint(_ => Task.CompletedTask, new EndpointMetadataCollection(Mock.Of<IAuthorizeData>()), "Test"),
|
||||||
|
});
|
||||||
|
var routeOptions = Options.Create(new RouteOptions { SuppressCheckForUnhandledSecurityMetadata = true });
|
||||||
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, _ => Task.CompletedTask, routeOptions);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
await middleware.Invoke(httpContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_WithEndpoint_ThrowsIfCorsMetadataWasFound_ButCorsMiddlewareNotInvoked()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "Endpoint Test contains CORS metadata, but a middleware was not found that supports CORS." +
|
||||||
|
Environment.NewLine +
|
||||||
|
"Configure your application startup by adding app.UseCors() inside the call to Configure(..) in the application startup code.";
|
||||||
|
var httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
RequestServices = new ServiceProvider()
|
||||||
|
};
|
||||||
|
|
||||||
|
httpContext.Features.Set<IEndpointFeature>(new EndpointSelectorContext()
|
||||||
|
{
|
||||||
|
Endpoint = new Endpoint(_ => Task.CompletedTask, new EndpointMetadataCollection(Mock.Of<ICorsMetadata>()), "Test"),
|
||||||
|
});
|
||||||
|
|
||||||
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, _ => Task.CompletedTask, RouteOptions);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => middleware.Invoke(httpContext));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_WithEndpoint_WorksIfCorsMetadataWasFound_AndCorsMiddlewareInvoked()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
RequestServices = new ServiceProvider()
|
||||||
|
};
|
||||||
|
|
||||||
|
httpContext.Features.Set<IEndpointFeature>(new EndpointSelectorContext()
|
||||||
|
{
|
||||||
|
Endpoint = new Endpoint(_ => Task.CompletedTask, new EndpointMetadataCollection(Mock.Of<ICorsMetadata>()), "Test"),
|
||||||
|
});
|
||||||
|
|
||||||
|
httpContext.Items[EndpointMiddleware.CorsMiddlewareInvokedKey] = true;
|
||||||
|
|
||||||
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, _ => Task.CompletedTask, RouteOptions);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
await middleware.Invoke(httpContext);
|
||||||
|
|
||||||
|
// If we got this far, we can sound the everything's OK alarm.
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_WithEndpoint_DoesNotThrowIfUnhandledCorsAttributesWereFound_ButSuppressedViaOptions()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var httpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
RequestServices = new ServiceProvider()
|
||||||
|
};
|
||||||
|
|
||||||
|
httpContext.Features.Set<IEndpointFeature>(new EndpointSelectorContext()
|
||||||
|
{
|
||||||
|
Endpoint = new Endpoint(_ => Task.CompletedTask, new EndpointMetadataCollection(Mock.Of<IAuthorizeData>()), "Test"),
|
||||||
|
});
|
||||||
|
var routeOptions = Options.Create(new RouteOptions { SuppressCheckForUnhandledSecurityMetadata = true });
|
||||||
|
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, _ => Task.CompletedTask, routeOptions);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
await middleware.Invoke(httpContext);
|
||||||
|
}
|
||||||
|
|
||||||
private class ServiceProvider : IServiceProvider
|
private class ServiceProvider : IServiceProvider
|
||||||
{
|
{
|
||||||
public object GetService(Type serviceType)
|
public object GetService(Type serviceType)
|
||||||
|
|
|
||||||
|
|
@ -129,9 +129,6 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
public DefaultCorsPolicyProvider(Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Cors.Infrastructure.CorsOptions> options) { }
|
public DefaultCorsPolicyProvider(Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Cors.Infrastructure.CorsOptions> options) { }
|
||||||
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy> GetPolicyAsync(Microsoft.AspNetCore.Http.HttpContext context, string policyName) { throw null; }
|
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy> GetPolicyAsync(Microsoft.AspNetCore.Http.HttpContext context, string policyName) { throw null; }
|
||||||
}
|
}
|
||||||
public partial interface ICorsMetadata
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public partial interface ICorsPolicyMetadata : Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata
|
public partial interface ICorsPolicyMetadata : Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata
|
||||||
{
|
{
|
||||||
Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy Policy { get; }
|
Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy Policy { get; }
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cors.Test,PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cors.Test,PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
||||||
<Compile Include="Microsoft.AspNetCore.Authorization.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.AspNetCore.Authorization.netcoreapp3.0.cs" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Options" />
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -137,9 +137,6 @@ namespace Microsoft.AspNetCore.Authorization
|
||||||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||||
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Authorization.AuthorizationResult> AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, string policyName) { throw null; }
|
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Authorization.AuthorizationResult> AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, string policyName) { throw null; }
|
||||||
}
|
}
|
||||||
public partial interface IAllowAnonymous
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public partial interface IAuthorizationEvaluator
|
public partial interface IAuthorizationEvaluator
|
||||||
{
|
{
|
||||||
Microsoft.AspNetCore.Authorization.AuthorizationResult Evaluate(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context);
|
Microsoft.AspNetCore.Authorization.AuthorizationResult Evaluate(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context);
|
||||||
|
|
@ -170,12 +167,6 @@ namespace Microsoft.AspNetCore.Authorization
|
||||||
System.Threading.Tasks.Task<Microsoft.AspNetCore.Authorization.AuthorizationResult> AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Authorization.IAuthorizationRequirement> requirements);
|
System.Threading.Tasks.Task<Microsoft.AspNetCore.Authorization.AuthorizationResult> AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Authorization.IAuthorizationRequirement> requirements);
|
||||||
System.Threading.Tasks.Task<Microsoft.AspNetCore.Authorization.AuthorizationResult> AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, string policyName);
|
System.Threading.Tasks.Task<Microsoft.AspNetCore.Authorization.AuthorizationResult> AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, string policyName);
|
||||||
}
|
}
|
||||||
public partial interface IAuthorizeData
|
|
||||||
{
|
|
||||||
string AuthenticationSchemes { get; set; }
|
|
||||||
string Policy { get; set; }
|
|
||||||
string Roles { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
namespace Microsoft.AspNetCore.Authorization.Infrastructure
|
namespace Microsoft.AspNetCore.Authorization.Infrastructure
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>ASP.NET Core authorization classes.
|
<Description>ASP.NET Core authorization classes.
|
||||||
|
|
@ -14,6 +14,7 @@ Microsoft.AspNetCore.Authorization.AuthorizeAttribute</Description>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Options" />
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
[assembly: TypeForwardedTo(typeof(IAuthorizeData))]
|
||||||
|
[assembly: TypeForwardedTo(typeof(IAllowAnonymous))]
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
<Reference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Cors" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Diagnostics" />
|
<Reference Include="Microsoft.AspNetCore.Diagnostics" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Connections;
|
using Microsoft.AspNetCore.Http.Connections;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
@ -47,6 +49,8 @@ namespace FunctionalTests
|
||||||
})
|
})
|
||||||
.AddMessagePackProtocol();
|
.AddMessagePackProtocol();
|
||||||
|
|
||||||
|
services.AddCors();
|
||||||
|
|
||||||
services.AddAuthorization(options =>
|
services.AddAuthorization(options =>
|
||||||
{
|
{
|
||||||
options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
|
options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
|
||||||
|
|
@ -73,17 +77,33 @@ namespace FunctionalTests
|
||||||
{
|
{
|
||||||
OnMessageReceived = context =>
|
OnMessageReceived = context =>
|
||||||
{
|
{
|
||||||
var signalRTokenHeader = context.Request.Query["access_token"];
|
var endpoint = context.HttpContext.Features.Get<IEndpointFeature>()?.Endpoint;
|
||||||
|
if (endpoint != null && endpoint.Metadata.GetMetadata<HubMetadata>() != null)
|
||||||
if (!string.IsNullOrEmpty(signalRTokenHeader) &&
|
|
||||||
(context.HttpContext.WebSockets.IsWebSocketRequest || context.Request.Headers["Accept"] == "text/event-stream"))
|
|
||||||
{
|
{
|
||||||
context.Token = context.Request.Query["access_token"];
|
var request = context.HttpContext.Request;
|
||||||
|
string token = request.Headers["Authorization"];
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
if (token.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
token = token.Substring("Bearer ".Length).Trim();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
token = context.Request.Query["access_token"];
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Token = token;
|
||||||
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddAuthorizationPolicyEvaluator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
|
@ -127,8 +147,6 @@ namespace FunctionalTests
|
||||||
return next.Invoke();
|
return next.Invoke();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
app.Use((context, next) =>
|
app.Use((context, next) =>
|
||||||
{
|
{
|
||||||
if (context.Request.Path.StartsWithSegments("/redirect"))
|
if (context.Request.Path.StartsWithSegments("/redirect"))
|
||||||
|
|
@ -148,9 +166,24 @@ namespace FunctionalTests
|
||||||
context.Response.Cookies.Append("testCookie2", "testValue2");
|
context.Response.Cookies.Append("testCookie2", "testValue2");
|
||||||
context.Response.Cookies.Append("expiredCookie", "doesntmatter", new CookieOptions() { Expires = DateTimeOffset.Now.AddHours(-1) });
|
context.Response.Cookies.Append("expiredCookie", "doesntmatter", new CookieOptions() { Expires = DateTimeOffset.Now.AddHours(-1) });
|
||||||
}
|
}
|
||||||
|
|
||||||
await next.Invoke();
|
await next.Invoke();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
// Custom CORS to allow any origin + credentials (which isn't allowed by the CORS spec)
|
||||||
|
// This is for testing purposes only (karma hosts the client on its own server), never do this in production
|
||||||
|
app.UseCors(policy =>
|
||||||
|
{
|
||||||
|
policy.SetIsOriginAllowed(host => host.StartsWith("http://localhost:") || host.StartsWith("http://127.0.0.1:"))
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowCredentials();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapHub<TestHub>("/testhub");
|
endpoints.MapHub<TestHub>("/testhub");
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Security.Claims;
|
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.SignalR.Tests
|
namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
|
|
@ -25,11 +22,16 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||||
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||||
}).AddCookie();
|
}).AddCookie();
|
||||||
|
|
||||||
|
services.AddAuthorizationPolicyEvaluator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app)
|
public void Configure(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapHub<UncreatableHub>("/uncreatable");
|
endpoints.MapHub<UncreatableHub>("/uncreatable");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue