Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 8, 2026

Implements a clean-slate OIDC authentication module decoupled from Elsa.Studio.Login, using Microsoft's native authentication infrastructure for automatic token management. Addresses manual token fetching issues and introduces shared abstractions for future authentication providers (OAuth2, JWT, SAML).

Architecture

Four new projects:

  • Elsa.Studio.Authentication.Abstractions - Shared ITokenAccessor interface and AuthenticationOptions base class enabling consistent patterns across authentication providers
  • Elsa.Studio.Authentication.OpenIdConnect - Core OIDC abstractions (IOidcTokenAccessor, OidcOptions, OidcAuthenticationProvider)
  • Elsa.Studio.Authentication.OpenIdConnect.BlazorServer - Server implementation using Microsoft.AspNetCore.Authentication.OpenIdConnect with cookie-based sessions
  • Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm - WASM implementation using Microsoft.AspNetCore.Components.WebAssembly.Authentication with framework-managed tokens

Key Differences from Legacy

Aspect Legacy New
Token storage Browser localStorage Server: auth properties (server-side)
WASM: framework-managed
Token refresh Manual implementation Automatic via framework
PKCE Manual Built-in
Security Client-exposed Server: no browser exposure
WASM: framework-secured

Usage

Blazor Server:

builder.Services.AddOidcAuthentication(options =>
{
    options.Authority = "https://identity-server.com";
    options.ClientId = "elsa-studio";
    options.Scopes = new[] { "openid", "profile", "elsa_api" };
});
app.UseAuthentication();
app.UseAuthorization();

Blazor WASM:

builder.Services.AddOidcAuthentication(options =>
{
    options.Authority = "https://identity-server.com";
    options.ClientId = "elsa-studio-wasm";
    options.Scopes = new[] { "openid", "profile", "elsa_api" };
});

Compatibility

  • Works with WorkflowInstanceObserverFactory for SignalR authentication via IAuthenticationProviderManager
  • Compatible with existing AuthenticatingApiHttpMessageHandler
  • Does not modify Elsa.Studio.Login - can coexist with legacy implementation
  • Targets net8.0, net9.0, net10.0

Documentation

  • Multi-provider architecture guide in src/modules/AUTHENTICATION_ARCHITECTURE.md
  • Complete usage guide in OIDC module README
  • Examples for implementing new authentication providers in abstractions README
Original prompt

Goal: implement an optional module called Elsa.Studio.Authentication.OpenIdConnect.

Elsa Studio currently supports OIDC, but its implementation might not be optimal for several reasons:

  • It's intermixed / tight coupled with the ore general-purpose Elsa.Studio.Login project.
  • It's fetching access tokens "manually" - we need to understan if this is strictly necessary, or if there's stuff from existing MS packages that makes things more "automatic" for us. When assessing, take into account also WorkflowInstanceObserverFactory

Ideally, leave the existing OIDC code as-is, but start a clean slate implementation from the new (empty) class library project Elsa.Studio.Authentication.OpenIdConnect with best practices and patterns.

We need to support both the Blazor Server and Blazor WASM models, so if necessary, you can crete additional projects targeting these different hosting models.

I have attached files that showcase the current implementation for your reference, but use it as you see fit.
First, make a plan, then execute upon it autonomously. Ask me any questions if you need to.

The user has attached the following files from their workspace:

  • src/modules/Elsa.Studio.Login/Extensions/ServiceCollectionExtensions.cs
  • src/modules/Elsa.Studio.Workflows/Services/WorkflowInstanceObserverFactory.cs
  • src/modules/Elsa.Studio.Login/Elsa.Studio.Login.csproj
  • src/modules/Elsa.Studio.Login/Models/OpenIdConnectConfiguration.cs
  • src/hosts/Elsa.Studio.Host.Server/Program.cs
  • src/modules/Elsa.Studio.Login/Components/ReceiveAuthorizationCode.cs
  • src/modules/Elsa.Studio.Login/Services/OpenIdConnectAuthorizationService.cs
  • src/modules/Elsa.Studio.Login/Services/OpenIdConnectEndSessionService.cs
  • src/modules/Elsa.Studio.Login/Services/OpenIdConnectPkceCodeGenerator.cs
  • src/modules/Elsa.Studio.Login/Services/OpenIdConnectPkceService.cs
  • src/modules/Elsa.Studio.Login/Services/OpenIdConnectRefreshTokenService.cs

TITLE: New standalone OIDC Authentication module for Elsa Studio

USER INTENT:
Create a new optional, best-practices OpenID Connect authentication module for Elsa Studio as a clean, decoupled replacement/alternative to the current OIDC implementation that is intertwined with Elsa.Studio.Login. The user wants a plan first, then autonomous execution, asking questions only when necessary.

