Cirreum.Authorization.SignedRequest.Client 1.0.7

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

Cirreum.Authorization.SignedRequest.Client

A lightweight .NET client SDK for HMAC-signed HTTP request authentication. Sign outgoing HTTP requests and validate incoming webhooks with HMAC-SHA256 signatures.

Installation

dotnet add package Cirreum.Authorization.SignedRequest.Client

Features

  • Sign outgoing requests - Add HMAC-SHA256 signatures to HTTP requests
  • Validate incoming webhooks - Verify signatures on incoming requests
  • Allocation-free validation - Uses Span<byte> for efficient body hashing
  • Customizable headers - Configure header names and options
  • ASP.NET Core integration - Extension methods for HttpRequest

Sending Signed Requests

Quick Start

using System.Net.Http;

var credentials = new SigningCredentials("your-client-id", "your-signing-secret");

using var client = new HttpClient();
var response = await client.SendSignedAsync(
    HttpMethod.Post,
    "https://api.example.com/orders",
    credentials,
    content: new { ProductId = 123, Quantity = 2 });

Sign a Request

var request = new HttpRequestMessage(HttpMethod.Post, "https://api.example.com/orders");
request.Content = new StringContent(json, Encoding.UTF8, "application/json");

// Sign with credentials object
await request.SignRequestAsync(credentials);

// Or sign with individual values
await request.SignRequestAsync("client-id", "signing-secret");

// Then send
var response = await client.SendAsync(request);

Send Signed Requests

using var client = new HttpClient { BaseAddress = new Uri("https://api.example.com") };

// Send a signed request
var request = new HttpRequestMessage(HttpMethod.Get, "/data");
var response = await client.SendSignedAsync(request, credentials);

// Send with JSON body (auto-serialized)
var response = await client.SendSignedAsync(
    HttpMethod.Post,
    "/orders",
    credentials,
    content: new { ProductId = 123 });

Signing Options

var options = new SigningOptions {
    IncludeQueryString = true,           // Include query string in signature (default: true)
    SignatureVersion = "v1",             // Signature version prefix (default: "v1")
    ClientIdHeaderName = "X-Client-Id",  // Custom header names
    TimestampHeaderName = "X-Timestamp",
    SignatureHeaderName = "X-Signature"
};

await request.SignRequestAsync(credentials, options);

Receiving Webhooks

Quick Start

using Microsoft.AspNetCore.Http;

app.MapPost("/webhooks/events", async (HttpRequest request) => {
    var result = await request.ValidateSignatureAsync("whsec_your_webhook_secret");

    if (!result.IsValid) {
        return Results.Unauthorized();
    }

    var clientId = request.GetSignedRequestClientId();
    // Process webhook...

    return Results.Ok();
});

Throw on Invalid Signature

app.MapPost("/webhooks/events", async (HttpRequest request) => {
    await request.ValidateSignatureOrThrowAsync("whsec_your_webhook_secret");

    // Process webhook - only reached if signature is valid
    return Results.Ok();
});

Validation Options

var options = new ValidationOptions {
    TimestampTolerance = TimeSpan.FromMinutes(5),      // Max age of requests (default: 5 min)
    FutureTimestampTolerance = TimeSpan.FromMinutes(1), // Clock skew allowance (default: 1 min)
    IncludeQueryString = true,                          // Must match sender config
    SupportedSignatureVersions = ["v1"]                 // Supported versions
};

var result = await request.ValidateSignatureAsync(secret, options);

Manual Validation

For non-ASP.NET Core scenarios or custom handling:

var validator = new SignedRequestValidator(options);

var result = validator.Validate(
    body: bodyBytes,
    signature: "v1=abc123...",
    timestamp: 1734567890,
    httpMethod: "POST",
    path: "/webhooks/events",
    signingSecret: "whsec_your_secret");

if (!result.IsValid) {
    Console.WriteLine($"Validation failed: {result.ErrorMessage}");
}

How It Works

The SDK generates signatures using HMAC-SHA256 with the following canonical request format:

{timestamp}.{method}.{path}.{bodyHash}

Where:

  • timestamp: Unix timestamp (seconds since epoch)
  • method: HTTP method in uppercase (GET, POST, etc.)
  • path: Request path including query string (if configured)
  • bodyHash: SHA256 hash of the request body (or empty string hash for bodyless requests)

Three headers are added to each signed request:

  • X-Client-Id: Your public client identifier
  • X-Timestamp: Unix timestamp when the request was signed
  • X-Signature: HMAC signature in format v1={hex-encoded-signature}

Security Notes

  • Keep your signing secret secure - never commit it to source control
  • Store credentials in secure configuration (Azure Key Vault, AWS Secrets Manager, etc.)
  • Requests should be sent immediately after signing to avoid timestamp expiration
  • The default 5-minute timestamp tolerance protects against replay attacks
  • Use separate secrets for API authentication vs webhook validation

Requirements

  • .NET 10.0 or later

License

MIT License - see LICENSE file for details.

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

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.7 98 5/1/2026
1.0.6 101 4/28/2026
1.0.5 122 3/13/2026
1.0.4 107 3/9/2026
1.0.3 116 1/21/2026
1.0.2 141 12/20/2025
1.0.1 190 12/20/2025
1.0.0 193 12/20/2025