SignedChannel 0.3.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package SignedChannel --version 0.3.1
                    
NuGet\Install-Package SignedChannel -Version 0.3.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SignedChannel" Version="0.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SignedChannel" Version="0.3.1" />
                    
Directory.Packages.props
<PackageReference Include="SignedChannel" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SignedChannel --version 0.3.1
                    
#r "nuget: SignedChannel, 0.3.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SignedChannel@0.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SignedChannel&version=0.3.1
                    
Install as a Cake Addin
#tool nuget:?package=SignedChannel&version=0.3.1
                    
Install as a Cake Tool

SignedChannel

A session-bound signed channel between a browser and an ASP.NET Core server:

  • Browser → server is signed HTTP. Every request carries a signature made with a key pair generated per session, so a request cannot be forged or replayed.
  • Server → browser is SignalR push, on a presence-tracked connection — so the server knows when a tab goes away.
  • Business logic is actions, not controllers. You write classes implementing ISecureWebBrowserAction<TRequest, TResponse>; they are resolved by wire name through a namespace convention. No route table, no per-endpoint auth plumbing.
Package Registry What it is
SignedChannel NuGet The server half: handshake, dispatcher, presence hub, push
SignedChannel.MongoDb NuGet MongoDB session storage
signed-channel-client npm The browser half, framework-agnostic

All three version in lockstep from one git tag, so the client and server halves of the protocol cannot drift apart.

Getting started

builder.Services.BindSignedChannelConfiguration(builder.Configuration);
builder.Services.AddSignedChannel(options =>
{
    options.ActionAssembly = typeof(Program).Assembly;
    options.RootNamespace  = "MyApp";
    options.DevActionPrefix = "MyApp.Dev.";   // keep the trailing dot
});
builder.Services.AddSignedChannelMongoDb();   // or your own IChannelSessionStore

app.MapSignedChannelHub();   // must come before any SPA fallback route
app.MapSignedChannel();

ActionAssembly and RootNamespace have no sensible default and are validated at startup. Action lookup scans the assembly you name — if it scanned its own, it would find nothing and every action would answer 404 with nothing in the logs to say why.

An action is just a class in the right place. The wire name "Profile.GetName" resolves to MyApp.Profile.Actions.WebApp.GetName.GetNameAction:

public sealed class GetNameAction : ISecureWebBrowserAction<GetNameRequest, GetNameResponse>
{
    // Constructor dependencies are injected — no DI registration needed.
    public WebBrowserActionsValidationResult ValidateFromWebBrowser(...) => new() { IsValid = true };
    public Task<bool> HasAccess(...) => Task.FromResult(userId is not null);
    public async Task<GetNameResponse> ProcessMessageFromWebBrowserAsync(...) { ... }
}

Signing a session in

The channel never decides who someone is. Authenticate however you like — passkeys, OIDC, a magic link — then tell it:

await sessionStore.SetUserIdAsync(sessionId, yourOwnUserId);

The user id is opaque: echoed to actions, used to decide whether a request counts as signed in, never interpreted. That is what lets a confidential OIDC client hand over the sub from its own callback and get an authenticated channel out of it.

Optional hooks

Register any of these and the channel calls them; leave them out and it does not.

Interface Called for
IChannelSessionObserver a session registering — per-browser bookkeeping
IChannelActivityRecorder a completed action — your audit trail
ISessionDeviceResolver the device behind a signed-in session
IPresenceObserver connections opening and closing
IConnectionChangeNotifier a signed-in session losing a tab

Status

Early — 0.x, API not yet stable. The code is extracted from a production implementation rather than written fresh, so the protocol is settled even while the C# surface still moves.

Licence

Apache-2.0. See LICENSE and NOTICE.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on SignedChannel:

Package Downloads
SignedChannel.MongoDb

MongoDB session storage for SignedChannel. Provides IChannelSessionStore on top of MongoDbService, and is open for inheritance so an application can keep its own per-session state in the same document.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0 15 8/9/2026
0.3.1 31 8/9/2026
0.3.0 38 8/9/2026
0.2.1 29 8/7/2026
0.2.0 42 8/7/2026
0.1.0 40 8/7/2026