Authio.Testing 0.8.0

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

Authio.Testing

Test a .NET application that uses Authio without an Authio server. FakeAuthio is an in-memory Authio reached through an HttpMessageHandler: point the SDK's named clients at it and every request (discovery, keys, grants, introspection, userinfo, end session, Admin API) is answered in memory, recorded, and shaped like Authio's own answers. It is the fake the SDK's own test suites run on.

dotnet add package Authio.Testing

An API test

using var fake = new FakeAuthio();                       // https://authio.test, realm acme, client app
var builder = WebApplication.CreateSlimBuilder();

builder.WebHost.UseTestServer();
builder.Services.AddAuthioClient(o => { o.Authority = fake.BaseUrl; o.Realm = fake.Realm; o.ClientId = "app"; o.ClientSecret = "s3cret"; });
builder.Services.AddFakeAuthioBackchannel(fake);         // the Authio and Authio.Admin clients reach the fake
builder.Services.AddAuthentication().AddAuthioJwtBearer(o => o.Audiences = ["https://api.test"]);

// …

var token = fake.Tokens.CreateAccessToken("user-1")
    .WithAudience("https://api.test")
    .WithScope("orders:read")
    .WithAuthTime(DateTimeOffset.UtcNow)                 // a person; recency requirements read it
    .WithAcr("2").WithAmr("pwd", "otp", "mfa")
    .Build();

FakeTokenBuilder writes any claim (WithActor for a delegation chain, WithImpersonator, WithOrganization, WithResourceAccess, Expired, SignedWithUnknownKey, WithHeaderType, …). Tokens are real RS256 JWTs signed with fake.Tokens, whose public key the fake serves at jwks_uri; JwksOverride serves another key set instead.

A login test

The authorization endpoint redirects straight back with code, state and iss, or answers response_mode=web_message with the page that posts the result. ID tokens carry nonce, sid, acr, amr and at_hash.

Each FakeAuthioClient is configured like a client in Authio's console, and the fake enforces it as Authio does: what the client requires is refused when missing, with an error naming the setting, and the extra is accepted.

Setting Default Enforced
RequirePkce true No code_challenge: invalid_request
PkceMethods ["S256"] A code_challenge without code_challenge_method, or with another method: invalid_request, required or not; a voluntary challenge is enforced at the token endpoint
TokenEndpointAuthMethod from the credentials (private_key_jwt with Jwks, client_secret_basic with Secret, else none) Exact match at the token, introspection, revocation and device endpoints (invalid_client); a public client accepts and ignores a secret, and introspects with its client_id alone, as Authio accepts
SigningAlgorithm RS256 HS256/HS384/HS512 sign ID tokens, UserInfo JWTs and logout tokens with Secret
AccessTokenSigningAlgorithm RS256 HS256/HS384/HS512 sign access tokens with Secret (introspection, exchange, revocation and UserInfo read them back); refresh tokens stay RS256

A client signing with HS* needs a Secret of at least 32, 48 or 64 bytes (RFC 7518 §3.2), as Authio requires: AddClient refuses a shorter one, and so does every token signed with it (EnsureSigningSecret()). A refresh that names a resource addresses the new access token to it; the refresh token keeps its own. | FrontChannelLogoutUri, FrontChannelLogoutSessionRequired | none, true | DeliverFrontChannelLogoutAsync loads the URI with iss and sid |

An unsupported response_mode (anything but query and web_message) is refused with invalid_request.

var redirect = await login.CreateAuthorizationAsync(new AuthioAuthorizationRequest { RedirectUri = "https://app.test/cb" });
var callback = await fake.AuthorizeAsync(redirect.Url);   // follows the authorization endpoint
var result = await login.HandleCallbackAsync(callback, redirect.State);

NextLoginUser signs in another user, NextAuthorizeError answers with an error (login_required, access_denied).

Encrypted tokens

Give a client the public half of its encryption key and its ID and access tokens become nested JWEs, as Authio issues them for a client whose key source is its own:

using var rsa = RSA.Create(2048);
fake.DefaultClient.EncryptionKey = RSA.Create(rsa.ExportParameters(false));
fake.DefaultClient.EncryptionAlgorithm = "RSA-OAEP-256";   // RSA-OAEP (default), RSA-OAEP-256 or RSA1_5
// the SDK: options.ClientEncryptionKey = rsa.ExportPkcs8PrivateKeyPem();

fake.Encrypt(token, recipient, algorithm, encryption) encrypts any token the same way (the fake still recognises it at introspection and userinfo), and FakeJweFactory.Encrypt builds a JWE straight from RFC 7516, independent of IdentityModel. UserInfoSigned and UserInfoEncryptionKey answer UserInfo as a signed or encrypted JWT.

Logout

The end-session endpoint ends the session of the id_token_hint (EndedSessions) and redirects to a registered post_logout_redirect_uri. Back-channel logout is delivered on demand:

using var app = testServer.CreateClient();
var answer = await fake.DeliverBackChannelLogoutAsync(app, subject, sessionId, logoutUri: "/bff/backchannel-logout");

CreateLogoutToken(sub, sid, clientId) builds the logout token alone; BackChannelDeliveries records every delivery.

Everything else

Every grant (client credentials, authorization code, refresh with rotation and reuse detection, password, device with scripted outcomes in DeviceOutcomes, token exchange and connected accounts), forced token errors (TokenErrors), introspection, revocation (RevokeToken), suspended subjects, discovery failures, and Admin API stubs over fake.Admin (users, roles, groups, sessions, account credentials). ManualTimeProvider is a clock whose timers fire at once and record the delays asked for, so polling and Retry-After waits are instant and checkable.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.8.0 0 10/14/2026
0.7.0 0 10/13/2026