Identity — User Claims & Tenant Context
Granit.Identity provides a provider-agnostic identity management layer. Keycloak, Cognito, Google Cloud Identity Platform (Firebase Auth), or any OIDC provider handles authentication — Granit.Identity handles everything else: user lookup, role management, session control, password operations, and a local user cache with GDPR erasure and pseudonymization built in.
Package structure
Section titled “Package structure”DirectoryGranit.Identity/ Abstractions (7 interfaces), null defaults
DirectoryGranit.Identity.Federated/ Federated identity abstractions
- Granit.Identity.Federated.Keycloak Keycloak Admin API implementation (+ realm-vs-client role distinction)
- Granit.Identity.Federated.EntraId Microsoft Graph API implementation (+ Entra ID App Role distinction)
- Granit.Identity.Federated.Cognito AWS Cognito User Pool API implementation
- Granit.Identity.Federated.GoogleCloud Google Cloud Identity Platform (Firebase Auth) implementation
- Granit.Identity.Federated.EntityFrameworkCore User cache (cache-aside, login-time sync)
- Granit.Identity.Federated.Privacy Personal-data export provider for the federated user cache
DirectoryGranit.Identity.Local/ Shared domain types for self-hosted identity providers
- Granit.Identity.Local.AspNetIdentity ASP.NET Core Identity provider (GranitUser + role orchestration + tenant-aware lookup)
- Granit.Identity.Local.Endpoints Account self-service endpoints (login, register, profile, 2FA, passkey) + role CRUD + admin impersonation
- Granit.Identity.Local.Notifications 9 security notifications (welcome, password reset, 2FA, email change, impersonation)
- Granit.Identity.Local.Privacy Personal-data export provider for the local identity store
- Granit.Identity.Endpoints Minimal API endpoints (provider CRUD, user cache sync, GDPR, webhook)
| Package | Role | Depends on |
|---|---|---|
Granit.Identity | Abstractions, null defaults | — |
Granit.Identity.Federated | Federated identity abstractions | Granit.Identity |
Granit.Identity.Federated.Keycloak | Keycloak Admin API implementation (+ realm-vs-client role distinction) | Granit.Identity.Federated |
Granit.Identity.Federated.EntraId | Microsoft Graph API implementation (+ App Role boot-time sync) | Granit.Identity.Federated |
Granit.Identity.Federated.Cognito | AWS Cognito User Pool API implementation | Granit.Identity.Federated |
Granit.Identity.Federated.GoogleCloud | Firebase Auth implementation (Firebase Admin SDK) | Granit.Identity.Federated |
Granit.Authentication.JwtBearer.GoogleCloud | JWT Bearer for Firebase Auth + claims transformation | Granit.Authentication.JwtBearer |
Granit.Identity.Federated.EntityFrameworkCore | EF Core user cache | Granit.Identity.Federated, Granit.Persistence |
Granit.Identity.Federated.Privacy | Personal-data export provider for the federated user cache | Granit.Identity.Federated, Granit.Privacy.BlobStorage |
Granit.Identity.Local | Shared domain types for self-hosted identity providers | Granit.Identity, Granit.Events, Granit.Guids, Granit.Settings, Granit.Timing |
Granit.Identity.Local.AspNetIdentity | ASP.NET Core Identity provider, role orchestration, tenant-aware role lookup | Granit.Identity.Local, Granit.Persistence.EntityFrameworkCore |
Granit.Identity.Local.Endpoints | Account self-service + role CRUD + admin impersonation REST endpoints | Granit.Identity.Local, Granit.Authorization |
Granit.Identity.Local.Notifications | 9 security email/in-app notifications (17 cultures) | Granit.Identity.Local, Granit.Notifications.Abstractions, Granit.Templating |
Granit.Identity.Local.Privacy | Personal-data export provider for the local identity store | Granit.Identity.Local, Granit.Privacy.BlobStorage |
Granit.Identity.Endpoints | REST endpoints for user cache + provider CRUD + GDPR | Granit.Identity, Granit.Authorization |
Dependency graph
Section titled “Dependency graph”graph TD
I[Granit.Identity] --> C[Granit]
IF[Granit.Identity.Federated] --> I
IK[Granit.Identity.Federated.Keycloak] --> IF
IEI[Granit.Identity.Federated.EntraId] --> IF
IC[Granit.Identity.Federated.Cognito] --> IF
IGC[Granit.Identity.Federated.GoogleCloud] --> IF
AGC[Granit.Authentication.JwtBearer.GoogleCloud] --> JB[Granit.Authentication.JwtBearer]
IEF[Granit.Identity.Federated.EntityFrameworkCore] --> IF
IEF --> P[Granit.Persistence]
IFP[Granit.Identity.Federated.Privacy] --> IF
IFP --> PR[Granit.Privacy.BlobStorage]
IL[Granit.Identity.Local] --> I
IL --> S[Granit.Settings]
ILA[Granit.Identity.Local.AspNetIdentity] --> IL
ILE[Granit.Identity.Local.Endpoints] --> IL
ILE --> AZ[Granit.Authorization]
ILN[Granit.Identity.Local.Notifications] --> IL
ILN --> N[Granit.Notifications.Abstractions]
ILN --> T[Granit.Templating]
ILP[Granit.Identity.Local.Privacy] --> IL
ILP --> PR
IE[Granit.Identity.Endpoints] --> I
IE --> AZ
[DependsOn(typeof(GranitIdentityFederatedKeycloakModule))][DependsOn(typeof(GranitIdentityFederatedEntityFrameworkCoreModule))][DependsOn(typeof(GranitIdentityEndpointsModule))]public class AppModule : GranitModule{ public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddGranitIdentityEntityFrameworkCore<AppDbContext>(); context.Services.AddGranitIdentityEndpoints(); }
public override void OnApplicationInitialization(ApplicationInitializationContext context) { context.App.MapGranitIdentityUserCache(); }}[DependsOn(typeof(GranitIdentityFederatedCognitoModule))][DependsOn(typeof(GranitIdentityFederatedEntityFrameworkCoreModule))][DependsOn(typeof(GranitIdentityEndpointsModule))]public class AppModule : GranitModule{ public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddGranitIdentityEntityFrameworkCore<AppDbContext>(); context.Services.AddGranitIdentityEndpoints(); }
public override void OnApplicationInitialization(ApplicationInitializationContext context) { context.App.MapGranitIdentityUserCache(); }}[DependsOn(typeof(GranitIdentityFederatedGoogleCloudModule))][DependsOn(typeof(GranitAuthenticationJwtBearerGoogleCloudModule))][DependsOn(typeof(GranitIdentityFederatedEntityFrameworkCoreModule))][DependsOn(typeof(GranitIdentityEndpointsModule))]public class AppModule : GranitModule{ public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddGranitIdentityEntityFrameworkCore<AppDbContext>(); context.Services.AddGranitIdentityEndpoints(); }
public override void OnApplicationInitialization(ApplicationInitializationContext context) { context.App.MapGranitIdentityUserCache(); }}[DependsOn(typeof(GranitIdentityModule))]public class AppModule : GranitModule { }Registers NullIdentityProvider and NullUserLookupService — useful for development
or modules that only need the interfaces.
context.Services.AddIdentityProvider<MyCustomIdentityProvider>();Interface Segregation
Section titled “Interface Segregation”IIdentityProvider is a composite interface built from 7 fine-grained interfaces
following ISP (Interface Segregation Principle). Inject only what you need:
| Interface | Methods | Purpose |
|---|---|---|
IIdentityUserReader | GetUsersAsync, GetUserAsync | Read user profiles |
IIdentityUserWriter | CreateUserAsync, UpdateUserAsync, SetUserEnabledAsync | Mutate user profiles |
IIdentityRoleManager | GetRolesAsync, GetUserRolesAsync, AssignRoleAsync, RemoveRoleAsync, GetRoleMembersAsync | Role assignments |
IIdentityGroupManager | GetGroupsAsync, GetUserGroupsAsync, AddUserToGroupAsync, RemoveUserFromGroupAsync | Group membership |
IIdentitySessionManager | GetUserSessionsAsync, GetUserDeviceActivityAsync, TerminateSessionAsync, TerminateAllSessionsAsync | Active session control |
IIdentityPasswordManager | GetPasswordChangedAtAsync, SendPasswordResetEmailAsync, SetTemporaryPasswordAsync | Password operations |
IIdentityCredentialVerifier | VerifyUserCredentialsAsync | Credential validation |
// Inject only what you need — not the full IIdentityProviderpublic class UserProfileService(IIdentityUserReader userReader){ public async Task<IdentityUser?> GetProfileAsync( string userId, CancellationToken cancellationToken) { return await userReader.GetUserAsync(userId, cancellationToken) .ConfigureAwait(false); }}Provider capabilities
Section titled “Provider capabilities”Not all providers support every operation. Query capabilities at runtime:
public class SessionService( IIdentitySessionManager sessions, IIdentityProviderCapabilities capabilities){ public async Task TerminateSessionAsync( string userId, string sessionId, CancellationToken cancellationToken) { if (!capabilities.SupportsIndividualSessionTermination) { throw new BusinessException( "Identity:UnsupportedOperation", "Provider does not support individual session termination"); }
await sessions.TerminateSessionAsync(userId, sessionId, cancellationToken) .ConfigureAwait(false); }}User cache (cache-aside)
Section titled “User cache (cache-aside)”Granit.Identity.Federated.EntityFrameworkCore maintains a local cache of user data from the
identity provider. This avoids hitting Keycloak on every “who is this user?” query.
IUserLookupService
Section titled “IUserLookupService”public interface IUserLookupService{ Task<UserCacheEntry?> FindByIdAsync(string userId, CancellationToken cancellationToken); Task<IReadOnlyList<UserCacheEntry>> FindByIdsAsync( IReadOnlyCollection<string> userIds, CancellationToken cancellationToken); Task<PagedResult<UserCacheEntry>> SearchAsync( string searchTerm, int page, int pageSize, CancellationToken cancellationToken); Task RefreshByIdAsync(string userId, CancellationToken cancellationToken); Task RefreshAllAsync(CancellationToken cancellationToken); Task RefreshStaleAsync(CancellationToken cancellationToken); Task DeleteByIdAsync(string userId, CancellationToken cancellationToken); Task PseudonymizeByIdAsync(string userId, CancellationToken cancellationToken);}Cache-aside strategy
Section titled “Cache-aside strategy”sequenceDiagram
participant App
participant Cache as UserLookupService
participant DB as EF Core
participant IDP as Keycloak
App->>Cache: FindByIdAsync("user-123")
Cache->>DB: SELECT WHERE ExternalUserId = "user-123"
alt Cache hit (fresh)
DB-->>Cache: UserCacheEntry
Cache-->>App: UserCacheEntry
else Cache miss or stale
Cache->>IDP: GetUserAsync("user-123")
IDP-->>Cache: IdentityUser
Cache->>DB: INSERT/UPDATE UserCacheEntry
Cache-->>App: UserCacheEntry
end
Entity
Section titled “Entity”public class UserCacheEntry : AuditedEntity, IMultiTenant{ public string ExternalUserId { get; set; } = string.Empty; public string? Username { get; set; } public string? Email { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } public bool Enabled { get; set; } public DateTimeOffset? LastSyncedAt { get; set; } public Guid? TenantId { get; set; }}Login-time sync
Section titled “Login-time sync”UserCacheSyncMiddleware automatically refreshes the cache entry when a user
authenticates. This ensures the cache stays fresh without polling.
Configuration
Section titled “Configuration”{ "IdentityUserCache": { "StalenessThreshold": "1.00:00:00", "EnableLoginTimeSync": true, "IncrementalSyncBatchSize": 50 }}| Property | Default | Description |
|---|---|---|
StalenessThreshold | 24:00:00 | Age after which a cache entry is considered stale |
EnableLoginTimeSync | true | Refresh cache on login |
IncrementalSyncBatchSize | 50 | Batch size for RefreshStaleAsync |
Keycloak provider
Section titled “Keycloak provider”Granit.Identity.Federated.Keycloak implements the full IIdentityProvider against the
Keycloak Admin REST API.
Configuration
Section titled “Configuration”{ "KeycloakAdmin": { "BaseUrl": "https://keycloak.example.com", "Realm": "my-realm", "ClientId": "admin-cli", "ClientSecret": "secret", "TimeoutSeconds": 30, "UseTokenExchangeForDeviceActivity": false, "DirectAccessClientId": "direct-access-client" }}Required Keycloak service account roles:
realm-management:view-usersrealm-management:manage-users
Health check
Section titled “Health check”builder.Services.AddHealthChecks() .AddGranitKeycloakHealthCheck();Verifies Keycloak connectivity by requesting a client_credentials token. Tagged
["readiness", "startup"]. Returns Unhealthy on 401/403, Degraded on 5xx.
OpenTelemetry
Section titled “OpenTelemetry”All Keycloak Admin API calls are traced via IdentityKeycloakActivitySource.
Activity names follow the pattern Granit.Identity.Keycloak.{Operation}.
Cognito provider
Section titled “Cognito provider”Granit.Identity.Federated.Cognito implements the full IIdentityProvider against the
AWS Cognito User Pool API via AWSSDK.CognitoIdentityProvider.
Configuration
Section titled “Configuration”{ "CognitoAdmin": { "UserPoolId": "eu-west-1_XXXXXXXXX", "Region": "eu-west-1", "AccessKeyId": "", "SecretAccessKey": "", "TimeoutSeconds": 30 }}AccessKeyId and SecretAccessKey are optional — when omitted, the SDK uses the
default credential chain (IAM role, environment variables, ~/.aws/credentials).
Cognito-specific behavior
Section titled “Cognito-specific behavior”- Groups as roles — Cognito has no native “roles” concept. Groups serve as both
roles and groups.
GetRolesAsyncandGetGroupsAsyncreturn the same data. - No individual session termination — Cognito supports
AdminUserGlobalSignOut(terminate all sessions) but not individual session termination.IIdentityProviderCapabilities.SupportsIndividualSessionTerminationreturnsfalse. - No device activity —
GetUserDeviceActivityAsyncreturns an empty list.
OpenTelemetry
Section titled “OpenTelemetry”All Cognito User Pool API calls are traced via IdentityCognitoActivitySource.
Activity names follow the pattern cognito.{operation}.
Google Cloud Identity Platform provider
Section titled “Google Cloud Identity Platform provider”Granit.Identity.Federated.GoogleCloud implements the full IIdentityProvider against the
Firebase Auth API via Firebase Admin SDK v3.
Configuration
Section titled “Configuration”{ "Identity": { "GoogleCloud": { "ProjectId": "my-firebase-project", "RolesClaimKey": "roles", "TimeoutSeconds": 30 } }}For Workload Identity (recommended in GKE), omit CredentialFilePath —
Application Default Credentials are used automatically.
Google Cloud-specific behavior
Section titled “Google Cloud-specific behavior”- Roles via custom claims — Firebase Auth has no native roles. User roles are
stored as a JSON array in custom claims (configurable key, default
"roles").GetRolesAsyncreturns an empty list;GetUserRolesAsyncextracts from claims. - Groups not supported — Firebase Auth does not support groups.
AddUserToGroupAsyncandRemoveUserFromGroupAsyncthrowNotSupportedException. - No individual session termination — Firebase supports
RevokeRefreshTokens(terminate all sessions) but not individual session termination.IIdentityProviderCapabilities.SupportsIndividualSessionTerminationreturnsfalse. - Credential verification —
VerifyUserCredentialsAsyncvalidates email/password via the Firebase Auth REST API.
Health check
Section titled “Health check”builder.Services.AddHealthChecks() .AddGranitGoogleCloudIdentityHealthCheck();Verifies that ProjectId is configured. Tagged ["readiness"].
OpenTelemetry
Section titled “OpenTelemetry”All Firebase Auth API calls are traced via IdentityGoogleCloudActivitySource.
Activity names follow the pattern firebase.{operation}.
Google Cloud Authentication
Section titled “Google Cloud Authentication”Granit.Authentication.JwtBearer.GoogleCloud configures JWT Bearer authentication for
Firebase Auth tokens and transforms custom claims into standard ClaimTypes.Role.
Configuration
Section titled “Configuration”{ "GoogleCloudAuth": { "ProjectId": "my-firebase-project", "RequireHttpsMetadata": true, "AdminRole": "admin", "RolesClaimKey": "roles" }}| Property | Default | Description |
|---|---|---|
ProjectId | — | GCP project ID (derives OIDC authority) |
RequireHttpsMetadata | true | Require HTTPS for OIDC metadata discovery |
AdminRole | "admin" | Role name for the “Admin” authorization policy |
RolesClaimKey | "roles" | Custom claims key containing roles |
The module derives the OIDC authority as https://securetoken.google.com/{ProjectId}
and configures JWT Bearer validation with Audience = ProjectId,
NameClaimType = "email".
Claims transformation
Section titled “Claims transformation”GoogleCloudClaimsTransformation maps Firebase custom claims to
ClaimTypes.Role. Supports JSON array format (["admin","editor"]) and
single string values. Existing ClaimTypes.Role claims are preserved without
duplication.
Endpoints
Section titled “Endpoints”Granit.Identity.Endpoints exposes user cache management as Minimal API endpoints.
| Method | Route | Permission | Description |
|---|---|---|---|
| GET | /identity/users/search | Identity.UserCache.Read | Search cached users |
| GET | /identity/users/{id} | Identity.UserCache.Read | Get by external ID |
| POST | /identity/users/batch | Identity.UserCache.Read | Batch resolve by IDs |
| POST | /identity/users/sync | Identity.UserCache.Sync | Sync specific user |
| POST | /identity/users/sync-all | Identity.UserCache.Sync | Full sync from provider |
| DELETE | /identity/users/{id} | Identity.UserCache.Delete | GDPR erase |
| PATCH | /identity/users/{id}/pseudonymize | Identity.UserCache.Delete | GDPR pseudonymize |
| GET | /identity/users/stats | Identity.UserCache.Read | Cache statistics |
| GET | /identity/users/capabilities | Identity.UserCache.Read | Provider capabilities |
| POST | /identity-webhook | (anonymous, signature-validated) | IdP webhook receiver |
Webhook
Section titled “Webhook”The webhook endpoint receives events from the identity provider (user created, updated, deleted) and updates the local cache accordingly.
Payload authenticity is verified via HMAC-SHA256 signature validation using the shared
secret configured in IdentityWebhookOptions.
GDPR operations
Section titled “GDPR operations”Two operations support data subject rights:
// Right to erasure (Art. 17) — hard deleteawait userLookupService.DeleteByIdAsync("user-123", cancellationToken) .ConfigureAwait(false);
// Right to restriction (Art. 18) — pseudonymizeawait userLookupService.PseudonymizeByIdAsync("user-123", cancellationToken) .ConfigureAwait(false);- Delete removes the
UserCacheEntryentirely (physical delete, not soft delete) - Pseudonymize replaces PII fields with anonymized values while preserving the record
Both operations emit Wolverine domain events (IdentityUserDeletedEvent,
IdentityUserUpdatedEvent) for downstream modules to react.
Security notifications
Section titled “Security notifications”Granit.Identity.Local.Notifications provides 9 out-of-the-box email and in-app
notifications for local identity management. Wolverine event handlers listen to
identity lifecycle events and dispatch notifications via Granit.Notifications.
| Notification | Channels | Opt-out | Trigger |
|---|---|---|---|
Security.Welcome | Yes | User registration | |
Security.PasswordReset | No | Forgot password flow | |
Security.EmailConfirmation | No | Registration / resend | |
Security.PasswordChanged | No | Password change (compromise alert) | |
Security.AccountLocked | Email, InApp | No | Failed login attempts (includes password reset link for self-service unlock) |
Security.TwoFactorChanged | No | 2FA enabled/disabled | |
Security.EmailChangeAlert | No | Email change alert (old address) | |
Security.EmailChangeConfirmation | No | Email change confirm (new address) | |
Security.ImpersonationAlert | Email, InApp | No | Admin impersonation (GDPR/SOC2) |
[DependsOn(typeof(GranitIdentityLocalNotificationsModule))]public class AppModule : GranitModule { }{ "Identity": { "Notifications": { "FrontendBaseUrl": "https://app.example.com", "ResetPasswordPath": "reset-password", "ConfirmEmailPath": "confirm-email", "ChangeEmailPath": "confirm-email-change" } }}Templates are embedded in the package (9 types x 18 cultures) and wrapped by
Layout.Email via the layout registry. Tenants can override any template or
the layout via the database template store.
Account lockout notification
Section titled “Account lockout notification”The Security.AccountLocked notification is sent when a user’s account is locked
after exceeding the maximum number of failed login attempts. The email includes:
- The number of failed attempts that triggered the lockout
- The exact lockout expiry date (formatted per the user’s locale via Scriban)
- A “Reset my password” button with a one-time reset token
Resetting the password via this link immediately unlocks the account and resets the exponential backoff counter — the user never needs to wait or contact support.
See Account lockout for the complete lockout security architecture.
Email change flow
Section titled “Email change flow”Email change triggers two notifications from a single EmailChangeRequestedEto event:
Security.EmailChangeAlert→ sent to the current email (security alert)Security.EmailChangeConfirmation→ sent to the new email (usesRecipientOverride)
The confirmation token is generated by ASP.NET Core Identity and encodes the new email — no additional database column is needed.
Federated identity notifications
Section titled “Federated identity notifications”Granit.Identity.Federated.Notifications ships notifications surfacing
federated-provider lifecycle events (Keycloak / Entra ID / Cognito / Firebase).
Tenants opt in via the notifications admin UI.
| Notification | Trigger | Channels | Severity |
|---|---|---|---|
identity.sync_failed | IdentityUserSyncFailedEto — login-time user-cache sync from the federated provider failed | Email, InApp | Warning |
identity.token_exchange_audit | IdentityTokenExchangedEto — token exchange completed (audit trail of who acted on whose behalf) | Email, InApp | Warning |
identity.user_provisioning_removed | IdentityUserDeletedEto — federated user removed from the provider; cache entry deprovisioned | Email, InApp | Info |
Email templates ship in EN + FR; additional cultures are produced via the translation script (US #1311).
Public API summary
Section titled “Public API summary”| Category | Key types | Package |
|---|---|---|
| Module | GranitIdentityModule, GranitIdentityFederatedModule, GranitIdentityFederatedKeycloakModule, GranitIdentityFederatedCognitoModule, GranitIdentityFederatedGoogleCloudModule, GranitAuthenticationJwtBearerGoogleCloudModule, GranitIdentityFederatedEntityFrameworkCoreModule, GranitIdentityEndpointsModule, GranitIdentityLocalAspNetIdentityModule | — |
| Abstractions | IIdentityProvider, IIdentityUserReader, IIdentityUserWriter, IIdentityRoleManager, IIdentityGroupManager, IIdentitySessionManager, IIdentityPasswordManager, IIdentityCredentialVerifier | Granit.Identity |
| Lookup | IUserLookupService, IUserCacheStats, IIdentityProviderCapabilities | Granit.Identity |
| Models | IdentityUser, IdentityUserCreate, IdentityUserUpdate, IdentityRole, IdentityGroup, IdentitySession, IdentityDeviceActivity | Granit.Identity |
| Keycloak | KeycloakIdentityProvider, KeycloakAdminOptions | Granit.Identity.Federated.Keycloak |
| Cognito | CognitoIdentityProvider, CognitoAdminOptions | Granit.Identity.Federated.Cognito |
| Google Cloud | GoogleCloudIdentityProvider, GoogleCloudIdentityOptions | Granit.Identity.Federated.GoogleCloud |
| Google Cloud Auth | GoogleCloudClaimsTransformation, GoogleCloudAuthenticationOptions | Granit.Authentication.JwtBearer.GoogleCloud |
| EF Core | UserCacheEntry, IUserCacheDbContext, UserCacheOptions | Granit.Identity.Federated.EntityFrameworkCore |
| Endpoints | IdentityEndpointsOptions, IdentityWebhookOptions | Granit.Identity.Endpoints |
| Notifications | WelcomeNotificationType, PasswordResetNotificationType, EmailConfirmationNotificationType, PasswordChangedNotificationType, AccountLockedNotificationType, TwoFactorChangedNotificationType, EmailChangeAlertNotificationType, EmailChangeConfirmationNotificationType, ImpersonationAlertNotificationType | Granit.Identity.Local.Notifications |
| Notifications options | IdentityNotificationOptions | Granit.Identity.Local.Notifications |
| Events | PasswordChangedEto, AccountLockedEto (includes LockoutEndUtc + ResetToken), TwoFactorChangedEto, EmailConfirmationRequestedEto, EmailChangeRequestedEto | Granit.Identity.Local |
| Extensions | AddGranitIdentity(), AddIdentityProvider<T>(), AddGranitIdentityKeycloak(), AddGranitIdentityCognito(), AddGranitIdentityGoogleCloud(), AddGranitGoogleCloudAuthentication(), AddGranitIdentityEntityFrameworkCore<T>(), AddGranitIdentityEndpoints(), MapGranitIdentityUserCache() | — |
See also
Section titled “See also”- Security module — Authentication, authorization, RBAC permissions
- Privacy module — GDPR data export/deletion, cookie consent
- Persistence module —
AuditedEntity, interceptors - API Reference (auto-generated from XML docs)