Authaz logoAuthaz
DocumentationAPI Reference
  • Get Started

    • Authaz
    • Core Concepts
    • Set up your app
    • Quickstart — cURL
  • Authentication

    • Authentication Settings
    • Signup
    • Invitations
    • Password Authentication
    • Multi-Factor Auth
    • Magic Link
    • OAuth / Social Login
    • Passkey (WebAuthn)
    • SAML SSO
    • Machine-to-Machine (M2M)
    • API Keys
  • Authorization

    • Authorization
    • Resources
    • Policies
    • Roles
    • Access Explorer
  • Tenancy

    • Multi-tenancy
    • Tenancy Customization
  • Brand & Host

    • Branding
    • Custom Domains
    • Communications & Email Templates
  • Operate

    • Users
    • Analytics
    • Audit Logs
    • Application Settings
  • SDK Quickstarts

    • Quickstart — Next.js
    • Quickstart — React SPA
    • Quickstart — Hono
    • Quickstart — .NET (Authaz.Sdk)
  • Recipes

    • Recipes & Cookbook
    • Next.js — first integration
    • Next.js — B2B SaaS (multi-tenant)
    • Hono — first integration
    • Hono — B2B SaaS (multi-tenant)
    • React SPA — first integration
    • React SPA — B2B SaaS (multi-tenant)
    • .NET — first integration
    • .NET — B2B SaaS (multi-tenant)
  • Reference

    • Tokens
    • API Reference
    • Errors & Troubleshooting
  • Documentation

    • How Authaz is Built
  1. Authaz
  2. Docs
  3. SDK Quickstarts
  4. Quickstart — .NET (Authaz.Sdk)

SDK Quickstarts

Quickstart — .NET (Authaz.Sdk)

3 min read·Updated Jun 19, 2026

cURL · Next.js · React · Hono · .NET

Authaz.Sdk is the typed .NET client for the Authaz Management API — list users, manage roles, send invitations, run authorization checks, query audit logs.

It's not a Authaz Sign-In SDK. End-user authentication in your .NET web app should still go through the standard OAuth 2.0 + PKCE flow (any OIDC library works); use Authaz.Sdk when your server needs to do management work. About 5 minutes.

Prerequisites#

  • .NET 8 or 9.
  • A Management API key. New to Authaz? Set up your app in 60 seconds — the Management API Key lives in Settings → API Keys. Store it as AUTHAZ__APIKEY in your secrets / environment / configuration.

Step 1 — Install

Previous
Quickstart — Hono
Next
Recipes & Cookbook
#
dotnet add package Authaz.Sdk

Step 2 — Register the SDK#

// Program.cs
using Authaz.Sdk;
 
var builder = WebApplication.CreateBuilder(args);
 
builder.Services.AddAuthazSdk(opts =>
{
    opts.BaseAddress = new Uri("https://your-app.authaz.io");
    opts.ApiKey = builder.Configuration["AUTHAZ:APIKEY"];
});
 
var app = builder.Build();

AddAuthazSdk registers IAuthazClient as a singleton, wires up a named HttpClient, and adds a standard resilience handler (2 retries on 5xx, 10s per-attempt timeout, 30s total, circuit breaker). You don't need to add Polly yourself.

Step 3 — Use the client#

Inject IAuthazClient anywhere — controllers, minimal API endpoints, hosted services:

app.MapGet("/users/{id:guid}", async (Guid id, IAuthazClient authaz) =>
{
    var result = await authaz.Users.GetAsync(id);
    return result.IsSuccess
        ? Results.Ok(result.Value)
        : Results.Problem(result.Error!.Message, statusCode: 500);
});

Step 4 — Handle the result#

Every method returns AuthazResult<T>. There are no thrown exceptions for API errors (network/transport problems become AuthazError.Network).

var result = await authaz.Users.GetAsync(userId);
 
