Add member auth to the Delivery API (#14730)
* Refactor OpenIddict for shared usage between APIs + implement member authentication and handling within the Delivery API * Make SwaggerRouteTemplatePipelineFilter UI config overridable * Enable token revocation + rename logout endpoint to signout * Add default implementation of SwaggerGenOptions configuration for enabling Delivery API member auth in Swagger * Correct notification handling when (un)protecting content * Fixing integration test framework * Cleanup test to not execute some composers twice * Update paths to match docs * Return Forbidden when a member is authorized but not allowed to access the requested resource * Cleanup * Rename RequestMemberService to RequestMemberAccessService * Rename badly named variable * Review comments * Hide the auth controller from Swagger * Remove semaphore * Add security requirements for content API operations in Swagger * Hide the back-office auth endpoints from Swagger * Fix merge * Update back-office API auth endpoint paths + add revoke and sign-out endpoints (as of now they do not exist, a separate task will fix that) * Swap endpoint order to maintain backwards compat with the current login screen for new back-office (will be swapped back again to ensure correct .well-known endpoints, see FIXME comment) * Make "items by IDs" endpoint support member auth * Add 401 and 403 to "items by IDs" endpoint responses --------- Co-authored-by: Bjarke Berg <mail@bergmania.dk> Co-authored-by: Elitsa <elm@umbraco.dk>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
@@ -13,7 +14,7 @@ public interface IMemberSignInManager
|
||||
|
||||
Task SignOutAsync();
|
||||
|
||||
AuthenticationProperties ConfigureExternalAuthenticationProperties(string provider, string redirectUrl, string? userId = null);
|
||||
AuthenticationProperties ConfigureExternalAuthenticationProperties(string? provider, string? redirectUrl, string? userId = null);
|
||||
|
||||
Task<ExternalLoginInfo?> GetExternalLoginInfoAsync(string? expectedXsrf = null);
|
||||
|
||||
@@ -24,4 +25,6 @@ public interface IMemberSignInManager
|
||||
Task<MemberIdentityUser?> GetTwoFactorAuthenticationUserAsync();
|
||||
|
||||
Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient);
|
||||
|
||||
Task<ClaimsPrincipal> CreateUserPrincipalAsync(MemberIdentityUser user) => Task.FromResult(new ClaimsPrincipal());
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
@@ -19,16 +20,25 @@ public class PublicAccessChecker : IPublicAccessChecker
|
||||
_contentService = contentService;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<PublicAccessStatus> HasMemberAccessToContentAsync(int publishedContentId)
|
||||
=> await HasMemberAccessToContentAsync(publishedContentId, httpContext => httpContext.User);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<PublicAccessStatus> HasMemberAccessToContentAsync(int publishedContentId, ClaimsPrincipal claimsPrincipal)
|
||||
=> await HasMemberAccessToContentAsync(publishedContentId, _ => claimsPrincipal);
|
||||
|
||||
private async Task<PublicAccessStatus> HasMemberAccessToContentAsync(int publishedContentId, Func<HttpContext, ClaimsPrincipal> getClaimsPrincipal)
|
||||
{
|
||||
HttpContext httpContext = _httpContextAccessor.GetRequiredHttpContext();
|
||||
IMemberManager memberManager = httpContext.RequestServices.GetRequiredService<IMemberManager>();
|
||||
if (httpContext.User.Identity == null || !httpContext.User.Identity.IsAuthenticated)
|
||||
ClaimsPrincipal claimsPrincipal = getClaimsPrincipal(httpContext);
|
||||
if (claimsPrincipal.Identity is not { IsAuthenticated: true })
|
||||
{
|
||||
return PublicAccessStatus.NotLoggedIn;
|
||||
}
|
||||
|
||||
MemberIdentityUser? currentMember = await memberManager.GetUserAsync(httpContext.User);
|
||||
MemberIdentityUser? currentMember = await memberManager.GetUserAsync(claimsPrincipal);
|
||||
if (currentMember == null)
|
||||
{
|
||||
return PublicAccessStatus.NotLoggedIn;
|
||||
|
||||
Reference in New Issue
Block a user