Base solution for your next web application
Open Closed

ELSA Tenant specific workflows #12403


User avatar
0
benjamin.edinger@synaptix.at created

Hi,

I followed this tutorial:
https://aspnetzero.com/blog/integrating-elsa-with-aspnet-zero-angular

ELSA Workflows is now integrated however if I create a new Workflow the TenantId is not being set in the Database and stays null.
I want that Tenants can create their own tenant specific workflows which only run on their tenant.

Best regards


3 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @benjamin.edinger

    Add TenantId to Elsa Workflow Context:
    When starting Elsa workflows, add the TenantId information to the context. This will allow Elsa to store the TenantId along with the workflow data.

    Example Code

    using Abp.Runtime.Session;
    using Elsa.Activities.ControlFlow;
    using Elsa.Activities.Primitives;
    using Elsa.Builders;
    using Elsa.Persistence;
    using Elsa.Services;
    using System.Threading.Tasks;
    
    public class TenantAwareWorkflow : IWorkflow
    {
        private readonly IAbpSession _abpSession;
        private readonly IWorkflowInstanceStore _workflowInstanceStore;
    
        public TenantAwareWorkflow(IAbpSession abpSession, IWorkflowInstanceStore workflowInstanceStore)
        {
            _abpSession = abpSession;
            _workflowInstanceStore = workflowInstanceStore;
        }
    
        public void Build(IWorkflowBuilder builder)
        {
            builder
                .StartWith(setup =>
                {
                    setup.VariableName = "TenantId";
                    setup.ValueExpression = new Elsa.Expressions.LiteralExpression(_abpSession.TenantId.ToString());
                })
                .Then(setup => setup.Text = "Tenant ID: " + "TenantId");
        }
    
        public async Task StartWorkflow(IWorkflowRegistry workflowRegistry, IWorkflowRunner workflowRunner)
        {
            var workflowDefinition = workflowRegistry.FindLatestVersionByNameAsync("TenantAwareWorkflow").Result;
            var workflowInstance = await workflowRunner.RunWorkflowAsync(workflowDefinition.Id, context: new Elsa.Services.WorkflowContext(null, new System.Collections.Generic.Dictionary() {{"TenantId", _abpSession.TenantId}}));
        }
    
    }
    
    services.AddElsa(elsa =>
    {
        elsa.AddWorkflow();
        //... other elsa configurations
    });
    

    We add the tenant information to the workflow context using the key "TenantId". In the RunWorkflowAsync method of the WorkflowInstanceRunner class, we include the tenantId in the context parameter. Within the workflow, this tenantId variable can be accessed and used accordingly.

    Would you try this configuration? In your scenario, this configuration will set the TenantId information.

  • User Avatar
    0
    benjamin.edinger@synaptix.at created

    Hi,

    First of all, thank you for your response.

    However I have some follow up questions regarding integrating ELSA workflows with the ASP.NET Zero API in a multi-tenant environment:

    1. Authenticating Workflow Requests:
      Currently, when creating a workflow, a user provides a JWT token to authenticate the request against the ASP.NET Zero API (see attached screenshot). How can we authenticate requests in scenarios where the workflow runs automatically (e.g., on a monthly schedule) without an active user session?
      Screenshot 2025-03-21 084823.png

    2. Securing Endpoints for Tenant Users:
      I want to configure the security for an endpoint so that only users belonging to the correct tenant can trigger the workflow associated with that tenant (see attached screenshot). What is the best approach to enforce this tenant-based access control?
      Screenshot 2025-03-21 084948.png

    3. Multi-Tenant Workflow Configuration:
      I have set up ELSA to handle workflows per tenant by implementing a custom Tenant Accessor. Here’s the code I’m using:

      using Elsa.Services;
      using System.Threading;
      using System.Threading.Tasks;
      using Abp.Runtime.Session;
      using System;
      
      namespace SYNAPTIX_WORKFORCE.Web.Startup
      {
          public class TenantAccessor : ITenantAccessor
          {
              private readonly IAbpSession _abpSession;
      
              public TenantAccessor(IAbpSession abpSession)
              {
                  _abpSession = abpSession;
              }
      
              public Task<string> GetTenantIdAsync(CancellationToken cancellationToken = default)
              {
                  var tenantId = _abpSession.TenantId?.ToString();
                  return Task.FromResult(tenantId);
              }
          }
      }
      

      And in Startup.cs, I register the Tenant Accessor as follows:

      services.AddElsa(elsa =>
      {
          elsa
            .UseEntityFrameworkPersistence(ef =>
                ef.UseMySql(_appConfiguration.GetConnectionString("Default"))
            )
            .AddConsoleActivities()
            .AddHttpActivities(_appConfiguration.GetSection("Elsa").GetSection("Server").Bind)
            .AddQuartzTemporalActivities()
            .AddJavaScriptActivities()
            .AddWorkflowsFrom<Startup>()
            .AddCustomTenantAccessor<TenantAccessor>();
      
          elsa.UseAutoMapper(() => { });
      });
      

    Could you please advise on how to:

    • Authenticate scheduled workflows without an active user JWT token,

    • Secure the endpoint so only users from the respective tenant can trigger the workflow, and

    • Validate or improve my current multi-tenant workflow configuration?

    Thanks in advance for your help!


  • User Avatar
    0
    benjamin.edinger@synaptix.at created

    any updates on this?