Overview
The Identity module provides comprehensive authentication and authorization features built on ASP.NET Core Identity. It handles users, roles, permissions, groups, and sessions with JWT-based authentication.
Module Order: 100 (loads first)
API Base Path: /api/v1/identity
Core Features
Users Registration, profiles, status management, and password policies
Roles & Permissions Role-based access control with granular permissions
Groups User groups with inherited permissions
Sessions JWT token management with refresh and revocation
Implementation
The module is defined in IdentityModule.cs (identity/Modules.Identity):
namespace FSH . Modules . Identity ;
public class IdentityModule : IModule
{
public void ConfigureServices ( IHostApplicationBuilder builder )
{
var services = builder . Services ;
// Current user context
services . AddScoped < ICurrentUserService , CurrentUserService >();
services . AddScoped < ICurrentUser >( sp => sp . GetRequiredService < ICurrentUserService >());
// User services - single-responsibility pattern
services . AddTransient < IUserRegistrationService , UserRegistrationService >();
services . AddTransient < IUserProfileService , UserProfileService >();
services . AddTransient < IUserStatusService , UserStatusService >();
services . AddTransient < IUserRoleService , UserRoleService >();
services . AddTransient < IUserPasswordService , UserPasswordService >();
services . AddTransient < IUserPermissionService , UserPermissionService >();
// Role and token services
services . AddTransient < IRoleService , RoleService >();
services . AddTransient < ITokenService , TokenService >();
// Password policy and history
services . Configure < PasswordPolicyOptions >( builder . Configuration . GetSection ( "PasswordPolicy" ));
services . AddScoped < IPasswordHistoryService , PasswordHistoryService >();
services . AddScoped < IPasswordExpiryService , PasswordExpiryService >();
// Session management
services . AddScoped < ISessionService , SessionService >();
services . AddHostedService < SessionCleanupHostedService >();
// Groups and group-derived permissions
services . AddScoped < IGroupRoleService , GroupRoleService >();
// Database and eventing
services . AddHeroDbContext < IdentityDbContext >();
services . AddEventingCore ( builder . Configuration );
services . AddEventingForDbContext < IdentityDbContext >();
// ASP.NET Core Identity
services . AddIdentity < FshUser , FshRole >( options =>
{
options . Password . RequiredLength = 8 ;
options . Password . RequireDigit = false ;
options . Password . RequireLowercase = false ;
options . Password . RequireNonAlphanumeric = false ;
options . Password . RequireUppercase = false ;
options . User . RequireUniqueEmail = true ;
})
. AddEntityFrameworkStores < IdentityDbContext >()
. AddDefaultTokenProviders ();
// JWT authentication
services . ConfigureJwtAuth ();
// Health checks
services . AddHealthChecks ()
. AddDbContextCheck < IdentityDbContext >(
name : "db:identity" ,
failureStatus : HealthStatus . Unhealthy );
}
public void MapEndpoints ( IEndpointRouteBuilder endpoints )
{
var apiVersionSet = endpoints . NewApiVersionSet ()
. HasApiVersion ( new ApiVersion ( 1 ))
. ReportApiVersions ()
. Build ();
var group = endpoints
. MapGroup ( "api/v{version:apiVersion}/identity" )
. WithTags ( "Identity" )
. WithApiVersionSet ( apiVersionSet );
// Map all endpoints...
}
}
User Management
User Endpoints
Method Endpoint Description Permission POST/users/registerAdmin user registration Users.CreatePOST/users/self-registerPublic self-registration Anonymous GET/usersList all users Users.ViewGET/users/searchSearch users Users.ViewGET/users/{id}Get user by ID Users.ViewGET/users/meGet current user profile Authenticated PUT/users/{id}Update user Users.UpdateDELETE/users/{id}Delete user Users.DeletePOST/users/{id}/toggle-statusActivate/deactivate Users.UpdatePOST/users/{id}/change-passwordChange password Users.UpdatePOST/users/{id}/reset-passwordReset password Users.UpdateGET/users/{id}/permissionsGet user permissions Users.View
User Services
The module uses specialized services following single-responsibility principle:
User Registration
User Profile
Password Management
public interface IUserRegistrationService
{
Task < string > RegisterAsync (
string email ,
string userName ,
string password ,
string ? firstName ,
string ? lastName ,
string ? phoneNumber ,
CancellationToken cancellationToken );
}
Roles & Permissions
Role Endpoints
Method Endpoint Description Permission GET/rolesList all roles Roles.ViewGET/roles/{id}Get role by ID Roles.ViewGET/roles/{id}/permissionsGet role permissions Roles.ViewPOST/rolesCreate or update role Roles.CreatePUT/roles/{id}/permissionsUpdate permissions Roles.UpdateDELETE/roles/{id}Delete role Roles.Delete
User-Role Association
Method Endpoint Description Permission GET/users/{id}/rolesGet user’s roles Users.ViewPOST/users/{id}/rolesAssign roles to user Users.Update
Permission System
Endpoints use .RequirePermission() for authorization:
group . MapGetUsersListEndpoint ()
. WithName ( "ListUsers" )
. WithSummary ( "List users" )
. RequirePermission ( IdentityPermissionConstants . Users . View );
Permission constants (identity/Contracts/v1):
public static class IdentityPermissionConstants
{
public static class Users
{
public const string View = "Permissions.Identity.Users.View" ;
public const string Create = "Permissions.Identity.Users.Create" ;
public const string Update = "Permissions.Identity.Users.Update" ;
public const string Delete = "Permissions.Identity.Users.Delete" ;
}
public static class Roles
{
public const string View = "Permissions.Identity.Roles.View" ;
public const string Create = "Permissions.Identity.Roles.Create" ;
public const string Update = "Permissions.Identity.Roles.Update" ;
public const string Delete = "Permissions.Identity.Roles.Delete" ;
}
}
Groups allow organizing users and assigning permissions at the group level.
Group Endpoints
Method Endpoint Description Permission GET/groupsList all groups Groups.ViewGET/groups/{id}Get group by ID Groups.ViewPOST/groupsCreate group Groups.CreatePUT/groups/{id}Update group Groups.UpdateDELETE/groups/{id}Delete group Groups.DeleteGET/groups/{id}/membersGet group members Groups.ViewPOST/groups/{id}/membersAdd users to group Groups.UpdateDELETE/groups/{id}/members/{userId}Remove user from group Groups.UpdateGET/users/{id}/groupsGet user’s groups Users.View
Group-Derived Permissions
Users inherit permissions from their groups via IGroupRoleService:
public interface IGroupRoleService
{
Task < IEnumerable < string >> GetGroupPermissionsAsync (
string userId ,
CancellationToken cancellationToken );
}
Sessions
Session management provides JWT token tracking and revocation.
User Session Endpoints
Method Endpoint Description GET/sessions/myGet current user’s sessions DELETE/sessions/{id}Revoke a session DELETE/sessionsRevoke all sessions
Admin Session Endpoints
Method Endpoint Description Permission GET/users/{id}/sessionsGet user’s sessions Users.ViewDELETE/users/{id}/sessions/{sessionId}Revoke user session Users.UpdateDELETE/users/{id}/sessionsRevoke all user sessions Users.Update
Session Cleanup
Expired sessions are automatically cleaned up by SessionCleanupHostedService:
services . AddScoped < ISessionService , SessionService >();
services . AddHostedService < SessionCleanupHostedService >();
Authentication
Token Endpoints
Method Endpoint Description Rate Limited POST/tokensGenerate access token Yes POST/tokens/refreshRefresh access token Yes
JWT Configuration
Configure JWT options in appsettings.json:
{
"JwtOptions" : {
"Issuer" : "fullstackhero" ,
"Audience" : "fullstackhero-api" ,
"SigningKey" : "your-256-bit-secret-key-min-32-chars" ,
"AccessTokenMinutes" : 30 ,
"RefreshTokenDays" : 7
}
}
The SigningKey must be at least 32 characters long. Never commit secrets to source control.
JWT Options Model
public class JwtOptions : IValidatableObject
{
public string Issuer { get ; init ; } = string . Empty ;
public string Audience { get ; init ; } = string . Empty ;
public string SigningKey { get ; init ; } = string . Empty ;
public int AccessTokenMinutes { get ; init ; } = 30 ;
public int RefreshTokenDays { get ; init ; } = 7 ;
}
Password Policy
Enforce password history and expiry policies.
Configuration
{
"PasswordPolicy" : {
"PasswordHistoryCount" : 5 ,
"PasswordExpiryDays" : 90 ,
"PasswordExpiryWarningDays" : 14 ,
"EnforcePasswordExpiry" : true
}
}
Password Policy Options
public class PasswordPolicyOptions
{
/// < summary > Number of previous passwords to keep in history (prevent reuse) </ summary >
public int PasswordHistoryCount { get ; set ; } = 5 ;
/// < summary > Number of days before password expires and must be changed </ summary >
public int PasswordExpiryDays { get ; set ; } = 90 ;
/// < summary > Number of days before expiry to show warning to user </ summary >
public int PasswordExpiryWarningDays { get ; set ; } = 14 ;
/// < summary > Set to false to disable password expiry enforcement </ summary >
public bool EnforcePasswordExpiry { get ; set ; } = true ;
}
Services
Password History
Password Expiry
public interface IPasswordHistoryService
{
Task < bool > IsPasswordInHistoryAsync (
string userId ,
string password ,
CancellationToken cancellationToken );
Task AddPasswordToHistoryAsync (
string userId ,
string passwordHash ,
CancellationToken cancellationToken );
}
Email Confirmation
Method Endpoint Description Rate Limited POST/users/confirm-emailConfirm email address Yes
Database Context
The module uses IdentityDbContext for persistence:
public class IdentityDbContext : DbContext
{
public DbSet < FshUser > Users { get ; set ; }
public DbSet < FshRole > Roles { get ; set ; }
public DbSet < IdentityUserRole < string >> UserRoles { get ; set ; }
public DbSet < IdentityUserClaim < string >> UserClaims { get ; set ; }
public DbSet < IdentityRoleClaim < string >> RoleClaims { get ; set ; }
public DbSet < Group > Groups { get ; set ; }
public DbSet < GroupMember > GroupMembers { get ; set ; }
public DbSet < Session > Sessions { get ; set ; }
public DbSet < PasswordHistory > PasswordHistory { get ; set ; }
}
The Identity module publishes integration events for cross-module communication:
UserRegisteredEvent
UserDeletedEvent
UserStatusChangedEvent
RoleCreatedEvent
RolePermissionsUpdatedEvent
services . AddEventingCore ( builder . Configuration );
services . AddEventingForDbContext < IdentityDbContext >();
services . AddIntegrationEventHandlers ( typeof ( IdentityModule ). Assembly );
Metrics
The module includes Prometheus-compatible metrics:
services . AddSingleton < IdentityMetrics >();
Metrics tracked:
User registrations
Login attempts (success/failure)
Token generations
Password changes
Next Steps
Multitenancy Module Learn about tenant isolation and provisioning
Creating Modules Build your own custom modules