Skip to content

Commit 64a2ecb

Browse files
committed
No-op Authorization middleware for Razor Pages
Workaround for #7011
1 parent 21f80b2 commit 64a2ecb

File tree

7 files changed

+103
-4
lines changed

7 files changed

+103
-4
lines changed

src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageRouteMetadata.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Microsoft.AspNetCore.Mvc.ApplicationModels
55
{
66
// This is used to store the uncombined parts of the final page route
7+
// Note: This type name is referenced by name in AuthorizationMiddleware, do not change this without addressing https://github.com/aspnet/AspNetCore/issues/7011
78
internal class PageRouteMetadata
89
{
910
public PageRouteMetadata(string pageRoute, string routeTemplate)

src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,11 +1190,11 @@ public async Task PagesCanByRoutedToApplicationRoot_ViaAddPageRoute()
11901190
public async Task AuthFiltersAppliedToPageModel_AreExecuted()
11911191
{
11921192
// Act
1193-
var response = await Client.GetAsync("/ModelWithAuthFilter");
1193+
var response = await Client.GetAsync("/Pages/ModelWithAuthFilter");
11941194

11951195
// Assert
11961196
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
1197-
Assert.Equal("/Login?ReturnUrl=%2FModelWithAuthFilter", response.Headers.Location.PathAndQuery);
1197+
Assert.Equal("/Login?ReturnUrl=%2FPages%2FModelWithAuthFilter", response.Headers.Location.PathAndQuery);
11981198
}
11991199

12001200
[Fact]
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Net;
5+
using System.Net.Http;
6+
using System.Threading.Tasks;
7+
using Xunit;
8+
9+
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
10+
{
11+
public class RazorPagesWithEndpointRoutingTest : IClassFixture<MvcTestFixture<RazorPagesWebSite.StartupWithEndpointRouting>>
12+
{
13+
public RazorPagesWithEndpointRoutingTest(MvcTestFixture<RazorPagesWebSite.StartupWithEndpointRouting> fixture)
14+
{
15+
Client = fixture.CreateDefaultClient();
16+
}
17+
18+
public HttpClient Client { get; }
19+
20+
[Fact]
21+
public async Task Authorize_AppliedUsingConvention_Works()
22+
{
23+
// Act
24+
var response = await Client.GetAsync("/Conventions/AuthFolder");
25+
26+
// Assert
27+
await response.AssertStatusCodeAsync(HttpStatusCode.Redirect);
28+
Assert.Equal("/Login?ReturnUrl=%2FConventions%2FAuthFolder", response.Headers.Location.PathAndQuery);
29+
}
30+
31+
[Fact]
32+
public async Task Authorize_AppliedUsingConvention_CanByOverridenByAllowAnonymousAppliedToModel()
33+
{
34+
// Act
35+
var response = await Client.GetAsync("/Conventions/AuthFolder/AnonymousViaModel");
36+
37+
// Assert
38+
await response.AssertStatusCodeAsync(HttpStatusCode.OK);
39+
40+
var content = await response.Content.ReadAsStringAsync();
41+
Assert.Equal("Hello from Anonymous", content.Trim());
42+
}
43+
44+
[Fact]
45+
public async Task Authorize_AppliedUsingAttributeOnModel_Works()
46+
{
47+
// Act
48+
var response = await Client.GetAsync("/ModelWithAuthFilter");
49+
50+
// Assert
51+
await response.AssertStatusCodeAsync(HttpStatusCode.Redirect);
52+
Assert.Equal("/Login?ReturnUrl=%2FModelWithAuthFilter", response.Headers.Location.PathAndQuery);
53+
}
54+
}
55+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNetCore.Authentication.Cookies;
5+
using Microsoft.AspNetCore.Builder;
6+
using Microsoft.AspNetCore.Mvc;
7+
using Microsoft.Extensions.DependencyInjection;
8+
9+
namespace RazorPagesWebSite
10+
{
11+
public class StartupWithEndpointRouting
12+
{
13+
public void ConfigureServices(IServiceCollection services)
14+
{
15+
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
16+
.AddCookie(options => options.LoginPath = "/Login");
17+
18+
services.AddMvc()
19+
.AddRazorPagesOptions(options =>
20+
{
21+
options.Conventions.AuthorizeFolder("/Admin");
22+
})
23+
.SetCompatibilityVersion(CompatibilityVersion.Latest);
24+
}
25+
26+
public void Configure(IApplicationBuilder app)
27+
{
28+
app.UseRouting(routes =>
29+
{
30+
routes.MapApplication();
31+
});
32+
33+
app.UseAuthorization();
34+
}
35+
}
36+
}

src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Microsoft.AspNetCore.Authorization.Policy;
99
using Microsoft.AspNetCore.Http;
1010
using Microsoft.AspNetCore.Http.Endpoints;
11-
using Microsoft.AspNetCore.Http.Features;
1211
using Microsoft.Extensions.DependencyInjection;
1312

1413
namespace Microsoft.AspNetCore.Authorization
@@ -45,11 +44,19 @@ public async Task Invoke(HttpContext context)
4544
throw new ArgumentNullException(nameof(context));
4645
}
4746

47+
var endpoint = context.GetEndpoint();
48+
49+
// Workaround for https://github.com/aspnet/AspNetCore/issues/7011. Do not use the AuthorizationMiddleware for Razor Pages
50+
if (endpoint.Metadata.Any(m => m.GetType().FullName == "Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteMetadata"))
51+
{
52+
await _next(context);
53+
return;
54+
}
55+
4856
// Flag to indicate to other systems, e.g. MVC, that authorization middleware was run for this request
4957
context.Items[AuthorizationMiddlewareInvokedKey] = AuthorizationMiddlewareInvokedValue;
5058

5159
// IMPORTANT: Changes to authorization logic should be mirrored in MVC's AuthorizeFilter
52-
var endpoint = context.GetEndpoint();
5360
var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();
5461
var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
5562
if (policy == null)

0 commit comments

Comments
 (0)