Make Http Endpoint activity security opt-in

This commit is contained in:
Sipke Schoorstra 2021-10-04 15:52:56 +02:00
parent 7106225c04
commit d06199f9ee
5 changed files with 23 additions and 6 deletions

View file

@ -51,6 +51,7 @@ namespace Microsoft.Extensions.DependencyInjection
.AddSingleton<IHttpResponseContentReader, FileHttpResponseContentReader>()
.AddSingleton<IActionContextAccessor, ActionContextAccessor>()
.AddSingleton<IAbsoluteUrlProvider, DefaultAbsoluteUrlProvider>()
.AddSingleton<AllowAnonymousHttpEndpointAuthorizationHandler>()
.AddSingleton(sp => sp.GetRequiredService<IOptions<HttpActivityOptions>>().Value.HttpEndpointAuthorizationHandlerFactory(sp))
.AddBookmarkProvider<HttpEndpointBookmarkProvider>()
.AddHttpContextAccessor()

View file

@ -16,6 +16,7 @@ using Elsa.Services;
using Elsa.Services.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Open.Linq.AsyncExtensions;
@ -37,7 +38,6 @@ namespace Elsa.Activities.Http.Middleware
IWorkflowInstanceStore workflowInstanceStore,
IWorkflowRegistry workflowRegistry,
IWorkflowBlueprintReflector workflowBlueprintReflector,
IHttpEndpointAuthorizationHandler authorizationHandler,
IEnumerable<IHttpRequestBodyParser> contentParsers)
{
var basePath = options.Value.BasePath;
@ -92,7 +92,7 @@ namespace Elsa.Activities.Http.Middleware
var contentParser = orderedContentParsers.FirstOrDefault(x => x.SupportedContentTypes.Contains(simpleContentType, StringComparer.OrdinalIgnoreCase)) ?? orderedContentParsers.LastOrDefault() ?? new DefaultHttpRequestBodyParser();
var activityWrapper = workflowBlueprintWrapper.GetUnfilteredActivity<HttpEndpoint>(pendingWorkflow.ActivityId!)!;
if (!await AuthorizeAsync(httpContext, activityWrapper, workflowBlueprint, pendingWorkflow, authorizationHandler, cancellationToken))
if (!await AuthorizeAsync(httpContext, options.Value, activityWrapper, workflowBlueprint, pendingWorkflow, cancellationToken))
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
return;
@ -157,10 +157,10 @@ namespace Elsa.Activities.Http.Middleware
private async Task<bool> AuthorizeAsync(
HttpContext httpContext,
HttpActivityOptions options,
IActivityBlueprintWrapper<HttpEndpoint> httpEndpoint,
IWorkflowBlueprint workflowBlueprint,
CollectedWorkflow pendingWorkflow,
IHttpEndpointAuthorizationHandler authorizationHandler,
CancellationToken cancellationToken)
{
var authorize = await httpEndpoint.EvaluatePropertyValueAsync(x => x.Authorize, cancellationToken);
@ -168,6 +168,8 @@ namespace Elsa.Activities.Http.Middleware
if (!authorize)
return true;
var authorizationHandler = options.HttpEndpointAuthorizationHandlerFactory(httpContext.RequestServices);
return await authorizationHandler.AuthorizeAsync(new AuthorizeHttpEndpointContext(httpContext, httpEndpoint, workflowBlueprint, pendingWorkflow.WorkflowInstanceId, cancellationToken));
}

View file

@ -17,6 +17,6 @@ namespace Elsa.Activities.Http.Options
/// </summary>
public PathString? BasePath { get; set; }
public Func<IServiceProvider, IHttpEndpointAuthorizationHandler> HttpEndpointAuthorizationHandlerFactory { get; set; } = ActivatorUtilities.GetServiceOrCreateInstance<AuthenticationBasedHttpEndpointAuthorizationHandler>;
public Func<IServiceProvider, IHttpEndpointAuthorizationHandler> HttpEndpointAuthorizationHandlerFactory { get; set; } = ActivatorUtilities.GetServiceOrCreateInstance<AllowAnonymousHttpEndpointAuthorizationHandler>;
}
}

View file

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Elsa.Activities.Http.Models;
namespace Elsa.Activities.Http.Services
{
public class AllowAnonymousHttpEndpointAuthorizationHandler : IHttpEndpointAuthorizationHandler
{
public ValueTask<bool> AuthorizeAsync(AuthorizeHttpEndpointContext context) => new(true);
}
}

View file

@ -13,8 +13,12 @@ namespace Elsa.Activities.Http.Services
{
var httpContext = context.HttpContext;
var user = httpContext.User;
var identity = user.Identity;
if (!user.Identity.IsAuthenticated)
if (identity == null)
return false;
if (identity.IsAuthenticated == false)
return false;
var cancellationToken = context.CancellationToken;
@ -22,7 +26,7 @@ namespace Elsa.Activities.Http.Services
var policyName = await httpEndpoint.EvaluatePropertyValueAsync(x => x.Policy, cancellationToken);
if (string.IsNullOrWhiteSpace(policyName))
return user.Identity.IsAuthenticated;
return identity.IsAuthenticated;
var resource = new HttpWorkflowResource(context.WorkflowBlueprint, httpEndpoint.ActivityBlueprint, context.WorkflowInstanceId);
var authorizationResult = await _authorizationService.AuthorizeAsync(user, resource, policyName);