StubId.Client 2026.9.4

dotnet add package StubId.Client --version 2026.9.4
                    
NuGet\Install-Package StubId.Client -Version 2026.9.4
                    
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="StubId.Client" Version="2026.9.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="StubId.Client" Version="2026.9.4" />
                    
Directory.Packages.props
<PackageReference Include="StubId.Client" />
                    
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 StubId.Client --version 2026.9.4
                    
#r "nuget: StubId.Client, 2026.9.4"
                    
#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 StubId.Client@2026.9.4
                    
#: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=StubId.Client&version=2026.9.4
                    
Install as a Cake Addin
#tool nuget:?package=StubId.Client&version=2026.9.4
                    
Install as a Cake Tool

StubID

A stand-in for the test environments of the Danish MitID identity brokers, so you can run your MitID login and signing integration in automated tests.

Status: early development. A login works: a stock ASP.NET Core application signs in against it, and so does Node's openid-client — over TLS as well as plain HTTP, each trusting only the certificate the instance hands out, with nothing relaxed on either side. So does a real browser over TLS, in Chromium, Firefox and WebKit, which is the step the real broker makes impossible. Spring Security resolves its metadata from the path-bearing issuer, which is the part it is strictest about. Tests can create citizens, decide how each login resolves, and move the clock to force a timeout, and a .NET suite can drive all of that from code — against a container, or against an instance hosted inside the test process with no Docker at all. Every instance also serves pages that show logins arriving, decide them by hand, and say what the build emulates. What a suite may rely on, and what will move under it, is written down at what stays compatible. The documentation is at stubid.dev, and the roadmap says what is left.

The problem

If your application signs users in with MitID, you reach it through a broker — Signaturgruppen ("Nets eID Broker"), Idura, NemLog-in for the public sector. Their pre-production environments work, but every login has to be approved by hand in MitID's Test Tool, and the MitID widget blocks browser automation on purpose. A pre-production login takes 20-30 seconds when the environment is up.

That makes end-to-end tests of a login flow impractical, and it makes the interesting cases impossible. You cannot ask pre-production for a user who aborts, a session that times out, a CPR match that runs out of attempts, or a signing key that rotates underneath a cached metadata document.

What StubID does

It serves the same endpoints as the broker, on the same paths, with the same claim names and JSON types, so your application only changes its authority URL and client credentials. Behind that surface there is no authenticator: you create citizens yourself and decide how each login resolves.

  • Approve automatically, from a test, or by clicking.
  • Make a login fail with a specific broker error code, on demand and repeatably.
  • Move the clock forward to trigger a timeout, without waiting for it.
  • Run offline, in CI, in milliseconds.
await using var stub = new StubIdBuilder().Build();
await stub.StartAsync();

var citizen = await stub.Citizens.CreateAsync(
    new CitizenSpec { Name = "Anders Berg Christiansen", DateOfBirth = new DateOnly(1985, 3, 29) });

await stub.Behavior.EnqueueAsync(Decision.Approved(citizen.Id).ForClient(clientId));
// Point the application at stub.Authority and sign in.

The container is ready in about three seconds, and the login itself takes about fifty milliseconds. Both numbers come from a test that runs in CI.

Seeing a login work, against an application you can start yourself, is in docs/guides/signing-in.md. How a login is decided, and how to ask why it went the way it did, is in docs/guides/approvals.md. Running StubID from a test suite is in docs/guides/testcontainers.md for the container, and in docs/guides/in-process.md for a host inside the test process, which starts in about 150 milliseconds and needs no Docker. Trusting the certificate it serves over TLS, from any stack, is in docs/guides/certificates.md, and driving a login from a browser test is in docs/guides/browsers.md. Watching logins arrive and steering an instance by hand, without writing any code, is in docs/guides/admin.md — which is also where the exposure this tool assumes is written down.

Fidelity

Being close is not useful; a client library either accepts a token or it does not. What the emulator emits is checked byte-for-byte against recordings of the real broker, including the parts that look like mistakes. The discovery document omits scopes_supported, so ours omits it too. The broker misspells one amr value, so we misspell it identically.

Where StubID knowingly differs, it says so: GET /_stubid/v1/fidelity lists every divergence, and endpoints that are not emulated answer 501 with a link to the reason rather than a misleading 404.

What that is worth, concretely: the first version of the token was written from the broker's own documentation and was wrong in eight ways at once. Four of the claims it omitted appear in no vendor table, one claim it emitted is never sent, and one timestamp is a string where every other timestamp in the same token is a number. Every one of those tokens validated — a client library would have accepted all of them. The recordings are in fixtures/, and what they established is written up in docs/brokers/neb/claims.md.

Not affiliated

StubID is an independent project. It is not affiliated with, endorsed by, or connected to Digitaliseringsstyrelsen, Signaturgruppen, Idura, or IN Groupe. It performs no authentication, verifies no identity, and produces no signature with any legal effect. Do not point it at real people or real personal data. See NOTICE and TRADEMARKS.md.

License

Apache-2.0. See LICENSE.

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.
  • net10.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on StubId.Client:

Package Downloads
StubId.Testing

A Testcontainers module that runs StubID in Docker for a test suite.

StubId.InProcess

Runs StubID inside your test process. No Docker, no listener, no browser.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.9.4 123 9/9/2026
2026.9.3 119 9/7/2026
2026.9.2 118 9/6/2026
2026.9.1 114 9/4/2026