Guardhouse.SDK
1.0.3
Prefix Reserved
dotnet add package Guardhouse.SDK --version 1.0.3
NuGet\Install-Package Guardhouse.SDK -Version 1.0.3
<PackageReference Include="Guardhouse.SDK" Version="1.0.3" />
<PackageVersion Include="Guardhouse.SDK" Version="1.0.3" />
<PackageReference Include="Guardhouse.SDK" />
paket add Guardhouse.SDK --version 1.0.3
#r "nuget: Guardhouse.SDK, 1.0.3"
#:package Guardhouse.SDK@1.0.3
#addin nuget:?package=Guardhouse.SDK&version=1.0.3
#tool nuget:?package=Guardhouse.SDK&version=1.0.3
Guardhouse SDK for .NET
Official .NET SDK for Guardhouse Cloud.
Use it to:
- request access tokens with the client credentials flow
- validate incoming tokens with JWT signature validation or introspection
- call the external Guardhouse system API for users, roles, and permissions
- validate Guardhouse webhook signatures in receiver endpoints
Supported frameworks:
- .NET 6.0
- .NET 7.0
- .NET 8.0
- .NET 9.0
- .NET 10.0
Installation
dotnet add package Guardhouse.SDK
What The SDK Includes
IGuardhouseTokenServicefor token acquisition, refresh, and introspectionIGuardhouseResourceServicefor resource-server token validationIGuardhouseUsersClient,IGuardhouseRolesClient, andIGuardhousePermissionsClientfor the external system APIGuardhouseWebhookSignatureValidatorfor validating signed Guardhouse webhooks- DI extensions for client, resource server, and system API registration
- HTTP resilience with Polly
- JWKS caching with lazy refresh
Core Capabilities
- Client credentials token acquisition with in-memory token caching
- Optional refresh-token support through
offline_access - JWT signature validation using OpenID Connect metadata and JWKS
- RFC 7662 token introspection for resource-server validation and client-side inspection
- Typed external system API clients for users, roles, and permissions
- HMAC-SHA256 webhook signature validation with timestamp replay protection
- Retry and timeout policies for outbound HTTP calls
Quick Start
Client Application
using Guardhouse.SDK.Extensions;
using Guardhouse.SDK.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGuardhouseClient(options =>
{
options.Authority = "https://your-guardhouse-server.com";
options.ClientId = "your-client-id";
options.ClientSecret = "your-client-secret";
options.Scope = "api";
options.EnableTokenCaching = true;
options.EnableTokenRefresh = true;
options.IncludeOfflineAccessScope = true;
});
var app = builder.Build();
app.MapGet("/token", async (IGuardhouseTokenService tokenService) =>
{
var accessToken = await tokenService.GetAccessTokenAsync();
return Results.Ok(new
{
AccessTokenPreview = accessToken[..Math.Min(20, accessToken.Length)] + "..."
});
});
app.Run();
System API
Use this when your application needs to call the external Guardhouse endpoints under Users, Roles, and Permissions.
using Guardhouse.SDK.Constants;
using Guardhouse.SDK.Extensions;
using Guardhouse.SDK.Models.Users;
using Guardhouse.SDK.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGuardhouseClientWithApiClients(
authority: "https://your-guardhouse-server.com",
clientId: "your-system-api-client-id",
clientSecret: "your-system-api-client-secret",
scope: AuthorizationConsts.Scopes.SystemApi,
apiBaseUrl: "https://your-guardhouse-server.com");
var app = builder.Build();
app.MapPost("/users", async (IGuardhouseUsersClient usersClient) =>
{
var created = await usersClient.CreateUserAsync(new CreateUserRequest
{
FirstName = "Ada",
LastName = "Lovelace",
Email = "ada@example.com",
SendInvite = true,
InviterName = "Grace Hopper",
RedirectUrl = "https://your-app.example.com/invitation"
});
return Results.Ok(created);
});
app.MapGet("/users/{id:int}", async (int id, IGuardhouseUsersClient usersClient) =>
{
var user = await usersClient.GetUserByIdAsync(id);
return user is null ? Results.NotFound() : Results.Ok(user);
});
app.Run();
For the full endpoint-to-client mapping, see the System API Guide.
Resource Server
using Guardhouse.SDK.Constants;
using Guardhouse.SDK.Extensions;
using Guardhouse.SDK.Models;
using Microsoft.AspNetCore.Authorization;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(GuardhouseConstants.Authentication.DefaultScheme);
builder.Services.AddGuardhouseResource(options =>
{
options.Authority = "https://your-guardhouse-server.com";
options.Audience = "my_resource_api";
options.ValidationMode = TokenValidationMode.JwtSignature;
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/protected", [Authorize] () => Results.Ok(new { Message = "Protected" }));
app.Run();
For introspection mode:
builder.Services.AddGuardhouseResource(options =>
{
options.Authority = "https://your-guardhouse-server.com";
options.Audience = "my_resource_api";
options.ValidationMode = TokenValidationMode.Introspection;
options.IntrospectionClientId = "your-introspection-client-id";
options.IntrospectionClientSecret = "your-introspection-client-secret";
});
Validation modes:
TokenValidationMode.JwtSignaturevalidates JWTs locally using discovered signing keysTokenValidationMode.Introspectionvalidates tokens through the Guardhouse introspection endpoint
Webhook Receiver
Guardhouse sends webhook signatures in X-Hub-Signature using the format t=<unix seconds>,v1=<hex hmac>. The signed payload is <timestamp>.<raw request body>.
using Guardhouse.SDK.Webhooks;
app.MapPost("/webhooks/guardhouse/user-created", async (HttpRequest request, IConfiguration configuration) =>
{
var secret = configuration["Guardhouse:Webhooks:UserCreatedSecret"];
if (string.IsNullOrWhiteSpace(secret))
{
return Results.StatusCode(StatusCodes.Status500InternalServerError);
}
var isValid = await GuardhouseWebhookSignatureValidator.IsValidAsync(request, secret);
if (!isValid)
{
return Results.BadRequest("Signature verification failed.");
}
using var reader = new StreamReader(request.Body);
var json = await reader.ReadToEndAsync();
// Deserialize and handle the webhook envelope here.
return Results.Ok();
});
IsValidAsync validates the timestamped HMAC-SHA256 signature against the raw request body and rewinds the body stream so the endpoint can deserialize the same payload after validation. It rejects bodies over 5 MB by default; pass maxBodySizeBytes only when your webhook contract requires a different limit.
For stricter secret-memory handling, use the overloads that accept secret bytes:
var secretBytes = Convert.FromBase64String(configuration["Guardhouse:Webhooks:Secret"]!);
try
{
var isValid = await GuardhouseWebhookSignatureValidator.IsValidAsync(request, secretBytes);
}
finally
{
CryptographicOperations.ZeroMemory(secretBytes);
}
Registration Helpers
Client registration:
AddGuardhouseClient(...)AddGuardhouse(...)
System API registration:
AddGuardhouseApiClients(...)AddGuardhouseClientWithApiClients(...)AddGuardhouseUserClients(...)AddGuardhouseClientWithUserClients(...)
Resource server registration:
AddGuardhouseResource(...)
Backward-compatible aliases are still available for the older user-service naming.
Repeated calls to the Guardhouse registration helpers are safe. The SDK adds its internal infrastructure once, while later configureAction delegates still layer option values.
Main Interfaces
Token client:
public interface IGuardhouseTokenService
{
Task<string> GetAccessTokenAsync(CancellationToken cancellationToken = default);
Task<TokenResponse> RequestTokenAsync(CancellationToken cancellationToken = default);
Task<TokenResponse> RefreshTokenAsync(string refreshToken, CancellationToken cancellationToken = default);
Task<IntrospectionResponse> IntrospectTokenAsync(string tokenValue, CancellationToken cancellationToken = default);
Task<bool> IsTokenActiveAsync(string tokenValue, CancellationToken cancellationToken = default);
}
Resource service:
public interface IGuardhouseResourceService
{
Task<ClaimsPrincipal?> ValidateTokenAsync(string token, CancellationToken cancellationToken = default);
Task<IntrospectionResponse> IntrospectTokenAsync(string token, CancellationToken cancellationToken = default);
Task<AuthenticationScheme?> GetDefaultSchemeAsync(CancellationToken cancellationToken = default);
}
System API clients:
IGuardhouseUsersClientfor create/get/update user operations, password changes, role assignment, block/unblock, and personal-data deletionIGuardhouseRolesClientfor create/get/update role operations and role-permission assignmentIGuardhousePermissionsClientfor create/get/update permission operationsIGuardhouseUserServiceremains available as a backward-compatible alias ofIGuardhouseUsersClient
Detailed system API usage and endpoint mapping are documented in the System API Guide.
Configuration Notes
Authorityis required for token acquisition and resource-server validation.ApiBaseUrlis the base URL for the external system API.- If
ApiBaseUrlis omitted, the SDK falls back toAuthority. - The intended scope for the system API is
AuthorizationConsts.Scopes.SystemApi(system_api). - For refresh tokens, enable
IncludeOfflineAccessScopeor includeoffline_accessexplicitly inScope. - You can register Guardhouse services from multiple startup paths without duplicating the SDK's internal DI infrastructure.
Security And Reliability
- JWT validation uses issuer, audience, lifetime, and signing-key checks from Guardhouse metadata
- Webhook validation uses the raw request body, a five-minute timestamp tolerance, a 5 MB default body limit, and fixed-time HMAC comparison
- JWKS refresh is lazy and triggered when unknown signing keys are encountered
- Introspection mode does not silently fall back to signature validation
- HTTP calls use retry and timeout policies to handle transient failures
- Error messages sanitize server responses instead of returning raw bodies
System API Coverage
The SDK system API surface is intentionally limited to the external routes exposed by Guardhouse under:
Endpoints/API/UsersEndpoints/API/RolesEndpoints/API/Permissions
If a route is not part of those external endpoint folders, it is not part of the supported SDK system API contract.
Examples
- Example client app: examples/ExampleClient
- Example resource app: examples/ExampleResource
Documentation
- Guardhouse Documentation: guardhouse.cloud/docs
- System API Guide: docs/SYSTEM_API.md
- Deployment Guide: docs/DEPLOYMENT.md
- GitHub Issues: guardhouse-sdk-dotnet/issues
License
Apache-2.0
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 is compatible. 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. |
-
net10.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 10.0.1)
- Microsoft.Extensions.Http.Polly (>= 10.0.1)
- NodaTime (>= 3.2.3)
- Polly (>= 8.6.5)
- System.IdentityModel.Tokens.Jwt (>= 8.15.0)
-
net6.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 6.0.36)
- Microsoft.Extensions.Http.Polly (>= 6.0.33)
- NodaTime (>= 3.2.3)
- Polly (>= 8.6.5)
- System.IdentityModel.Tokens.Jwt (>= 8.15.0)
-
net7.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 7.0.20)
- Microsoft.Extensions.Http.Polly (>= 7.0.20)
- NodaTime (>= 3.2.3)
- Polly (>= 8.6.5)
- System.IdentityModel.Tokens.Jwt (>= 8.15.0)
-
net8.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 8.0.12)
- Microsoft.Extensions.Http.Polly (>= 8.0.12)
- NodaTime (>= 3.2.3)
- Polly (>= 8.6.5)
- System.IdentityModel.Tokens.Jwt (>= 8.15.0)
-
net9.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 9.0.2)
- Microsoft.Extensions.Http.Polly (>= 9.0.2)
- NodaTime (>= 3.2.3)
- Polly (>= 8.6.5)
- System.IdentityModel.Tokens.Jwt (>= 8.15.0)
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 |
|---|---|---|
| 1.0.3 | 111 | 5/27/2026 |
| 1.0.2 | 513 | 4/24/2026 |
| 1.0.1 | 397 | 3/2/2026 |
| 1.0.0 | 338 | 2/20/2026 |
| 1.0.0-beta17 | 287 | 1/4/2026 |
| 1.0.0-beta16 | 124 | 1/4/2026 |
| 1.0.0-beta15 | 119 | 1/2/2026 |
| 1.0.0-beta14 | 116 | 1/2/2026 |
| 1.0.0-beta1 | 121 | 1/2/2026 |
1.0.3 - webhook validation and introspection logging refinement.
Changes:
- Add Guardhouse webhook signature validation helpers
- Add byte-secret webhook validation overloads and default 5 MB webhook body limit
- Downgrade routine inactive introspection token rejections to debug logging