From 279a823eb7a694a985c152be8dd5e7ee1be09c0a Mon Sep 17 00:00:00 2001 From: Florian Rappl Date: Mon, 25 May 2026 21:44:07 +0200 Subject: [PATCH] Improved demo and updated docs --- docs/Using/Secure-Communication.md | 32 ++++ docs/_Sidebar.md | 1 + .../Components/_Imports.razor | 6 +- ...ElectronNET.Samples.AuthMiddleware.csproj} | 6 +- .../ElectronNET.Samples.AuthMiddleware.sln | 2 +- .../Program.Minimal.cs.txt | 21 --- .../Program.cs | 10 +- .../README.md | 153 ------------------ 8 files changed, 45 insertions(+), 186 deletions(-) create mode 100644 docs/Using/Secure-Communication.md rename src/ElectronNET.Samples.AuthMiddleware/{ElectronNET.Samples.BlazorSignalR.csproj => ElectronNET.Samples.AuthMiddleware.csproj} (90%) delete mode 100644 src/ElectronNET.Samples.AuthMiddleware/Program.Minimal.cs.txt delete mode 100644 src/ElectronNET.Samples.AuthMiddleware/README.md diff --git a/docs/Using/Secure-Communication.md b/docs/Using/Secure-Communication.md new file mode 100644 index 0000000..4c35a00 --- /dev/null +++ b/docs/Using/Secure-Communication.md @@ -0,0 +1,32 @@ +# Secure Communication + +By default, the IPC communication between .NET and Node.js is secured on startup. Consequently, multiple instances running on different user accounts (but shared on the same machine) can safely co-exist. However, this protection is not enough to secure the web application behind - or make any security statement w.r.t. a malicious root user. + +## Securing the Web Application + +You can opt-in to also guard your ASP.NET Core application using the same mechanism that is already used to protected the IPC broker that deals with the .NET to Node.js communication. + +The key to opt-in is to provide another service *before* calling `AddElectron` on the service collection. + +The following two namespaces are used in the next instructions: + +```cs +using ElectronNET.AspNet.Middleware; +using ElectronNET.AspNet.Services; +``` + +You'll need the following line: + +```cs +builder.Services.AddSingleton(); +``` + +This way, Electron.NET is notified that you want to store and re-use the authentication token that has been negotiated between the .NET and Node.js processes at startup. + +With this being set up you can register a middleware to actually deny requests that have originated outside of your Electron.NET application: + +```cs +app.UseMiddleware(); +``` + +This must be placed above any routing (e.g., before calling `UseRouting` on the web application) in order to properly take effect. diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md index 487f547..6b88356 100644 --- a/docs/_Sidebar.md +++ b/docs/_Sidebar.md @@ -24,6 +24,7 @@ - [Startup-Methods](Using/Startup-Methods.md) - [Debugging](Using/Debugging.md) - [Package Building](Using/Package-Building.md) +- [Secure Communication](Using/Secure-Communication.md) - [Adding a `custom_main.js`](Using/Custom_main.md) # API Reference diff --git a/src/ElectronNET.Samples.AuthMiddleware/Components/_Imports.razor b/src/ElectronNET.Samples.AuthMiddleware/Components/_Imports.razor index d8e69d7..483223c 100644 --- a/src/ElectronNET.Samples.AuthMiddleware/Components/_Imports.razor +++ b/src/ElectronNET.Samples.AuthMiddleware/Components/_Imports.razor @@ -6,6 +6,6 @@ @using static Microsoft.AspNetCore.Components.Web.RenderMode @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop -@using ElectronNET.Samples.BlazorSignalR -@using ElectronNET.Samples.BlazorSignalR.Components -@using ElectronNET.Samples.BlazorSignalR.Components.Layout +@using ElectronNET.Samples.AuthMiddleware +@using ElectronNET.Samples.AuthMiddleware.Components +@using ElectronNET.Samples.AuthMiddleware.Components.Layout diff --git a/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.BlazorSignalR.csproj b/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.AuthMiddleware.csproj similarity index 90% rename from src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.BlazorSignalR.csproj rename to src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.AuthMiddleware.csproj index fc1d522..66909fb 100644 --- a/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.BlazorSignalR.csproj +++ b/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.AuthMiddleware.csproj @@ -12,10 +12,10 @@ - Electron.NET Blazor SignalR Sample + Electron.NET Auth Middleware Sample 1.0.0 - com.electronnet.blazor-signalr-sample - Sample Blazor Server application using Electron.NET with SignalR mode + com.electronnet.auth-middleware-sample + Sample Blazor Server application using Electron.NET with Auth Middleware Electron.NET Copyright © 2026, Electron.NET 30.4.0 diff --git a/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.AuthMiddleware.sln b/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.AuthMiddleware.sln index e77fdf0..b05eec0 100644 --- a/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.AuthMiddleware.sln +++ b/src/ElectronNET.Samples.AuthMiddleware/ElectronNET.Samples.AuthMiddleware.sln @@ -2,7 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.2.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.Samples.BlazorSignalR", "ElectronNET.Samples.BlazorSignalR.csproj", "{1A87C5B5-16EE-5DA0-33B4-17DA71675A87}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.Samples.AuthMiddleware", "ElectronNET.Samples.AuthMiddleware.csproj", "{1A87C5B5-16EE-5DA0-33B4-17DA71675A87}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/ElectronNET.Samples.AuthMiddleware/Program.Minimal.cs.txt b/src/ElectronNET.Samples.AuthMiddleware/Program.Minimal.cs.txt deleted file mode 100644 index d45983b..0000000 --- a/src/ElectronNET.Samples.AuthMiddleware/Program.Minimal.cs.txt +++ /dev/null @@ -1,21 +0,0 @@ -using ElectronNET.API; -using ElectronNET.AspNet.Hubs; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddElectron(); - -// Configure Electron.NET with SignalR mode -builder.WebHost.UseElectron(args, async () => -{ - Console.WriteLine("[TEST] App ready callback started"); -}); - -var app = builder.Build(); - -// Absolute minimal setup -app.MapHub("/electron-hub"); - -Console.WriteLine("[TEST] Application starting..."); - -app.Run(); diff --git a/src/ElectronNET.Samples.AuthMiddleware/Program.cs b/src/ElectronNET.Samples.AuthMiddleware/Program.cs index 87e9bd2..701554a 100644 --- a/src/ElectronNET.Samples.AuthMiddleware/Program.cs +++ b/src/ElectronNET.Samples.AuthMiddleware/Program.cs @@ -1,7 +1,7 @@ using ElectronNET.API; using ElectronNET.API.Entities; -// using ElectronNET.AspNet.Middleware; -// using ElectronNET.AspNet.Services; +using ElectronNET.AspNet.Middleware; +using ElectronNET.AspNet.Services; var watch = new System.Diagnostics.Stopwatch(); watch.Start(); @@ -24,7 +24,7 @@ builder.Services.AddCors(options => }); // Register Electron authentication service as singleton -// builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddElectron(); @@ -63,7 +63,7 @@ var app = builder.Build(); serviceProvider = app.Services; // Capture for use in Electron callback above // Register authentication middleware FIRST (before routing, static files, etc.) -// app.UseMiddleware(); +app.UseMiddleware(); // Enable routing app.UseRouting(); @@ -86,7 +86,7 @@ app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: app.UseAntiforgery(); app.MapStaticAssets(); -app.MapRazorComponents() +app.MapRazorComponents() .AddInteractiveServerRenderMode(); app.Run(); diff --git a/src/ElectronNET.Samples.AuthMiddleware/README.md b/src/ElectronNET.Samples.AuthMiddleware/README.md deleted file mode 100644 index 261f49f..0000000 --- a/src/ElectronNET.Samples.AuthMiddleware/README.md +++ /dev/null @@ -1,153 +0,0 @@ -# Electron.NET Blazor SignalR Sample - -This sample demonstrates how to use Electron.NET with **SignalR-based startup mode** in a Blazor Server application. - -## Features - -✅ **SignalR Communication** - Uses SignalR instead of socket.io for .NET ↔ Electron communication -✅ **Dynamic Port Assignment** - Kestrel binds to port 0, avoiding conflicts -✅ **Blazor Server** - Full Blazor Server support with interactive components -✅ **Electron Integration** - Native desktop window with auto-hide menu bar - -## Prerequisites - -- .NET 10.0 SDK or later -- Node.js 22.x or later - -## How to Run - -### Method 1: Visual Studio - -1. Open the solution in Visual Studio -2. Set `ElectronNET.Samples.BlazorSignalR` as the startup project -3. Press **F5** to run - -The environment variable `ELECTRON_USE_SIGNALR=true` is already configured in `launchSettings.json`. - -### Method 2: Command Line - -```bash -cd src/ElectronNET.Samples.BlazorSignalR -set ELECTRON_USE_SIGNALR=true # Windows -# or -export ELECTRON_USE_SIGNALR=true # Linux/Mac -dotnet run -``` - -## What Happens - -1. ASP.NET Core starts with Kestrel on port 0 (random available port) -2. Electron.NET detects `ELECTRON_USE_SIGNALR=true` environment variable -3. Runtime controller captures the actual port (e.g., `http://localhost:54321`) -4. Electron process is launched with `--electronUrl=http://localhost:54321` -5. Electron connects to SignalR hub at `/electron-hub` -6. Once connected, the `ElectronAppReady` callback fires -7. A browser window is created showing the Blazor Server application -8. Both Blazor's SignalR hub (`/_blazor`) and Electron's hub (`/electron-hub`) run side-by-side - -## Key Files - -- **Program.cs** - Application startup with Electron and SignalR configuration -- **launchSettings.json** - Sets `ELECTRON_USE_SIGNALR=true` environment variable -- **ElectronNET.Samples.BlazorSignalR.csproj** - Project configuration with Electron.NET references - -## Code Highlights - -### Program.cs - -```csharp -// Configure Electron.NET with SignalR mode -builder.WebHost.UseElectron(args, async () => -{ - var options = new BrowserWindowOptions - { - Show = false, - Width = 1200, - Height = 800, - IsRunningBlazor = true, // Crucial for Blazor support - }; - - var browserWindow = await Electron.WindowManager.CreateWindowAsync(options); - browserWindow.OnReadyToShow += () => browserWindow.Show(); -}); - -// ... configure services ... - -// Map the Electron SignalR hub (required for SignalR mode) -app.MapElectronHub(); -``` - -### launchSettings.json - -```json -{ - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "ELECTRON_USE_SIGNALR": "true" - }, - "applicationUrl": "http://localhost:0" -} -``` - -## Differences from Socket.io Mode - -| Aspect | Socket.io Mode | SignalR Mode | -|--------|---------------|--------------| -| Communication | socket.io | SignalR | -| Port Selection | Fixed port found by portscanner | Dynamic (port 0) | -| Startup Order | Electron → .NET or .NET → Electron | .NET → Electron | -| Hub Endpoint | N/A (socket.io on separate port) | `/electron-hub` | -| Environment Variable | None | `ELECTRON_USE_SIGNALR=true` | - -## Console Output - -When running successfully, you should see: - -``` -[SignalR Sample] Application configured and starting... -[RuntimeControllerAspNetDotnetFirstSignalR] StartCore -[RuntimeControllerAspNetDotnetFirstSignalR] URL: http://localhost:54321 -[RuntimeControllerAspNetDotnetFirstSignalR] Launching: --dotnetpackedsignalr --electronUrl=http://localhost:54321 -[RuntimeControllerAspNetDotnetFirstSignalR] Electron ready -[SignalRBridge] Connecting to http://localhost:54321/electron-hub -[ElectronHub] Client connected: abc123xyz -[SignalRBridge] Connected successfully -[RuntimeControllerAspNetDotnetFirstSignalR] SignalR connected! -[SignalR Sample] Electron app ready callback executed! -[SignalR Sample] Window ready and visible! -``` - -## Troubleshooting - -### Window doesn't appear - -- Check that `ELECTRON_USE_SIGNALR` environment variable is set -- Look for errors in the console output -- Verify `app.MapElectronHub()` is called in Program.cs - -### Connection fails - -- Ensure SignalR hub is properly mapped -- Check firewall settings -- Verify Node.js and npm packages are installed (`npm install` in ElectronNET.Host) - -### Hot Reload issues - -- SignalR supports automatic reconnection -- If issues persist, restart the application - -## Next Steps - -- Modify the Blazor components in `Components/Pages/` -- Add more Electron API calls in the `ElectronAppReady` callback -- Explore bidirectional communication between Blazor and Electron - -## Learn More - -- [SignalR Startup Mode Documentation](../../docs/SignalR-Startup-Mode.md) -- [Electron.NET Documentation](https://github.com/ElectronNET/Electron.NET/wiki) -- [ASP.NET Core SignalR](https://docs.microsoft.com/aspnet/core/signalr) - -## License - -MIT - Same as Electron.NET