TASK DESCRIPTION:

  • Implement a new optional module (new class library) named:
    • Elsa.Studio.Authentication.OpenIdConnect
  • Goals/requirements for the new implementation:
    • Keep the existing OIDC implementation in place “as-is” (no breaking changes), but do not build on it directly; instead, start a clean-slate implementation in the new project.
    • Decouple OIDC authentication concerns from the more general-purpose Elsa.Studio.Login project (reduce tight coupling / intermixing).
    • Reassess the current approach of “manually” fetching access tokens:
      • Determine whether manual token acquisition is strictly necessary.
      • Investigate leveraging built-in Microsoft libraries/packages that can automate token handling (e.g., standard OIDC + token management patterns in ASP.NET Core / Blazor).
      • When evaluating token strategy, consider impact/requirements of WorkflowInstanceObserverFactory (token access needs, propagation, background calls, etc.).
    • Support both hosting models:
      • Blazor Server
      • Blazor WebAssembly (WASM)
    • If needed to support these hosting models cleanly, create additional projects targeting each model (e.g., separate packages for Server vs WASM or host-specific integration layers).

EXISTING:

  • Elsa Studio already has an OIDC implementation, but it is considered suboptimal because:
    • It is intermixed/tightly coupled with Elsa.Studio.Login.
    • It performs manual access token fetching.
  • The user attached files showing the current implementation for reference only, with explicit instruction that the assistant may use them as it sees fit, but should prefer a clean-slate approach.

PENDING:

  • Produce an implementation plan for the new Elsa.Studio.Authentication.OpenIdConnect module before coding.
  • Implement the module in the new empty project:
    • Establish clean abstractions and integration points with Elsa Studio.
    • Decide on token acquisition/management strategy (manual vs built-in) and ensure it works with WorkflowInstanceObserverFactory.
    • Add support for Blazor Server and Blazor WASM, potentially via additional projects/packages if required.
  • Determine exactly which Microsoft authentication packages/patterns to use for each hosting model:
    • Server: ASP.NET Core authentication middleware + OIDC handler patterns.
    • WASM: Microsoft.AspNetCore.Components.WebAssembly.Authentication-style patterns (or equivalent) with MSAL/OIDC integration if applicable.
  • Ensure the new module is optional and does not force consumers to adopt it, nor break existing login/OIDC behavior.

