Guardhouse.SDK
1.0.0-beta16
Prefix Reserved
See the version list below for details.
dotnet add package Guardhouse.SDK --version 1.0.0-beta16
NuGet\Install-Package Guardhouse.SDK -Version 1.0.0-beta16
<PackageReference Include="Guardhouse.SDK" Version="1.0.0-beta16" />
<PackageVersion Include="Guardhouse.SDK" Version="1.0.0-beta16" />
<PackageReference Include="Guardhouse.SDK" />
paket add Guardhouse.SDK --version 1.0.0-beta16
#r "nuget: Guardhouse.SDK, 1.0.0-beta16"
#:package Guardhouse.SDK@1.0.0-beta16
#addin nuget:?package=Guardhouse.SDK&version=1.0.0-beta16&prerelease
#tool nuget:?package=Guardhouse.SDK&version=1.0.0-beta16&prerelease
Guardhouse SDK for .NET
Official .NET SDK for https://guardhouse.cloud platform. Use it for .NET clients when you already configured everything in Guardhouse Cloud.
Installation
Install via NuGet:
dotnet add package Guardhouse.SDK
Or via NuGet Package Manager Console:
Install-Package Guardhouse.SDK
Supported Frameworks: .NET 6.0, 7.0, 8.0, 9.0, 10.0
Quick Start
Client Application (Requesting Access Tokens)
Configure your application as a Client to request access tokens:
using Guardhouse.SDK.Extensions;
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;
});
var app = builder.Build();
// Example: Get access token and call protected API
app.MapGet("/api/call-protected", async (IGuardhouseTokenService tokenService) =>
{
var accessToken = await tokenService.GetAccessTokenAsync();
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var response = await client.GetAsync("https://protected-api.com/data");
var data = await response.Content.ReadAsStringAsync();
return Results.Ok(new
{
Response = data,
AccessTokenPreview = accessToken.Substring(0, Math.Min(20, accessToken.Length)) + "..."
});
});
app.Run();
Minimal configuration:
builder.Services.AddGuardhouseClient(
authority: "https://your-guardhouse-server.com",
clientId: "your-client-id",
clientSecret: "your-client-secret",
scope: "api"
);
Resource Server (Protecting APIs)
Configure your API as a Resource to validate incoming tokens:
using Guardhouse.SDK.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGuardhouseResource(options =>
{
options.Authority = "https://your-guardhouse-server.com";
options.Audience = "my_resource_api";
options.ValidationMode = TokenValidationMode.JwtSignature;
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
// Protected endpoint
app.MapGet("/api/protected", [Authorize] () =>
{
return new { Message = "This is protected data", Timestamp = DateTime.UtcNow };
});
app.Run();
With Token Introspection (RFC 7662):
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";
});
Configuration
Client Options
builder.Services.AddGuardhouseClient(options =>
{
options.Authority = "https://your-guardhouse-server.com"; // Required
options.ClientId = "your-client-id"; // Required
options.ClientSecret = "your-client-secret"; // Required
options.Scope = "api"; // Default: "api"
// Optional features
options.EnableTokenCaching = true; // Default: true
options.CacheExpirationBufferSeconds = 60; // Default: 60
options.EnableTokenRefresh = true; // Default: true
// Resilience
options.EnableHttpResilience = true; // Default: true
options.RequestTimeoutSeconds = 30; // Default: 30
options.MaxRetryAttempts = 3; // Default: 3
});
Resource Options
builder.Services.AddGuardhouseResource(options =>
{
options.Authority = "https://your-guardhouse-server.com"; // Required
options.Audience = "my_resource_api"; // Required
// Validation mode: JWT Signature or Introspection
options.ValidationMode = TokenValidationMode.JwtSignature; // Default: JWT Signature
// Required for Introspection mode
options.IntrospectionClientId = "your-client-id"; // Required for introspection
options.IntrospectionClientSecret = "your-client-secret"; // Required for introspection
// Token validation settings
options.ValidateIssuer = true; // Default: true
options.ValidateAudience = true; // Default: true
options.ValidateLifetime = true; // Default: true
options.ValidateIssuerSigningKey = true; // Default: true
// JWT validation
options.ValidAlgorithms = new[] { "RS256" }; // Default: RS256
options.TokenTypes = new[] { "JWT" }; // Default: JWT
// JWKS caching
options.JwksCacheDurationHours = 24; // Default: 24 hours
options.JwksRefreshIntervalMinutes = 5; // Default: 5 minutes
// Introspection caching (micro-cache for burst traffic)
options.IntrospectionCacheTtlSeconds = 5; // Default: 5 seconds
// HTTPS metadata
options.RequireHttpsMetadata = true; // Default: derived from authority
});
Features
Token Management
✅ Automatic Token Caching - Tokens cached in memory with configurable expiration buffer
✅ Automatic Token Refresh - Seamless token renewal using refresh tokens
✅ HTTP Resilience - Built-in retry policies with exponential backoff
✅ Introspection Support - RFC 7662 token introspection for resource servers
Security
✅ Strict Algorithm Enforcement - Only RS256 allowed (prevents algorithm confusion)
✅ Token Type Validation - Validates typ header to prevent type confusion
✅ Comprehensive Validation - Validates issuer, audience, lifetime, and signature
✅ JWKS with Lazy Refresh - Automatic refresh on unknown keys with rate limiting
✅ Embedded Key Protection - Prevents embedded key attacks
✅ Key ID Injection Protection - Prevents path traversal in kid injection
✅ Psychic Signature Protection - Library validates ECDSA signatures correctly
✅ None Algorithm Prevention - Rejects "none" algorithm tokens
Developer Experience
✅ Configuration Validation - Fails fast at startup for missing required settings
✅ Clear Error Messages - Helpful messages for introspection credentials
✅ Dependency Injection - Full .NET DI support with extension methods
✅ Logging Integration - Built-in logging for debugging and monitoring
API Reference
Client Service
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 token, CancellationToken cancellationToken = default);
Task<bool> IsTokenActiveAsync(string token, 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);
}
Security Features
Validation Modes
JWT Signature Mode (Default):
- Uses JWKS endpoint for token validation
- Automatic key rotation support with lazy refresh
- Validates signature, issuer, audience, lifetime, algorithm, token type
Introspection Mode (RFC 7662):
- Validates tokens via Guardhouse introspection endpoint
- Client credentials required for introspection calls
- Micro-cache (5 seconds) for burst traffic handling
Protected Attack Vectors
- ✅ Validates everything (signature, audience, issuer, lifetime, algorithm, type)
- ✅ Strict RS256 enforcement prevents algorithm confusion
- ✅ Issuer/audience validation prevents confused deputy attacks
- ✅ JWKS library handles embedded key attacks
- ✅ Valid algorithms list prevents algorithm confusion
- ✅ "none" algorithm prevention
- ✅ No fallback between validation methods
- ✅ Token type (typ) validation prevents type confusion
- ✅ Library prevents key ID injection (path traversal)
- ✅ Library validates ECDSA/psychic signatures correctly
JWKS Caching with Lazy Refresh
The SDK implements "Lazy Refresh on Unknown Key" strategy:
- Extract
kid(Key ID) from incoming JWT token header - Check local cache for key
- If key exists: Validate signature (fast path)
- If key missing: Trigger JWKS refresh from
/.well-known/jwks.json - Rate limit refresh (configurable, default 5 minutes)
- Re-check cache and validate with new keys
This ensures your API accepts valid tokens even after key rotation, while protecting against DoS attacks via rate limiting.
Introspection Micro-Cache Strategy
The SDK implements a micro-cache for introspection results:
- Default TTL: 5 seconds
- Purpose: Handles burst traffic (e.g., page loads with multiple API calls)
- Security: Maintains near-real-time revocation security by rapidly refreshing
- Trade-off: Minimal delay (5 seconds) vs. significant performance improvement for burst scenarios
Use introspection mode when you need real-time token revocation checking, but be aware of the network request overhead.
Examples
Calling Protected APIs
public class ExternalApiService
{
private readonly IGuardhouseTokenService _tokenService;
public ExternalApiService(IGuardhouseTokenService tokenService)
{
_tokenService = tokenService;
}
public async Task<string> CallProtectedEndpoint()
{
var accessToken = await _tokenService.GetAccessTokenAsync();
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var response = await client.GetAsync("https://protected-api.com/data");
return await response.Content.ReadAsStringAsync();
}
}
Protecting Endpoints
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult GetAll()
{
return Ok(new[] { "Product 1", "Product 2" });
}
[HttpPost]
[Authorize]
public IActionResult Create([FromBody] CreateProductRequest request)
{
return CreatedAtAction(nameof(GetById), new { id = 1 }, request);
}
[HttpDelete("{id}")]
[Authorize]
public IActionResult Delete(int id)
{
return Ok(new { Message = $"Product {id} deleted" });
}
}
Authorization Policies
builder.Services.AddAuthorization(options =>
{
// Require specific scope
options.AddPolicy("ReadAccess", policy =>
policy.RequireClaim("scope", "read"));
// Require admin role
options.AddPolicy("AdminOnly", policy =>
policy.RequireRole("admin"));
// Require multiple conditions
options.AddPolicy("CanManage", policy =>
policy.RequireClaim("scope", "manage")
.RequireRole("manager"));
});
[HttpGet("admin")]
[Authorize(Policy = "AdminOnly")]
public IActionResult AdminEndpoint()
{
return Ok("Admin data");
}
Dependencies
- .NET 6.0 or later (supports .NET 6.0, 7.0, 8.0, 9.0, 10.0)
- Microsoft.Extensions.DependencyInjection
- Microsoft.Extensions.Http
- Microsoft.Extensions.Http.Polly
- Microsoft.Extensions.Caching.Memory
- Microsoft.Extensions.Options
- Microsoft.AspNetCore.Authentication.JwtBearer
- System.IdentityModel.Tokens.Jwt
- System.Text.Json
- NodaTime
- Polly
Troubleshooting
Configuration Errors
Error: "IntrospectionClientId is required when ValidationMode is set to Introspection"
Add introspection credentials to your configuration:
builder.Services.AddGuardhouseResource(options =>
{
options.ValidationMode = TokenValidationMode.Introspection;
options.IntrospectionClientId = "your-client-id";
options.IntrospectionClientSecret = "your-client-secret";
});
Token Validation Issues
Error: "401 Unauthorized"
- Verify your Guardhouse credentials are correct
- Check that Authority URL matches your Guardhouse instance
- Ensure client is enabled in Guardhouse Cloud
- Verify token hasn't expired
JWKS Refresh Issues
Error: "kid not found" or signature validation fails
- Check your Authority URL is correct
- Verify Guardhouse server is accessible
- Check that
JwksRefreshIntervalMinutesis appropriate (default 5) - Check application logs for JWKS refresh errors
Documentation
- Guardhouse Documentation: https://docs.guardhouse.cloud
- GitHub Issues: https://github.com/legiosoft/guardhouse-sdk-dotnet/issues
- Deployment Guide: docs/DEPLOYMENT.md
License
Licensed under Apache License 2.0
Support
- Guardhouse Cloud: https://guardhouse.cloud
- Documentation: https://docs.guardhouse.cloud
- GitHub Repository: https://github.com/guardhouse/guardhouse-sdk-dotnet
| 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 | 123 | 5/27/2026 |
| 1.0.2 | 584 | 4/24/2026 |
| 1.0.1 | 398 | 3/2/2026 |
| 1.0.0 | 339 | 2/20/2026 |
| 1.0.0-beta17 | 289 | 1/4/2026 |
| 1.0.0-beta16 | 126 | 1/4/2026 |
| 1.0.0-beta15 | 120 | 1/2/2026 |
| 1.0.0-beta14 | 117 | 1/2/2026 |
| 1.0.0-beta1 | 122 | 1/2/2026 |
1.0.0-beta13 - beta release of Guardhouse SDK for .NET.
Features:
- JWT signature validation with JWKS caching and lazy refresh (RFC 7515)
- Token introspection support (RFC 7662)
- Comprehensive security validations (algorithm, token type, issuer, audience, lifetime)
- Configurable validation modes (JWT Signature or Introspection)
- Client credentials flow support with automatic token refresh
- HTTP resilience and retry policies with Polly
- Configuration validation with clear error messages
- Support for .NET 6.0, 7.0, 8.0, 9.0, and 10.0
- Protection against 10+ JWT security attack vectors