if (result.IsSuccess)
{
    var user = result.Value!;
    Console.WriteLine($"{user.Email} — {user.Status}");
}
else
{
    // Error is a discriminated union
    var problem = result.Error switch
    {
        AuthazError.NotFound nf      => Results.NotFound(nf.Message),
        AuthazError.Unauthorized     => Results.Unauthorized(),
        AuthazError.Forbidden f      => Results.Forbid(),
        AuthazError.Validation v     => Results.ValidationProblem(
            v.Fields.ToDictionary(f => f.Field, f => new[] { f.Message })),
        AuthazError.RateLimited r    => Results.Problem(
            r.Message, statusCode: 429),
        AuthazError.Server s         => Results.Problem(
            s.Message, statusCode: s.StatusCode),
        AuthazError.Network n        => Results.Problem(
            "Authaz unreachable", statusCode: 503),
        _                            => Results.Problem(result.Error!.Message),
    };
}

Pattern-matching on AuthazError is the idiomatic way — every variant carries the data you need to act (HTTP status, retry hint, validation field list).

result.Value is also available via TryGetValue(out var value) if you prefer that style.

Step 5 — What's on the client#

authaz.Users           // List, get, suspend, activate, sessions, MFA reset
authaz.Applications    // List, create, update, stats, custom domains
authaz.Tenants         // List, create, update, per-tenant OAuth config
authaz.Authorization   // .Roles, .Policies, .Permissions.CheckAsync
authaz.Invitations     // Send, list, resend, revoke, pending count
authaz.Email           // Email provider config + templates
authaz.Auth            // API keys, OAuth credentials
authaz.Audit           // Trail logs (search + list)

Step 6 — Run it#

AUTHAZ__APIKEY=mgmt_01h... dotnet run
curl http://localhost:5000/users/01a8...
# → { "id": "01a8...", "email": "you@example.com", ... }

If you see id and email in the response, the SDK is wired up and your API key is good.

If something's wrong#

SymptomLikely causeFix
Every call returns AuthazError.Unauthorized (401)API key wrong, missing, or you used an OAuth Client Secret instead.Management API needs the key from Settings → API Keys → Management (mgmt_01h...), not the Client Secret.
AuthazError.Network on every callWrong BaseAddress, no internet, or DNS / firewall issue.Confirm BaseAddress is https://your-app.authaz.io and the host is reachable.
result.Value is null after IsSuccessYou're checking IsSuccess for an endpoint that returns no body (e.g. delete).Use the bool result; Value is only populated on endpoints that return data.
AuthazError.NotFound for an ID you just createdYou're scoped to the wrong tenant or organization.If multi-tenant, pass the correct tenant ID; verify the ID belongs to the same org as the API key.
DI throws Unable to resolve service for IAuthazClientAddAuthazSdk not called or called after Build().Register before var app = builder.Build();.

For everything else, the errors catalog covers every code Authaz returns.

Worked example — authorization check#

Run a permission decision from the server:

app.MapPost("/can/{permission}", async (
    string permission,
    [FromBody] CheckBody body,
    IAuthazClient authaz) =>
{
    var result = await authaz.Authorization.Permissions.CheckAsync(
        new CheckPermissionRequest(
            UserId: body.UserId,
            Permission: permission,
            TenantId: body.TenantId?.ToString()));
 
    return result.IsSuccess
        ? Results.Ok(new { allowed = result.Value!.Allowed })
        : Results.Problem(result.Error!.Message);
});
 
record CheckBody(string UserId, Guid? TenantId = null);

Allowed typically returns in under a millisecond — Zeratul is built for this.

Customizing the credential provider#

The default credential provider reads AuthazClientOptions.ApiKey and sends it as the X-API-Key header. Swap it out (e.g. for AWS Secrets Manager) by implementing IAuthazCredentialProvider and using the builder:

builder.Services
    .AddAuthazSdk(opts => opts.BaseAddress = new Uri("https://your-app.authaz.io"))
    .WithCredentials<MyVaultCredentialProvider>();

Adding handlers#

Insert your own DelegatingHandler (logging, distributed-tracing headers, etc.):

builder.Services
    .AddAuthazSdk(opts => /* ... */)
    .AddHttpMessageHandler<MyTracingHandler>();

Complete worked example#

  • .NET — first integration (single-tenant) — the full ASP.NET Core app, end to end.
  • .NET — B2B SaaS (multi-tenant) — same, with tenant-scoped Management API calls.

Next steps#

  • API Reference — every Management API endpoint, with the same AuthazResult<T> semantics in the SDK.
  • Multi-tenancy — calling tenant-scoped endpoints when you have a per-tenant Bearer token.
  • Core Concepts — the full mental model.