Security Overview — Auth, Encryption & Audit
The base security package providing the ICurrentUserService abstraction and ActorKind
enum. Used by every module that needs to know “who is calling” — audit trails, tenant
resolution, authorization checks.
Choosing the right security modules
Section titled “Choosing the right security modules”| Problem | Module | When to use |
|---|---|---|
| You need to verify who is calling your API | Authentication | Always — choose the provider package matching your identity platform (Keycloak, Entra ID, or Cognito) |
| Users/roles need different access levels | Authorization | When permissions change at runtime or differ per tenant |
| You store PII that must be encrypted at rest | Field-level Encryption | GDPR Art. 32, ISO 27001 A.8.24 — national IDs, medical records, bank accounts |
| You need external secret/key management | Vault & Encryption | Production environments — never store encryption keys in config files |
| You manage user accounts (CRUD, sync) | Identity | When your API owns user lifecycle (registration, deactivation, profile sync) |
| Users can request data export or deletion | Privacy | GDPR Art. 15–18 — any app handling EU personal data |
| Your SPA uses cookie-based auth with consent | Cookies | Browser-based apps with GDPR cookie consent requirements |
| Your SPA should never touch tokens | BFF | SPAs where tokens must stay server-side (XSS mitigation, OAuth BCP) |
| You self-host your identity provider | OpenIddict | When you need full control over OIDC flows, token issuance, and user management |
| You need FAPI 2.0 financial-grade security | FAPI 2.0 | Banking, PSD2, or any high-security API requiring PAR + DPoP + private_key_jwt |
Package structure
Section titled “Package structure”DirectoryGranit.Users/ Base abstractions (ICurrentUserService, ActorKind)
- …
| Package | Role | Depends on |
|---|---|---|
Granit.Users | ICurrentUserService, ActorKind | Granit |
ICurrentUserService
Section titled “ICurrentUserService”The core abstraction for accessing the authenticated actor. Injected everywhere audit fields, tenant resolution, or authorization checks need to know “who is calling.”
public interface ICurrentUserService{ string? UserId { get; } string? UserName { get; } string? Email { get; } string? FirstName { get; } string? LastName { get; } bool IsAuthenticated { get; } ActorKind ActorKind { get; } bool IsMachine { get; } string? ApiKeyId { get; } IReadOnlyList<string> GetRoles(); bool IsInRole(string role);}ActorKind distinguishes between User (human), ExternalSystem (API key / service account),
and System (background jobs, scheduled tasks).
Full security stack
Section titled “Full security stack”The complete authentication and authorization stack is documented in dedicated pages:
graph TD
S[Granit.Users] --> C[Granit]
JWT[Granit.Authentication.JwtBearer] --> S
KC[Granit.Authentication.JwtBearer.Keycloak] --> JWT
EID[Granit.Authentication.JwtBearer.EntraId] --> JWT
CG[Granit.Authentication.JwtBearer.Cognito] --> JWT
GC[Granit.Authentication.JwtBearer.GoogleCloud] --> JWT
DPOP[Granit.Authentication.DPoP] --> JWT
AZ[Granit.Authorization] --> S
AZ --> CA[Granit.Caching]
AZEF[Granit.Authorization.EntityFrameworkCore] --> AZ
AZEF --> P[Granit.Persistence]
BFF[Granit.Bff] --> S
BFFE[Granit.Bff.Endpoints] --> BFF
BFFY[Granit.Bff.Yarp] --> BFF
See also
Section titled “See also”- Authentication — JWT Bearer, Keycloak, Entra ID, Cognito, Google Cloud, DPoP
- BFF — Backend For Frontend pattern for SPAs, session management, YARP proxy
- OpenIddict — self-hosted OIDC server, user management, FAPI 2.0
- Authorization — RBAC permissions, dynamic policy provider
- Identity — user management, Keycloak Admin API, user cache
- Privacy — GDPR compliance, right to erasure
- Core —
ICurrentTenant, exception hierarchy - Persistence —
AuditedEntitybase class, interceptors