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.
|
||||
// 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
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||
{
|
||||
public partial interface ICorsMetadata
|
||||
{
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Http
|
||||
{
|
||||
public abstract partial class ConnectionInfo
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
namespace Microsoft.AspNetCore.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface to enable the <see cref="AllowAnonymousAttribute"/>.
|
||||
/// Marker interface to allow access to anonymous users.
|
||||
/// </summary>
|
||||
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 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 SuppressCheckForUnhandledSecurityMetadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
}
|
||||
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.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
internal sealed class EndpointMiddleware
|
||||
{
|
||||
internal const string AuthorizationMiddlewareInvokedKey = "__AuthorizationMiddlewareInvoked";
|
||||
internal const string CorsMiddlewareInvokedKey = "__CorsMiddlewareInvoked";
|
||||
|
||||
private readonly ILogger _logger;
|
||||
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)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
if (next == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(next));
|
||||
}
|
||||
|
||||
_logger = logger;
|
||||
_next = next;
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_next = next ?? throw new ArgumentNullException(nameof(next));
|
||||
_routeOptions = routeOptions?.Value ?? throw new ArgumentNullException(nameof(routeOptions));
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
|
|
@ -35,6 +36,24 @@ namespace Microsoft.AspNetCore.Routing
|
|||
var endpoint = httpContext.Features.Get<IEndpointFeature>()?.Endpoint;
|
||||
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);
|
||||
|
||||
try
|
||||
|
|
@ -52,6 +71,22 @@ namespace Microsoft.AspNetCore.Routing
|
|||
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 readonly Action<ILogger, string, Exception> _executingEndpoint = LoggerMessage.Define<string>(
|
||||
|
|
|
|||
|
|
@ -28,6 +28,26 @@ namespace Microsoft.AspNetCore.Routing
|
|||
/// </summary>
|
||||
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();
|
||||
|
||||
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.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
public class EndpointMiddlewareTest
|
||||
{
|
||||
private readonly IOptions<RouteOptions> RouteOptions = Options.Create(new RouteOptions());
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_NoFeature_NoOps()
|
||||
{
|
||||
|
|
@ -24,7 +30,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
|
||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next, RouteOptions);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(httpContext);
|
||||
|
|
@ -49,7 +55,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
|
||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next, RouteOptions);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(httpContext);
|
||||
|
|
@ -81,7 +87,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
|
||||
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next, RouteOptions);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(httpContext);
|
||||
|
|
@ -90,6 +96,146 @@ namespace Microsoft.AspNetCore.Routing
|
|||
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
|
||||
{
|
||||
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 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
|
||||
{
|
||||
Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy Policy { get; }
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cors.Test,PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
||||
<Compile Include="Microsoft.AspNetCore.Authorization.netcoreapp3.0.cs" />
|
||||
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
<Reference Include="Microsoft.Extensions.Options" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -137,9 +137,6 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
[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 partial interface IAllowAnonymous
|
||||
{
|
||||
}
|
||||
public partial interface IAuthorizationEvaluator
|
||||
{
|
||||
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, string policyName);
|
||||
}
|
||||
public partial interface IAuthorizeData
|
||||
{
|
||||
string AuthenticationSchemes { get; set; }
|
||||
string Policy { get; set; }
|
||||
string Roles { get; set; }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Authorization.Infrastructure
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core authorization classes.
|
||||
|
|
@ -14,6 +14,7 @@ Microsoft.AspNetCore.Authorization.AuthorizeAttribute</Description>
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
<Reference Include="Microsoft.Extensions.Options" />
|
||||
</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>
|
||||
<Reference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||
<Reference Include="Microsoft.AspNetCore.Cors" />
|
||||
<Reference Include="Microsoft.AspNetCore.Diagnostics" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
|
@ -47,6 +49,8 @@ namespace FunctionalTests
|
|||
})
|
||||
.AddMessagePackProtocol();
|
||||
|
||||
services.AddCors();
|
||||
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
|
||||
|
|
@ -73,17 +77,33 @@ namespace FunctionalTests
|
|||
{
|
||||
OnMessageReceived = context =>
|
||||
{
|
||||
var signalRTokenHeader = context.Request.Query["access_token"];
|
||||
|
||||
if (!string.IsNullOrEmpty(signalRTokenHeader) &&
|
||||
(context.HttpContext.WebSockets.IsWebSocketRequest || context.Request.Headers["Accept"] == "text/event-stream"))
|
||||
var endpoint = context.HttpContext.Features.Get<IEndpointFeature>()?.Endpoint;
|
||||
if (endpoint != null && endpoint.Metadata.GetMetadata<HubMetadata>() != null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
services.AddAuthorizationPolicyEvaluator();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
|
|
@ -127,8 +147,6 @@ namespace FunctionalTests
|
|||
return next.Invoke();
|
||||
});
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.Use((context, next) =>
|
||||
{
|
||||
if (context.Request.Path.StartsWithSegments("/redirect"))
|
||||
|
|
@ -148,9 +166,24 @@ namespace FunctionalTests
|
|||
context.Response.Cookies.Append("testCookie2", "testValue2");
|
||||
context.Response.Cookies.Append("expiredCookie", "doesntmatter", new CookieOptions() { Expires = DateTimeOffset.Now.AddHours(-1) });
|
||||
}
|
||||
|
||||
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 =>
|
||||
{
|
||||
endpoints.MapHub<TestHub>("/testhub");
|
||||
|
|
|
|||
|
|
@ -1,11 +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.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Tests
|
||||
|
|
@ -25,11 +22,16 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
}).AddCookie();
|
||||
|
||||
services.AddAuthorizationPolicyEvaluator();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseRouting();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapHub<UncreatableHub>("/uncreatable");
|
||||
|
|
|
|||
Loading…
Reference in New Issue