Adam
Adam

Reputation: 4780

Connect Elsa v3 to Azure AD

How do you setup Azure AD authentication with Elsa v3?

In Elsa v2, we did something like this and just wrapped Elsa in a login flow:

services.AddRazorPages(options =>
{
    options.Conventions.AuthorizeFolder("/");
    options.Conventions.AllowAnonymousToFolder("/endpoints");
}).AddMicrosoftIdentityUI();

For v3 I added this to the startup:

elsa.UseIdentity(identity =>
{
    identity.TokenOptions = options => options.SigningKey = "sufficiently-large-secret-signing-key";
    identity.UseAzureIdentityProvider(); // my custom extension below
});

This is what I have so far for the UseAzureIdentityProvider() extension method but not sure how to connect the Microsoft Identity IUserStore<T> and IRoleStore<T> to Elsa's IUserStore and IRoleStore respectively. The interfaces look straightforward enough to connect them together but getting the actual user store and identity store from Azure properly registered for injection into this custom class I created is where I am a bit lost:

public static class ElsaAzureActiveDirectoryIdentityAdapterServiceCollectionExtensions
{
    public static void UseAzureIdentityProvider(this IdentityFeature identity)
    {
        identity.Services.AddIdentityCore<User>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddUserStore<User>()
            .AddRoleStore<Role>();

        identity.Services.AddSingleton<ElsaAzureActiveDirectoryIdentityAdapter>();
        identity.Services.AddSingleton<IRoleStore>(provider => provider.GetService<ElsaAzureActiveDirectoryIdentityAdapter>()!);
        identity.Services.AddSingleton<IUserStore>(provider => provider.GetService<ElsaAzureActiveDirectoryIdentityAdapter>()!);

        identity.UserStore = provider => provider.GetService<IUserStore>()!;
        identity.RoleStore = provider => provider.GetService<IRoleStore>()!;
    }
}

/// <summary>
/// Connects Elsa to Azure AD for identity authentication.
/// </summary>
/// <param name="identityRoleStore">The Microsoft Identity role store.</param>
/// <param name="identityUserStore">The Microsoft Identity user store.</param>
public class ElsaAzureActiveDirectoryIdentityAdapter(IRoleStore<Role> identityRoleStore, IUserStore<User> identityUserStore)
    : IRoleStore, IUserStore
{
    #region Role Store Methods

    public Task AddAsync(Role role, CancellationToken cancellationToken = new()) => throw new NotImplementedException();

    public Task DeleteAsync(RoleFilter filter, CancellationToken cancellationToken = new()) => throw new NotImplementedException();

    public Task SaveAsync(Role role, CancellationToken cancellationToken = new()) => throw new NotImplementedException();

    public Task<Role?> FindAsync(RoleFilter filter, CancellationToken cancellationToken = new())
        => filter.Id != null ? identityRoleStore.FindByIdAsync(filter.Id, cancellationToken) : null;

    public Task<IEnumerable<Role>> FindManyAsync(RoleFilter filter, CancellationToken cancellationToken = new()) => throw new NotImplementedException();

    #endregion


    #region User Store Methods

    public Task SaveAsync(User user, CancellationToken cancellationToken = new()) => throw new NotImplementedException();

    public Task DeleteAsync(UserFilter filter, CancellationToken cancellationToken = new()) => throw new NotImplementedException();

    public async Task<User?> FindAsync(UserFilter filter, CancellationToken cancellationToken = new())
    {
        if (filter.Id != null)
        {
            User? user = await identityUserStore.FindByIdAsync(filter.Id!, cancellationToken);
            if (user != null)
            {
                return user;
            }
        }

        if (filter.Name != null)
        {
            User? user = await identityUserStore.FindByNameAsync(filter.Name!, cancellationToken);
            if (user != null)
            {
                return user;
            }
        }

        return null;
    }

    #endregion
}

That does not currently work however:

Error Message

Does this approach seem correct? Should I be doing something different to register Azure AD with Elsa Studio v3? I am setting up the Blazor WASM client if that matters for the answer/approach.

Upvotes: 2

Views: 436

Answers (0)

Related Questions