Audis.Authentication.Hmac 2.0.0

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

Audis.Authentication.Hmac

HMAC-Mechanismus für Audis.Authentication auf Basis von softaware.Authentication.Hmac: Inbound-Scheme mit Replay-Schutz über IDistributedCache, Algorithmus-Allowlist und robuster Header-Prüfung sowie Signatur ausgehender Requests. Policies, Modi, Rechte pro Client und Outbound-Credentials sind im Paket Audis.Authentication beschrieben.

Verwendung

HMAC ist der interne Standard für Service-to-Service-Aufrufe. Das Paket nutzt softaware.Authentication.Hmac unverändert als Abhängigkeit und ist header-kompatibel zu bestehenden Clients und Servern dieser Bibliothek.

// Inbound und Outbound
builder.Services.AddAudisAuthentication(builder.Configuration)
    .AddHmac()
    .AddApiKey();

// Erforderlich für Enforce-Policies mit Hmac: gemeinsamer Distributed Cache für den Replay-Schutz
builder.Services.AddStackExchangeRedisCache(options => options.Configuration = "...");

// Outbound: Credential pro Request (wie bei ApiKey) ...
services.AddHttpClient<IEndpointNotifier, HttpEndpointNotifier>()
        .AddAudisOutboundAuthentication();
request.Options.Set(AudisAuthRequestOptions.Credential, "trust");

// ... oder ein festes Credential für alle Requests eines Clients (Mechanismus per Konfiguration umstellbar)
services.AddHttpClient<ITrustClient, TrustClient>()
        .AddAudisOutboundAuthentication("trust");

// ... oder ausdrücklich HMAC
services.AddHttpClient<ICobraClient, CobraClient>()
        .AddAudisHmacAuthentication("cobra");

Konfiguration:

"Authentication": {
  "Inbound": {
    "Hmac": {
      "Clients": [ { "AppId": "cobra-adapter", "ApiKeys": [ "<neu, Base64>", "<alt, Base64>" ], "Policies": [ "Webhook" ], "Tenants": [ "tenant-a" ] } ],
      "MaxRequestAgeInSeconds": 300,      // Default 300, erlaubt 1..86400
      "TrustProxy": false,                // X-Forwarded-Proto für die signierte URI verwenden
      "AllowLegacyHeaderFormat": false,   // 4-teiliges Legacy-Format (MD5-Body-Hash), Default false
      "AllowProcessLocalNonceStore": false // nur Single-Replica/Entwicklung: Enforce ohne geteilten Cache erlauben, Default false
    },
    "Policies": {
      "ServiceToService": { "Schemes": [ "Hmac" ], "Mode": "Audit" },
      "Webhook":          { "Schemes": [ "Hmac", "ApiKey" ], "Mode": "Audit" }
    }
  },
  "Outbound": {
    "Credentials": {
      "trust": { "Type": "Hmac", "AppId": "audis-web", "ApiKey": "<Base64>", "AllowedOrigins": [ "https://trust.example.org" ] },
      "cobra": { "Type": "Hmac", "AppId": "audis-web", "ApiKey": "<Base64>", "HmacHashingMethod": "HMACSHA512", "RequestBodyHashingMethod": "SHA512", "AllowedOrigins": [ "https://cobra.example.org" ] }
    }
  }
}

Ablauf beim Empfang (Scheme AudisHmac):

  1. Ohne Authorization: Hmac ...-Header liefert das Scheme kein Ergebnis, andere Schemes der Policy (z.B. ApiKey) können den Request authentifizieren.
  2. Der Header wird vorab geprüft (Format, Algorithmen, Base64-Signatur, Timestamp als Unix-Sekunden in kanonischer Form ohne führende Nullen oder Vorzeichen, Nonce aus genau 32 Hex-Zeichen wie beim upstream-Client). Ungültige Header führen zu 401 bzw. im Audit-Modus zu einer Warnung, nie zu einem 500.
  3. Das upstream-Scheme prüft AppId, Signatur (alle Keys des Clients, Rotation ohne Neustart), Zeitfenster MaxRequestAgeInSeconds und die Nonce pro Replica.
  4. Die Nonce wird zusätzlich im INonceStore geprüft und gespeichert. Ist sie bereits bekannt, wird der Request abgewiesen (Replay).
  5. Der Principal enthält audis:service = AppId (zusätzlich NameIdentifier und Name) sowie die Policies/Tenants des Clients (audis:policy, audis:tenant, siehe Client-Rechte bei Audis.Authentication). Fehlt der Client nach einem Reload, wird der Request abgewiesen (fail closed).
  6. Wird die HMAC-Konfiguration während der Prüfung neu geladen, wird der Request abgewiesen (fail closed): Der Principal enthält nie Rechte aus einer Konfiguration, die nicht mehr gilt. Der Client wiederholt den Request mit neuer Nonce.

Hinweise:

  • Header-Format: Hmac {HmacHashingMethod}:{RequestBodyHashingMethod}:{AppId}:{Base64-Signatur}:{Nonce}:{Unix-Sekunden}. Die Keys sind Base64-kodiert und müssen dekodiert mindestens 32 Bytes (256 Bit) lang sein, wie sie der Key-Generator von softaware.Authentication.Hmac erzeugt (z.B. Convert.ToBase64String(RandomNumberGenerator.GetBytes(32))). Kürzere Keys verhindern den Start. Die AppId darf kein : enthalten.
  • Groß-/Kleinschreibung der URI: upstream (softaware.Authentication.Hmac) signiert die URI in Kleinbuchstaben. Zwei URIs, die sich nur in der Groß-/Kleinschreibung von Pfad oder Query unterscheiden, haben daher dieselbe Signatur. Das ist für die Kompatibilität mit bestehenden Clients beibehalten; Schutz bieten TLS (ein Request kann unterwegs nicht verändert werden) und die Nonce (jeder signierte Request wird nur einmal akzeptiert). Endpunkte, bei denen die Schreibweise von Pfad oder Query die Bedeutung ändert, sollten das berücksichtigen.
  • Prozent-kodierte Zeichen im Pfad: Der Client signiert die URI so, wie sie gesendet wird (Uri.AbsoluteUri), upstream prüft auf dem Server den dekodierten Pfad. Prozent-kodierte reservierte Zeichen wie %3A (:), %40 (@), %3D (=), %2C (,) oder %24 ($) im Pfad ergeben daher auf beiden Seiten unterschiedliche Signaturen, der Request wird abgewiesen (fail closed). Das betrifft z.B. AUDIS-IDs wie catalog:12, wenn sie mit Uri.EscapeDataString in den Pfad gesetzt werden. Abhilfe: solche Werte unkodiert in den Pfad setzen (: ist im Pfad erlaubt) oder als Query-Parameter bzw. im Body übertragen. %2F, Leerzeichen und Nicht-ASCII-Zeichen sind nicht betroffen.
  • Kultur: upstream wandelt die URI mit der aktuellen Kultur in Kleinbuchstaben um. Laufen Client und Server mit unterschiedlichen Kulturen, deren Kleinschreibung abweicht (z.B. tr-TR beim I), schlägt die Prüfung für solche Pfade fehl. Dienste sollten mit invarianter oder gleicher Kultur laufen.
  • Algorithmen: Erlaubt sind HMACSHA256/HMACSHA384/HMACSHA512 und als Body-Hash SHA256/SHA384/SHA512. MD5 und SHA1 werden eingehend und ausgehend abgewiesen. Das 4-teilige Legacy-Format impliziert einen MD5-Body-Hash und wird nur mit AllowLegacyHeaderFormat: true akzeptiert.
  • Replay-Schutz: Der Default-INonceStore nutzt einen registrierten IDistributedCache (Key audis:hmac:nonce:{AppId}:{Nonce}). Die TTL beträgt 2 × 86400 + 60 Sekunden (gut 2 Tage): upstream akzeptiert Timestamps bis MaxRequestAgeInSeconds in der Vergangenheit und in der Zukunft, die 60 Sekunden decken Uhrenabweichungen zwischen Replicas ab. Die TTL richtet sich nach dem größten zulässigen Fenster (86400 s), nicht nach dem konfigurierten: Sonst könnte ein verbrauchter Request nach einem Reload mit größerem MaxRequestAgeInSeconds (oder auf einer anderen Replica mit größerem Fenster) erneut akzeptiert werden, sobald sein Eintrag abgelaufen ist. Der Cache muss daher pro akzeptiertem HMAC-Request einen kleinen Eintrag für diese Dauer halten.
    • Ohne registrierten IDistributedCache oder mit AddDistributedMemoryCache() gilt der Replay-Schutz nur pro Replica: ein abgefangener Request kann innerhalb des Zeitfensters einmal pro Replica wiederholt werden.
      • Ist Hmac in einer Policy mit Enforce aktiv, schlägt die Startup-Validierung fehl (fail closed). Abhilfe: einen geteilten IDistributedCache (z.B. Redis) oder einen eigenen INonceStore registrieren. Nur für eine einzelne Replica oder die Entwicklung kann das mit AllowProcessLocalNonceStore: true bewusst erlaubt werden.
      • Bei Audit (und bei Enforce mit AllowProcessLocalNonceStore: true) wird beim Start eine Warnung geloggt (EventId 2001 bzw. 2002).
    • IDistributedCache hat kein atomares „Add if not exists“. Innerhalb einer Replica werden gleichzeitige Requests mit derselben Nonce serialisiert. Zwischen Replicas bleibt ein kleines Restrisiko: zwei gleichzeitige Requests mit derselben Nonce können innerhalb der Cache-Roundtrip-Zeit auf unterschiedlichen Replicas beide akzeptiert werden. Wer das ausschließen muss, registriert eine eigene INonceStore-Implementierung (z.B. Redis SET NX).
    • Ist der Cache nicht erreichbar, wird der Request abgewiesen (fail closed) und ein Fehler geloggt.
  • Validierung (Start und Reload): Clients ohne AppId oder Keys, Keys ohne gültiges Base64 oder kürzer als 32 Bytes, doppelte AppIds, derselbe Key bei mehreren AppIds (die Meldung nennt nur die AppIds), unbekannte Policies oder ungültige Tenants eines Clients, ungültiges MaxRequestAgeInSeconds, eine aktive Policy mit Hmac ohne Clients, eine Enforce-Policy mit Hmac ohne geteilten Replay-Schutz (siehe oben) sowie ausgehende Hmac-Credentials ohne AppId, mit ungültigem Key, schwachem Algorithmus oder ohne gültige AllowedOrigins verhindern den Start. Bei einem Reload (z.B. Umstellung einer Policy von ApiKey auf Hmac) werden dieselben Regeln geprüft, auch für HMAC-Clients, die im selben Reload hinzukommen: Ein ungültiger Reload wird nicht übernommen, die zuletzt gültigen Policies und Credentials bleiben aktiv. Requests an Origins außerhalb von AllowedOrigins werden nicht signiert und nicht gesendet (auch mit AddAudisHmacAuthentication). Fehlermeldungen enthalten nie Keys.
  • Reverse Proxy: Die Signatur umfasst Methode und absolute URI. Werden Host oder Pfad durch einen Proxy umgeschrieben, schlägt die Prüfung fehl. TrustProxy übernimmt nur das Schema aus X-Forwarded-Proto.
  • IMemoryCache: Upstream speichert seine Nonces im registrierten IMemoryCache ohne Size. Setzt der Host MemoryCacheOptions.SizeLimit, schlägt die upstream-Prüfung fehl: Der Request wird nicht authentifiziert (401 bei Enforce, Warnung bei Audit, nie 500). Beim Start wird dann eine Warnung geloggt (EventId 2005). Ausnahmen von upstream werden nur mit ihrem Typ geloggt (EventId 2004).
  • Rate Limiting: upstream merkt sich die Nonce jedes Requests mit gültigem Header-Format und aktuellem Timestamp im IMemoryCache, bevor die Signatur geprüft wird. Die AppId steht im Klartext im Header. Wer sie kennt, kann daher mit ungültigen Signaturen den Speicher einer Replica für MaxRequestAgeInSeconds füllen. HMAC-Endpunkte, die aus nicht vertrauenswürdigen Netzen erreichbar sind, sollten ein Rate Limiting haben (z.B. ASP.NET Core Rate Limiting, Reverse Proxy oder Gateway).
  • Größe des Replay-Caches: Pro akzeptiertem Request bleibt ein Eintrag gut 2 Tage im IDistributedCache (siehe Replay-Schutz). Bei z.B. 50 Requests pro Sekunde sind das rund 8,6 Mio. Einträge; der Cache (z.B. Redis) muss dafür dimensioniert sein.
  • Große Bodies: Für die Signatur wird der Body ausgehender Requests gepuffert und von upstream noch einmal als Byte-Array gelesen, große Uploads belegen dabei etwa die doppelte Größe im Speicher.
  • Client-Registrierung: AddAudisHmacAuthentication() enthält AddAudisOutboundAuthentication(). Ein zusätzlicher Aufruf (davor oder danach) fügt keinen zweiten Handler hinzu, jeder Request wird genau einmal signiert. Wie dort werden Redirects (3xx) nicht automatisch verfolgt. Ein zweiter Aufruf mit einem anderen Credential-Namen führt beim Erzeugen des Clients zu einer InvalidOperationException.
  • Retries: Jeder Versuch wird neu signiert (neue Nonce und neuer Timestamp), sofern der Retry-Handler vor AddAudisOutboundAuthentication() bzw. AddAudisHmacAuthentication() registriert ist. Bei mehreren Aufrufen zählt der letzte: Der Authentifizierungs-Handler steht an dessen Position, ein dazwischen registrierter Retry-Handler signiert also jeden Versuch neu.
  • Upstream-Version: softaware.Authentication.Hmac.AspNetCore und .Client sind exakt gepinnt, weil das Header-Format im Wrapper selbst geparst wird. Ein Update erfordert eine bewusste Anpassung, die Kompatibilitätstests sichern das Format ab.

Lizenz

MIT, © softaware gmbh.

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.

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
2.0.0 81 11/4/2026