Hellmade.HubAuth.AspNetCore 0.5.1
Hellmade.HubAuth.AspNetCore
ASP.NET Core helpers for services that authenticate users with Zitadel and then ask Hub whether the authenticated user may access the service.
Why this package exists
Every service consumer needs the same backend shape:
- cookie session for browser auth
- OIDC challenge flow against Zitadel
- service callback/logout path conventions
- Hub coarse-access gate after authentication
- optional projection of authenticated users into a local service store
This package centralizes those pieces so services do not hand-roll the same middleware repeatedly.
What it includes
AddHubOidcAuthentication(...)HubOidcAuthenticationOptionsHubPermissionGateMiddlewareHubPermissionGateOptionsHubUserProjectionClaimsTransformationBaseHubUserProjectionContext
What it is for
Use this package when your service:
- runs on ASP.NET Core
- uses OIDC browser login through Zitadel
- keeps its own local cookie session
- uses Hub as the source of truth for service access
- optionally projects authenticated users into a local table
What it is not for
Do not use this package for:
- Hub admin behavior
- direct Zitadel user administration
- service-local business authorization rules
- PAT authentication implementations that are unique to a specific service
Shared route conventions
Recommended downstream service routes:
- backend login:
/auth/login - backend logout:
/auth/logout - backend OIDC callback:
/auth/callback - backend signed-out callback:
/auth/signed-out
Important:
- Zitadel redirect URIs must point to the backend callback route.
- The frontend
/auth/callbackroute is only a post-session landing page.
Core concepts
OIDC auth wiring
AddHubOidcAuthentication(...) configures service-local cookie auth plus OpenID Connect challenge handling.
The service still chooses:
- its login endpoint
- its logout endpoint
- whether it needs local user projection
- how local app authorization works after coarse Hub access is granted
Permission gate
HubPermissionGateMiddleware runs after authentication and before service-local authorization.
It:
- resolves the external user id from claims
- forwards a bearer token when present
- falls back to the saved browser-session access token when needed
- asks Hub whether the user may access the service
Local user projection
HubUserProjectionClaimsTransformationBase exists for services that need a local user row.
Typical reasons:
- local ownership relationships
- local
Guidservice ids - local app preferences or local service roles
It should not be used to make the service authoritative for Hub-owned profile data.
Typical integration
services.AddHubAuthServiceClients(options =>
{
options.HubApiBaseUrl = configuration["HUB__API_BASE_URL"] ?? string.Empty;
options.ServiceSharedSecret = configuration["AUTH__HUB__SERVICE_SHARED_SECRET"];
});
services.AddHubOidcAuthentication(options =>
{
options.OidcIssuer = configuration["AUTH__OIDC__ISSUER"] ?? string.Empty;
options.ClientId = configuration["AUTH__CLIENT_ID"] ?? string.Empty;
options.CallbackPath = "/auth/callback";
options.SignedOutCallbackPath = "/auth/signed-out";
options.IncludeServiceScope = true;
});
app.UseAuthentication();
app.UseMiddleware<HubPermissionGateMiddleware>(new HubPermissionGateOptions
{
ServiceKey = configuration["SERVICE__KEY"] ?? string.Empty,
SkipForAuthenticationSchemes = new[] { "PersonalAccessToken" }
});
app.UseAuthorization();
Required configuration
AUTH__OIDC__ISSUERAUTH__CLIENT_IDHUB__API_BASE_URLSERVICE__KEY
Optional but often needed:
AUTH__HUB__SERVICE_SHARED_SECRET- client secret if your service client requires one
- custom excluded paths for the permission gate
When to add local projection
Add a subclass of HubUserProjectionClaimsTransformationBase only if your service needs a local user record.
Do not add it just to duplicate Hub profile fields.
Common failure modes
invalid_redirect_uri- Zitadel redirect URI does not match the backend callback route
- login succeeds but service returns
403- Hub permission gate denies service access
- login succeeds but user display info is stale or missing
- service is not using Hub directory/profile APIs correctly
- public/anonymous route breaks on directory lookups
AUTH__HUB__SERVICE_SHARED_SECRETis missing for service-authenticated fallback lookups
Related docs
- package overview:
../../README.md - backend package overview:
../README.md - Hub ecosystem architecture:
../../../Hub/docs/Auth/service-consumer-auth-architecture.md - new service integration guide:
../../../Hub/docs/Auth/new-service-auth-integration.md
No packages depend on Hellmade.HubAuth.AspNetCore.
.NET 10.0
- Hellmade.HubAuth.ServiceClients (>= 0.5.1)
- Microsoft.AspNetCore.Authentication.OpenIdConnect (>= 10.0.0)