Skip to content

sdk/dotnet

.NET 8 server SDK for networkless JWT verification, ASP.NET Core request authentication, and webhook signature validation.

Status

Implemented and verified locally. Real IdP round-trip verification (JWKS fetch, token sign/verify against a live Vonvon instance) has not been performed yet and must be completed before production use.

Registry status: UNPUBLISHED. Install this SDK only from the repository source checkout; do not use an external package registry.

Request authentication is Bearer-only by default. An application-owned JWT cookie is read only when its exact name is configured. The opaque __Host-vonvon.rt.* Core cookie is never scanned or verified locally; exchange it by forwarding the complete Cookie header to exact same-origin POST /v1/sessions/token with redirects disabled, and accept only a response containing the token field.

Install

.NET 8 target required.

<ItemGroup>
  <ProjectReference Include="../vonvon/sdk/dotnet/Vonvon.csproj" />
</ItemGroup>
// Program.cs
using Vonvon;

builder.Services.AddVonvon(options =>
{
    options.Issuer   = "https://vonvon.id";
    options.Audience = "your-client-id"; // optional
});

Authenticate a request

// Controller / Minimal API
public class MyController(VonvonClient vonvon) : ControllerBase
{
    [HttpGet("/me")]
    public async Task<IActionResult> GetMe()
    {
        var auth = await vonvon.AuthenticateRequestAsync(
            authorizationHeader: Request.Headers.Authorization);

        if (!auth.Authenticated)
            return Unauthorized(auth.Reason);

        return Ok(new { sub = auth.Claims!.Sub, email = auth.Claims.Email });
    }

    private Task<string> ExchangeSessionAsync() => vonvon.ExchangeSessionTokenAsync(
        $"{Request.Scheme}://{Request.Host}{Request.Path}",
        Request.Headers.Cookie.ToString());
}

Verify token directly

using Vonvon;

var client = new VonvonClient(new VonvonOptions { Issuer = "https://vonvon.id" });

try
{
    var claims = await client.VerifyTokenAsync("eyJ...");
    Console.WriteLine($"sub={claims.Sub} email={claims.Email}");
}
catch (TokenVerificationException ex)
{
    Console.WriteLine($"Invalid token: {ex.Message}");
}

Verify webhook

app.MapPost("/webhooks/vonvon", async (HttpRequest req, VonvonClient vonvon) =>
{
    using var ms = new MemoryStream();
    await req.Body.CopyToAsync(ms);
    var body = ms.ToArray();

    var headers = new Dictionary<string, string>
    {
        ["svix-id"]        = req.Headers["svix-id"].ToString(),
        ["svix-timestamp"] = req.Headers["svix-timestamp"].ToString(),
        ["svix-signature"] = req.Headers["svix-signature"].ToString(),
    };

    var webhookSecret = Environment.GetEnvironmentVariable("VONVON_WEBHOOK_SECRET")
        ?? throw new InvalidOperationException("VONVON_WEBHOOK_SECRET is required");

    try
    {
        var webhook = vonvon.VerifyWebhook(body, headers, secret: webhookSecret);
        return Results.Ok();
    }
    catch (WebhookVerificationException ex)
    {
        return Results.BadRequest(ex.Message);
    }
});

VonvonOptions

Property Default Description
Issuer required Vonvon issuer URL
Audience null Expected aud claim; null skips validation
JwksTtl 1 hour JWKS in-memory cache TTL
SessionCookieName disabled Application-owned JWT cookie name; disabled unless explicitly configured
ClockSkew 5 minutes JWT exp/nbf clock skew tolerance
WebhookToleranceWindow 5 minutes Webhook replay prevention window

VonvonClient API

Method Description
VerifyTokenAsync(token, ct) Verify JWT string; throws TokenVerificationException on failure.
AuthenticateRequestAsync(authHeader, cookies, ct) Extract and verify token; returns AuthStatus; does not throw.
VerifyWebhook(payload, headers, secret) Validate webhook signature; throws WebhookVerificationException on failure. Synchronous.

Platform notes

  • Uses Microsoft.IdentityModel.Tokens and System.IdentityModel.Tokens.Jwt 8.x. ES256 is primary; RS256 and PS256 are supported.
  • AddVonvon() registers VonvonClient as a singleton and wires IHttpClientFactory for JWKS fetching.
  • Exception hierarchy: VonvonException -> JwksException, TokenVerificationException, WebhookVerificationException.
Navigation

Type to search...

Use arrow keys to navigateEnter to selectEscape to close