Axiam.Sdk
1.0.0-alpha9
Prefix Reserved
dotnet add package Axiam.Sdk --version 1.0.0-alpha9
NuGet\Install-Package Axiam.Sdk -Version 1.0.0-alpha9
<PackageReference Include="Axiam.Sdk" Version="1.0.0-alpha9" />
<PackageVersion Include="Axiam.Sdk" Version="1.0.0-alpha9" />
<PackageReference Include="Axiam.Sdk" />
paket add Axiam.Sdk --version 1.0.0-alpha9
#r "nuget: Axiam.Sdk, 1.0.0-alpha9"
#:package Axiam.Sdk@1.0.0-alpha9
#addin nuget:?package=Axiam.Sdk&version=1.0.0-alpha9&prerelease
#tool nuget:?package=Axiam.Sdk&version=1.0.0-alpha9&prerelease
Axiam.Sdk (C#)
Official C# client SDK for AXIAM — Access eXtended Identity and Authorization Management.
Package identity
- NuGet packages:
Axiam.Sdk(core) andAxiam.Sdk.AspNetCore(ASP.NET Core middleware) - Source: github.com/ilpanich/axiam-csharp-sdk
- License: Apache-2.0
Contract conformance
This SDK conforms to CONTRACT.md §1–§11 (including §6.1 mTLS client certificates).
See CONTRACT.md for the full cross-language behavioral contract.
§1–§11 conformance checklist
| § | Requirement | Where implemented |
|---|---|---|
| §1 | PascalCase method map (Login/VerifyMfa/Refresh/Logout/CheckAccess/Can/BatchCheck) |
AxiamClient.LoginAsync/VerifyMfaAsync/RefreshAsync/LogoutAsync; AuthzRestClient.CheckAccessAsync/CanAsync/BatchCheckAsync; Grpc/AxiamGrpcAuthzClient.CheckAccessAsync/BatchCheckAsync |
| §2 | AuthError/AuthzError/NetworkError taxonomy + HTTP/gRPC status mapping |
Core/ErrorMapper.cs, Core/AuthError.cs, Core/AuthzError.cs, Core/NetworkError.cs |
| §3 | Non-browser CSRF: capture X-CSRF-Token response header, echo on state-changing requests |
Rest/AxiamHttpMessageHandler.cs |
| §4 | Persistent cookie jar (HttpClientHandler { UseCookies = true, CookieContainer = new() }) |
Rest/AxiamHttpClientFactory.cs |
| §5 | Tenant is a required, non-optional constructor parameter | AxiamClient's single public constructor (SC#1) |
| §6 | Strict TLS always on; only escape hatch is a customCa chain-trust callback — no bypass surface |
Rest/AxiamHttpClientFactory.CreatePrimaryHandler (verified by the TlsBypassGrepGateTests xUnit test + a CI grep gate, SC#4) |
| §6.1 | Optional client-certificate / mutual-TLS (mTLS) identity (ClientCertificatePem + ClientKeyPem), applied to both REST and gRPC transports; strict server verification stays on (separate code path from §6) |
Options/AxiamClientOptions.ClientCertificatePem/ClientKeyPem → Rest/AxiamHttpClientFactory.CreatePrimaryHandler/ConfigureFactoryHandler + Grpc/AxiamGrpcChannel.Create |
| §7 | Sensitive<T> struct redacting ToString()/JSON to "[SENSITIVE]" |
Core/Sensitive.cs |
| §8 | AMQP HMAC-SHA256 verify-before-handler, constant-time compare, NEW-4 replay protection (key_version/nonce/issued_at) |
Amqp/Hmac.cs, Amqp/AxiamAmqpConsumer.cs, Amqp/ReplayGuard.cs |
| §9 | SemaphoreSlim(1,1) single-flight refresh, one guard across REST + gRPC |
Auth/RefreshGuard.cs (shared by AxiamClient and Grpc/AuthInterceptor.cs) |
| §10 | app.UseMiddleware<AxiamAuthMiddleware>() + ClaimsPrincipal injection + policy-based [Authorize] |
Axiam.Sdk.AspNetCore/AxiamAuthMiddleware.cs, AxiamPolicyHandler.cs/AxiamPolicyProvider.cs |
| §11 | Declarative [AxiamAccess(action, resource)] authorization attribute with scope + route-param resolution; require_auth/require_role as framework-native [Authorize]/[Authorize(Roles = ...)] |
Axiam.Sdk.AspNetCore/AxiamAccessAttribute.cs, AxiamRequirement.cs, AxiamPolicyHandler.cs/AxiamPolicyProvider.cs |
Declarative authorization helpers (CONTRACT.md §11)
Axiam.Sdk.AspNetCore ships a declarative, per-endpoint authorization attribute built
strictly on top of the §10 middleware — it never re-implements or bypasses JWKS
verification, the tenant check, or §3a CSRF; it only consumes the identity
AxiamAuthMiddleware already injected into HttpContext.User.
using Axiam.Sdk.AspNetCore;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api")]
public sealed class DocumentsController : ControllerBase
{
// action = "read", resource type = "documents" (sent to CheckAccessAsync as
// "documents:read", the server's own "resource:verb" convention). The resource
// UUID is resolved from the "id" route value by default.
[HttpGet("documents/{id:guid}")]
[AxiamAccess("read", "documents")]
public IActionResult GetDocument(Guid id) => Ok(new { id });
// Scope + a non-default route parameter name.
[HttpGet("teams/{teamId:guid}/documents")]
[AxiamAccess("list", "documents", Scope = "team", ResourceRouteParam = "teamId")]
public IActionResult ListTeamDocuments(Guid teamId) => Ok(new { teamId });
}
[AxiamAccess(action, resource)] is sugar over the existing
[Authorize(Policy = "resource:action")] mechanism (AxiamPolicyProvider/
AxiamPolicyHandler) — the legacy "resource:action" policy-string form remains
fully supported side by side with the new attribute.
Semantics (CONTRACT.md §11.2, identical to every other AXIAM SDK):
- Runs strictly after authentication. No verified identity in
HttpContext.User→401 authentication_failed. The attribute never performs its own token extraction. - Subject propagation. The check is made for the request's authenticated user
(
subjectId= theuser_idclaimAxiamAuthMiddlewareinjected), never for the sharedAxiamClient's own session. - Resource resolution. The resource UUID is resolved from the route value named by
ResourceRouteParam(default"id"). A missing or non-UUID route value is a programming error →400 invalid_request— never a silent allow, never aGuid.Empty/nil-UUID fallback. - Scope. The optional
Scopeproperty is passed through toCheckAccessAsyncverbatim. - Fail-closed on transport failure. A
NetworkErrorwhile calling the authz endpoint →503 authz_unavailable— deny, never allow, on a transport failure. - No decision caching. Every check is a fresh
CheckAccessAsynccall, exactly like the legacy policy-string form. - Deny outcome.
403 authorization_denied.
require_auth and require_role are not new types in this SDK — they map directly
onto ASP.NET Core's own [Authorize] and [Authorize(Roles = "admin,editor")]
(AxiamAuthMiddleware already emits a ClaimTypes.Role claim per role, so
role-based [Authorize] works out of the box). require_role is a local check
against the verified token's claims — it never calls the AXIAM server, and it is
documented here (as in every AXIAM SDK) as NOT a substitute for the resource-level
[AxiamAccess(...)] check above.
Quickstart
dotnet add package Axiam.Sdk
dotnet add package Axiam.Sdk.AspNetCore # optional — ASP.NET Core middleware + DI
using Axiam.Sdk;
// tenantId is a required, positional constructor argument (SC#1) — there is no
// overload or default that omits it (CONTRACT.md §5).
using var client = new AxiamClient(new Uri("https://your-axiam-instance"), "your-tenant-slug");
var login = await client.LoginAsync("alice@example.com", "correct horse battery staple");
if (login.MfaRequired)
{
login = await client.VerifyMfaAsync(login.ChallengeToken!.Value, totpCode: "123456");
}
bool canRead = await client.Authz.CanAsync("documents:read", documentId);
See examples/ for a full runnable ASP.NET Core sample (middleware +
policy authorization, SC#3) and a console quickstart covering REST, gRPC, and
AMQP.
mTLS / client certificates (CONTRACT.md §6.1)
AXIAM authenticates IoT devices and service accounts by mutual TLS: the client
presents an X.509 identity certificate (signed by the tenant's organization CA) that the
server binds to a service account. Configure the client identity with a PEM certificate
chain plus a PEM private key (PKCS#8 or PKCS#1) via AxiamClientOptions — it is applied
to both the REST and gRPC transports of that same client instance:
using Axiam.Sdk;
using Axiam.Sdk.Options;
var options = new AxiamClientOptions
{
BaseUrl = new Uri("https://your-axiam-instance"),
TenantId = "your-tenant-slug",
ClientCertificatePem = File.ReadAllBytes("device-cert.pem"), // PEM cert chain
ClientKeyPem = File.ReadAllBytes("device-key.pem"), // PEM private key (secret)
};
using var client = new AxiamClient(new Uri("https://your-axiam-instance"), "your-tenant-slug", options);
Notes:
- Opt-in. Omitting the certificate leaves the SDK's default bearer-cookie behavior
unchanged.
ClientCertificatePemandClientKeyPemmust be supplied together — providing exactly one throwsArgumentExceptionat client construction. - Strict TLS preserved. Presenting a client certificate never relaxes server verification; the client-cert code path is entirely separate from §6's server-trust handling and installs no permissive server-validation delegate.
- Key secrecy (§7). The private key is secret material — it is never logged, serialized, or exposed via a public getter beyond the options object it is set on.
- On
Axiam.Sdk.AspNetCore, the same two properties exist onAxiamOptionsand flow through to the sharedAxiamClient.
Grpc.Tools exception
The C# SDK is the one documented exception to the buf codegen pipeline every other
AXIAM SDK uses. Rust, TypeScript, Python, Java, PHP and Go all run buf generate to produce
gRPC stubs from proto/axiam/v1/. The C# SDK uses Grpc.Tools MSBuild codegen instead:
the .proto files are included via <Protobuf Include="../proto/axiam/v1/*.proto" /> in
Axiam.Sdk.csproj and stubs are generated into obj/ at build time by the Grpc.Tools
package, not by buf. This repository therefore carries no buf.yaml/buf.gen.yaml.
This exception is intentional and approved (D-01). The C# SDK still tracks the same
proto/axiam/v1/ definitions as the buf pipeline; only the codegen toolchain differs.
Status
Axiam.Sdk (REST + gRPC + AMQP + Sensitive + JWKS) and Axiam.Sdk.AspNetCore
(middleware + DI + policy authorization) are both fully implemented and tested. See
the Quickstart above and examples/ for runnable code.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 was computed. 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 was computed. 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. |
-
net8.0
- BouncyCastle.Cryptography (>= 2.6.2)
- Google.Protobuf (>= 3.35.1)
- Grpc.Net.Client (>= 2.80.0)
- Microsoft.Extensions.Http (>= 10.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.9)
- RabbitMQ.Client (>= 7.2.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Axiam.Sdk:
| Package | Downloads |
|---|---|
|
Axiam.Sdk.AspNetCore
ASP.NET Core middleware, DI extensions, and policy-based authorization for the AXIAM C# SDK (Axiam.Sdk). |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-alpha9 | 47 | 7/18/2026 |
| 1.0.0-alpha8 | 57 | 7/17/2026 |
| 1.0.0-alpha24 | 52 | 8/4/2026 |
| 1.0.0-alpha23 | 52 | 8/2/2026 |
| 1.0.0-alpha21 | 50 | 7/30/2026 |
| 1.0.0-alpha2 | 57 | 7/16/2026 |
| 1.0.0-alpha18 | 66 | 7/24/2026 |
| 1.0.0-alpha16 | 58 | 7/22/2026 |
| 1.0.0-alpha15 | 47 | 7/21/2026 |
| 1.0.0-alpha12 | 49 | 7/19/2026 |
| 1.0.0-alpha11 | 49 | 7/18/2026 |
| 1.0.0-alpha10 | 53 | 7/18/2026 |
| 1.0.0-alpha | 54 | 7/16/2026 |