CODE STATE:

  • New project mentioned (currently empty):
    • `Elsa.Studio.A...

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Implement optional module for Elsa.Studio.Authentication.OpenIdConnect Add standalone OpenID Connect authentication module with multi-provider abstractions Jan 8, 2026
Copilot AI requested a review from sfmskywalker January 8, 2026 09:40
@sfmskywalker sfmskywalker marked this pull request as ready for review January 8, 2026 09:51
Copilot AI review requested due to automatic review settings January 8, 2026 09:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request implements a standalone OpenID Connect authentication module for Elsa Studio as a clean alternative to the existing OIDC implementation in Elsa.Studio.Login. The implementation introduces shared authentication abstractions that enable future support for additional authentication providers (OAuth2, JWT, SAML, etc.) and leverages Microsoft's native authentication infrastructure for automatic token management.

Key Changes:

  • Four new authentication projects with comprehensive abstractions layer
  • Separate Blazor Server and WASM implementations using platform-native authentication mechanisms
  • Extensive documentation including architecture guide and implementation summary

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
Elsa.Studio.Authentication.Abstractions/* New shared abstractions project with ITokenAccessor interface and AuthenticationOptions base class for reusable patterns across authentication providers
Elsa.Studio.Authentication.OpenIdConnect/* Core OIDC module with IOidcTokenAccessor interface, OidcOptions configuration, and OidcAuthenticationProvider implementation
Elsa.Studio.Authentication.OpenIdConnect.BlazorServer/* Blazor Server implementation using ASP.NET Core OIDC middleware with cookie-based sessions and server-side token storage
Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm/* Blazor WASM implementation using framework's IAccessTokenProvider for automatic token management
src/modules/AUTHENTICATION_ARCHITECTURE.md Comprehensive architecture documentation explaining multi-provider design and integration points
IMPLEMENTATION_SUMMARY.md Implementation overview with architectural decisions and migration guidance
Elsa.Studio.sln Solution file updated to include 3 of the 4 new projects, plus unintended platform configuration changes
Directory.Packages.props Added Microsoft.AspNetCore.Authentication.OpenIdConnect package versions for net8.0, net9.0, and net10.0

Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Studio.Authentication.OpenIdConnect", "src\modules\Elsa.Studio.Authentication.OpenIdConnect\Elsa.Studio.Authentication.OpenIdConnect.csproj", "{E88C478A-6B8C-46F3-941C-BEBD798ECD06}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm", "src\modules\Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm\Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm.csproj", "{AED216D2-620D-4446-931F-BDEF357DA805}"
EndProject
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BlazorServer project exists in the file system (src/modules/Elsa.Studio.Authentication.OpenIdConnect.BlazorServer) but is not added to the solution file. This means it won't be built as part of the solution and won't be included in CI/CD pipelines. The project needs to be added to Elsa.Studio.sln.

Suggested change
EndProject
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Studio.Authentication.OpenIdConnect.BlazorServer", "src\modules\Elsa.Studio.Authentication.OpenIdConnect.BlazorServer\Elsa.Studio.Authentication.OpenIdConnect.BlazorServer.csproj", "{3F6B7A9A-5A94-4C5E-9E4C-3F9F8C7C2C10}"
EndProject

Copilot uses AI. Check for mistakes.
Comment on lines +469 to +477
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Debug|x64.Build.0 = Debug|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Debug|x86.ActiveCfg = Debug|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Debug|x86.Build.0 = Debug|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|Any CPU.Build.0 = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x64.ActiveCfg = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x64.Build.0 = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x86.ActiveCfg = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x86.Build.0 = Release|Any CPU
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution file has been modified to add x64 and x86 platform configurations for every project in the solution. This is a significant change that affects all existing projects, not just the new authentication modules. This appears to be an unintended side effect and adds 304 lines of build configuration that may not be necessary for a Blazor application. Typically, Blazor projects only use "Any CPU" configuration. Consider reverting these platform configuration changes and only adding the new authentication projects without modifying existing project configurations.

Suggested change
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Debug|x64.Build.0 = Debug|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Debug|x86.ActiveCfg = Debug|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Debug|x86.Build.0 = Debug|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|Any CPU.Build.0 = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x64.ActiveCfg = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x64.Build.0 = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x86.ActiveCfg = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|x86.Build.0 = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09E284E0-7F8E-4346-962F-90F3FBA8837D}.Release|Any CPU.Build.0 = Release|Any CPU

Copilot uses AI. Check for mistakes.
sfmskywalker and others added 15 commits January 8, 2026 16:27
…ing ElsaAuth and OpenID Connect integration.
…back to default Unauthorized component when `IAuthorizationService` is unavailable.
…to `Elsa.Studio.Authentication.ElsaAuth`. Simplify dependencies and refactor JWT parsing for BlazorServer and BlazorWasm modules.
…eline, and revise default `GetClaimsFromUserInfoEndpoint`.
…ssageHandler` and remove obsolete references
…calization, workflows, deprecated, samples, and dashboard. Remove obsolete project references.
…dentity authentication with a login UI and unauthorized redirect behavior.
…ject references, and refine namespace imports for authentication module.
…t creation to support non-authenticated backend calls.
…entication modules. Introduce token refresh coordinators, configuration providers, and support for silent token refresh. Update related services and integrate advanced options for customization.
…ement browser-side pings, background services, and configurable strategies.
sfmskywalker and others added 7 commits January 9, 2026 19:35
…atibility patches, improve URI handling, and modularize features.
…opes during token exchange (#722)

* Initial plan

* Fix Azure AD authentication by passing explicit API scopes during token requests

- Updated WasmOidcTokenAccessor to request access tokens with explicit resource scopes
- Filter out standard OIDC scopes (openid, profile, email, offline_access) and pass only API scopes
- Register OidcOptions in DI container so WasmOidcTokenAccessor can access configured scopes
- This ensures Azure AD receives scope parameter during token exchange, fixing AADSTS errors

Co-authored-by: sfmskywalker <[email protected]>

* Add Azure AD configuration documentation for Blazor WASM

- Document Azure AD app registration setup and requirements
- Explain single-resource scope limitation (no mixing Graph + custom API scopes)
- Add troubleshooting guide for common Azure AD errors (AADSTS28000, AADSTS28003)
- Update example to use AddElsaOidcAuthentication instead of AddOidcAuthentication
- Document that standard OIDC scopes are automatically filtered

Co-authored-by: sfmskywalker <[email protected]>

* Address code review feedback

- Register OidcOptions as singleton instance instead of using Configure<T>
- Remove IOptions<T> dependency from WasmOidcTokenAccessor
- Add null check for Scopes array to prevent NullReferenceException
- Simplify DI registration pattern

Co-authored-by: sfmskywalker <[email protected]>

* Update src/modules/Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm/Services/WasmOidcTokenAccessor.cs

Co-authored-by: Copilot <[email protected]>

* Update src/modules/Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm/Services/WasmOidcTokenAccessor.cs

Co-authored-by: Copilot <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: sfmskywalker <[email protected]>
Co-authored-by: Sipke Schoorstra <[email protected]>
Co-authored-by: Copilot <[email protected]>
…ssignments and remove default path values from `OidcOptions`.
Introduce `IScopedAccessTokenProvider`, `IOidcTokenAccessorWithScopes`, and associated models to enable scope-aware token acquisition based on token purposes. Update handlers to support backend API scopes and implement scoped token caching for multi-audience token scenarios.
…te OIDC providers, and enhance incremental consent support.
@sfmskywalker sfmskywalker merged commit eedf02c into enh/auth-oidc-entra Jan 9, 2026
1 check passed
@sfmskywalker sfmskywalker deleted the copilot/implement-elsastudio-authentication-oidc branch January 9, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants