Genocs.Auth Agent Reference

`Genocs.Auth` provides JWT authentication and token management for ASP.NET Core services in the Geno

Genocs.Auth — Agent Reference Documentation

Format: AI-optimized agent reference. Structured for rapid decision-making. All capability claims are linked to actual source files. Do not infer capabilities not listed here.


1. Purpose

Genocs.Auth provides JWT authentication and token management for ASP.NET Core services in the Genocs ecosystem. It covers:

  • JWT registration with symmetric keys, X.509 certificates, or OpenIdConnect discovery (AddJwt, AddOpenIdJwt, AddPrivateKeyJwt).
  • Token issuance (IJwtHandler.CreateToken) with full claims, roles, audience, and configurable expiry.
  • Token validation (IJwtHandler.GetTokenPayload) for decoding tokens without full auth pipeline.
  • Real-time token revocation via an in-memory blacklist (IAccessTokenService, InMemoryAccessTokenService, AccessTokenValidatorMiddleware).
  • Auth bypass mode for development/testing: when jwt.enabled: false, registers DisabledAuthenticationPolicyEvaluator so all requests pass as authenticated.
  • [Auth] attribute — thin wrapper over [Authorize] with configurable scheme.

Package ID: Genocs.Auth
NuGet config section: jwt (= JwtOptions.Position)


2. Quick Facts

PropertyValue
Target frameworksnet10.0, net9.0, net8.0
Config section keyjwt (= JwtOptions.Position)
Registration guardbuilder.TryRegister("auth") — idempotent
Default signing algorithmHS256 (symmetric); auto-switches to RS256 for X.509 certs
Token storage for revocationIMemoryCache (in-process)
Expiry default60 minutes (ExpiryMinutes), overridable with Expiry (TimeSpan)
RequiresGenocs.Security (project/package ref), Microsoft.AspNetCore.Authorization
Source filesrc/Genocs.Auth/Extensions.cs

3. Use When

  • You need JWT Bearer authentication in any Genocs ASP.NET Core service.
  • You need to issue tokens from within the service (e.g. identity/auth endpoint) — inject IJwtHandler and call CreateToken(userId, roles, audience, claims).
  • You need real-time token revocation without a distributed store — use IAccessTokenService.Deactivate(token) and UseAccessTokenValidator middleware.
  • You need OpenID Connect / Firebase-compatible JWT validation — use AddOpenIdJwt.
  • You need RSA private-key signed JWT validation — use AddPrivateKeyJwt.
  • You need to completely disable auth in a development or testing environment — set jwt.enabled: false.

4. Do Not Assume

  • AddJwt is idempotentTryRegister("auth") blocks all subsequent calls; calling it twice is safe.
  • AddOpenIdJwt and AddPrivateKeyJwt are NOT guarded by TryRegister. Do not call them together with AddJwt — they each independently call AddAuthentication(...) / AddJwtBearer(...).
  • DisabledAuthenticationPolicyEvaluator is registered when jwt.enabled = false. All requests will appear as authenticated in this mode — never use in production.
  • IAccessTokenService (InMemoryAccessTokenService) is in-memory only. Revoked tokens are NOT shared across service replicas. For distributed revocation, replace the IAccessTokenService registration.
  • AccessTokenValidatorMiddleware must be explicitly added to the pipeline via UseAccessTokenValidator. AddJwt registers it as a transient middleware but does NOT add it to the pipeline automatically.
  • UseAccessTokenValidator checks the in-memory blacklist only. JWT signature and expiry validation is still performed by the standard JwtBearer middleware; the access token validator provides an additional real-time revocation check on top.
  • X.509 certificate for signing: if the certificate has a private key, it is used for both issuing and validating. If public key only, it is used for validation only. Both cases log to Console.WriteLine.
  • ClockSkew is set to TimeSpan.Zero — there is no tolerance for clock drift between issuer and validator. Tokens expire exactly at the exp claim.
  • AllowAnonymousEndpoints (in JwtOptions) — AccessTokenValidatorMiddleware bypasses the blacklist check for these exact path strings; standard JWT Bearer middleware still applies to them.

5. High-Value Entry Points

Extensions.cs → AddJwt(IGenocsBuilder, string sectionName, Action<JwtBearerOptions>?)
Extensions.cs → AddOpenIdJwt(IGenocsBuilder, string sectionName)
Extensions.cs → AddPrivateKeyJwt(IGenocsBuilder, string sectionName)
Extensions.cs → UseAccessTokenValidator(IApplicationBuilder)
IJwtHandler.cs → IJwtHandler                              ← create and decode tokens
IAccessTokenService.cs → IAccessTokenService              ← revoke tokens
AccessTokenValidatorMiddleware.cs                          ← pipeline hook for revocation
JsonWebToken.cs → JsonWebToken                             ← token issuance output model
Configurations/JwtOptions.cs → JwtOptions                 ← full config model
Attributes/AuthAttribute.cs → [Auth]                      ← endpoint authorization shorthand

6. Decision Matrix

GoalAPI to use
Register standard symmetric-key JWT authbuilder.AddJwt() with jwt.issuerSigningKey set
Register X.509 certificate JWT authbuilder.AddJwt() with jwt.certificate.location or jwt.certificate.rawData set
Register OpenIdConnect / Firebase JWTbuilder.AddOpenIdJwt() with jwt.issuer + jwt.metadataAddress
Register RSA private-key JWT validationbuilder.AddPrivateKeyJwt() with jwt.issuerSigningKey (RSA key)
Issue a new JWTInject IJwtHandler, call CreateToken(userId, roles, audience, claims)
Decode a JWT without auth pipelineInject IJwtHandler, call GetTokenPayload(accessToken)
Revoke the currently active tokenInject IAccessTokenService, call DeactivateCurrent()
Check if a specific token is revokedInject IAccessTokenService, call IsActive(token)
Enforce revocation check in pipelineapp.UseAccessTokenValidator() (after UseAuthentication)
Disable auth in dev/testSet jwt.enabled: false in config
Customize JwtBearerOptions at registrationPass Action<JwtBearerOptions> to AddJwt(...)
Add auth to an endpointDecorate with [Auth("Bearer")] or use auth: true in endpoint DSL

7. Minimal Integration Recipe

7.1 appsettings.json (symmetric key)

{
  "jwt": {
    "enabled": true,
    "issuerSigningKey": "your-secret-key-minimum-32-chars!!",
    "issuer": "https://your-service.example.com",
    "validIssuer": "https://your-service.example.com",
    "validAudience": "your-api",
    "validateAudience": true,
    "validateIssuer": true,
    "validateLifetime": true,
    "expiryMinutes": 60,
    "requireHttpsMetadata": false
  }
}

7.2 Program.cs — Registration

IGenocsBuilder gnxBuilder = builder
    .AddGenocs()
    .AddWebApi()
    .AddJwt();   // reads from "jwt" section

gnxBuilder.Build();

7.3 Program.cs — Middleware

var app = builder.Build();

app.UseAuthentication()      // standard ASP.NET Core
   .UseAuthorization()
   .UseAccessTokenValidator();  // optional real-time revocation check

app.UseEndpoints(endpoints => endpoints
    .Get("/public", ctx => ctx.Response.WriteAsync("ok"))
    .Get("/secure", ctx => ctx.Response.WriteAsync("secret"), auth: true));

7.4 Token issuance

public class AuthEndpoint(IJwtHandler jwt)
{
    public JsonWebToken Login(string userId, string role)
        => jwt.CreateToken(userId, roles: [role]);
}

7.5 Token revocation

public class LogoutEndpoint(IAccessTokenService tokens)
{
    public void Logout() => tokens.DeactivateCurrent();
}

7.6 X.509 certificate (appsettings.json)

{
  "jwt": {
    "enabled": true,
    "certificate": {
      "location": "/certs/signing.pfx",
      "password": "secret"
    }
  }
}

7.7 OpenID Connect (Firebase, Entra, etc.)

builder.AddOpenIdJwt();   // reads "jwt.issuer" + "jwt.metadataAddress"

8. Behavior Notes

  • TokenValidationParameters.ClockSkew = TimeSpan.Zero — the clock skew allowance is intentionally removed. Tokens are considered expired exactly at the exp value.
  • Algorithm auto-detection in JwtHandler: if options.Algorithm is empty, uses HS256 for symmetric keys and RS256 for X.509 keys.
  • JsonWebToken.RefreshToken is always set to string.Empty by JwtHandler.CreateToken — refresh tokens are not implemented in this package; callers must implement refresh separately.
  • InMemoryAccessTokenService.GetKey stores revoked tokens under the key "blacklisted-tokens:{token}" in IMemoryCache. The entry TTL matches the JWT expiry (jwtOptions.Expiry or ExpiryMinutes).
  • AllowAnonymousEndpoints matching is exact-string path comparison — no wildcard support.
  • JwtOptions.Challenge (default "Bearer") sets DefaultAuthenticateScheme, DefaultChallengeScheme, and DefaultScheme. Changing this affects all scheme-based authorization attributes in the application.
  • optionsFactory parameter in AddJwt is invoked after all defaults are set, allowing late overrides to JwtBearerOptions (e.g. custom OnTokenValidated events).

9. Source-Accurate Capability Map

CapabilitySource Location
AddJwt (symmetric / cert)Extensions.cs
AddOpenIdJwtExtensions.cs
AddPrivateKeyJwtExtensions.cs
UseAccessTokenValidatorExtensions.cs
DisabledAuthenticationPolicyEvaluatorDisabledAuthenticationPolicyEvaluator.cs
IJwtHandler interfaceIJwtHandler.cs
JwtHandler implementationHandlers/JwtHandler.cs
JsonWebToken output modelJsonWebToken.cs
JsonWebTokenPayloadJsonWebTokenPayload.cs
IAccessTokenService interfaceIAccessTokenService.cs
InMemoryAccessTokenServiceServices/InMemoryAccessTokenService.cs
AccessTokenValidatorMiddlewareAccessTokenValidatorMiddleware.cs
JwtOptions config modelConfigurations/JwtOptions.cs
[Auth] attributeAttributes/AuthAttribute.cs
[ApiKeyOrJwtAuthorize] attributeAttributes/ApiKeyOrJwtAuthorizeAttribute.cs
JwtAuthAttributeJwtAuthAttribute.cs
JwtOrApiKeyAuthenticationMiddlewareJwtOrApiKeyAuthenticationMiddleware.cs

10. Dependencies

DependencyRole
Genocs.SecuritySecurityKeyBuilder.CreateRsaSecurityKey (used in AddPrivateKeyJwt)
Microsoft.AspNetCore.AuthorizationIPolicyEvaluator, [Authorize], policy framework
Microsoft.AspNetCore.Authentication.JwtBearer (transitive)Bearer scheme registration
Microsoft.IdentityModel.Tokens (transitive)TokenValidationParameters, SigningCredentials
System.IdentityModel.Tokens.Jwt (transitive)JwtSecurityTokenHandler, JwtSecurityToken
Microsoft.Extensions.Caching.Memory (transitive)IMemoryCache used in InMemoryAccessTokenService