Skip to content

Commit 5bfab13

Browse files
ShazwazzaPaul Johnsonbergmania
authored
Fixes #11189 - protected content not working (#11193)
* Fixes #11189 * Fixes #11183 * Fix test Null_When_No_Content_On_PublishedRequest. Believe this is reasonable. * Update src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs Co-authored-by: Paul Johnson <[email protected]> Co-authored-by: Bjarke Berg <[email protected]>
1 parent cf52b46 commit 5bfab13

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public async Task Assigns_PublishedRequest_To_UmbracoContext()
163163
public async Task Null_When_No_Content_On_PublishedRequest()
164164
{
165165
IUmbracoContext umbracoContext = GetUmbracoContext(true);
166-
IPublishedRequest request = Mock.Of<IPublishedRequest>();
166+
IPublishedRequest request = Mock.Of<IPublishedRequest>(x => x.PublishedContent == null);
167167

168168
UmbracoRouteValueTransformer transformer = GetTransformerWithRunState(
169169
Mock.Of<IUmbracoContextAccessor>(x => x.TryGetUmbracoContext(out umbracoContext)),
@@ -172,9 +172,10 @@ public async Task Null_When_No_Content_On_PublishedRequest()
172172

173173
var httpContext = new DefaultHttpContext();
174174
RouteValueDictionary result = await transformer.TransformAsync(httpContext, new RouteValueDictionary());
175+
Assert.IsNull(result);
175176

176177
UmbracoRouteValues routeVals = httpContext.Features.Get<UmbracoRouteValues>();
177-
Assert.IsNull(routeVals);
178+
Assert.AreEqual(routeVals.PublishedRequest.GetRouteResult(), UmbracoRouteResult.NotFound);
178179
}
179180

180181
[Test]

src/Umbraco.Web.Common/Security/ConfigureMemberCookieOptions.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
using System.Threading.Tasks;
12
using Microsoft.AspNetCore.Authentication.Cookies;
23
using Microsoft.AspNetCore.Identity;
34
using Microsoft.Extensions.Options;
45
using Umbraco.Cms.Core.Routing;
56
using Umbraco.Cms.Core.Services;
7+
using Umbraco.Extensions;
68

79
namespace Umbraco.Cms.Web.Common.Security
810
{
@@ -34,6 +36,19 @@ public void Configure(CookieAuthenticationOptions options)
3436
options.LogoutPath = null;
3537

3638
options.CookieManager = new MemberCookieManager(_runtimeState, _umbracoRequestPaths);
39+
40+
options.Events = new CookieAuthenticationEvents
41+
{
42+
OnSignedIn = ctx =>
43+
{
44+
// occurs when sign in is successful and after the ticket is written to the outbound cookie
45+
46+
// When we are signed in with the cookie, assign the principal to the current HttpContext
47+
ctx.HttpContext.SetPrincipalForRequest(ctx.Principal);
48+
49+
return Task.CompletedTask;
50+
}
51+
};
3752
}
3853
}
3954
}

src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Threading.Tasks;
3+
using Microsoft.AspNetCore.Authentication;
34
using Microsoft.AspNetCore.Http;
5+
using Microsoft.AspNetCore.Identity;
46
using Microsoft.Extensions.Logging;
57
using Umbraco.Cms.Core;
68
using Umbraco.Cms.Core.Models;
@@ -65,6 +67,19 @@ public async Task<UmbracoRouteValues> RewriteForPublishedContentAccessAsync(Http
6567
{
6668
_logger.LogDebug("EnsurePublishedContentAccess: Page is protected, check for access");
6769

70+
// manually authenticate the request
71+
AuthenticateResult authResult = await httpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
72+
if (authResult.Succeeded)
73+
{
74+
// set the user to the auth result. we need to do this here because this occurs
75+
// before the authentication middleware.
76+
// NOTE: It would be possible to just pass the authResult to the HasMemberAccessToContentAsync method
77+
// instead of relying directly on the user assigned to the http context, and then the auth middleware
78+
// will run anyways and assign the user. Perhaps that is a little cleaner, but would require more code
79+
// changes right now, and really it's not any different in the end result.
80+
httpContext.SetPrincipalForRequest(authResult.Principal);
81+
}
82+
6883
publicAccessStatus = await _publicAccessChecker.HasMemberAccessToContentAsync(publishedContent.Id);
6984
switch (publicAccessStatus)
7085
{

src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,7 @@ public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext
130130

131131
IPublishedRequest publishedRequest = await RouteRequestAsync(umbracoContext);
132132

133-
umbracoRouteValues = await _routeValuesFactory.CreateAsync(httpContext, publishedRequest);
134-
135-
if (!umbracoRouteValues?.PublishedRequest?.HasPublishedContent() ?? false)
136-
{
137-
// No content was found, not by any registered 404 handlers and
138-
// not by the IContentLastChanceFinder. In this case we want to return
139-
// our default 404 page but we cannot return route values now because
140-
// it's possible that a developer is handling dynamic routes too.
141-
// Our 404 page will be handled with the NotFoundSelectorPolicy
142-
return null;
143-
}
133+
umbracoRouteValues = await _routeValuesFactory.CreateAsync(httpContext, publishedRequest);
144134

145135
// now we need to do some public access checks
146136
umbracoRouteValues = await _publicAccessRequestHandler.RewriteForPublishedContentAccessAsync(httpContext, umbracoRouteValues);
@@ -155,6 +145,18 @@ public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext
155145
return HandlePostedValues(postedInfo, httpContext);
156146
}
157147

148+
UmbracoRouteResult? routeResult = umbracoRouteValues?.PublishedRequest?.GetRouteResult();
149+
150+
if (!routeResult.HasValue || routeResult == UmbracoRouteResult.NotFound)
151+
{
152+
// No content was found, not by any registered 404 handlers and
153+
// not by the IContentLastChanceFinder. In this case we want to return
154+
// our default 404 page but we cannot return route values now because
155+
// it's possible that a developer is handling dynamic routes too.
156+
// Our 404 page will be handled with the NotFoundSelectorPolicy
157+
return null;
158+
}
159+
158160
// See https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.routing.dynamicroutevaluetransformer.transformasync?view=aspnetcore-5.0#Microsoft_AspNetCore_Mvc_Routing_DynamicRouteValueTransformer_TransformAsync_Microsoft_AspNetCore_Http_HttpContext_Microsoft_AspNetCore_Routing_RouteValueDictionary_
159161
// We should apparenlty not be modified these values.
160162
// So we create new ones.

0 commit comments

Comments
 (0)