A set of libraries to easily integrate and extend authentication in ASP.NET Core projects, using ASP.NET Core Identity.
$ dotnet add package Identity.Module.APIA set of libraries to easily integrate and extend authentication in ASP.NET Core projects, using ASP.NET Core Identity.
MinimalApi.Identity is a dynamic and modular identity manager for managing users, roles, claims and more for access control in Asp.Net Mvc Core and Web API, using .NET 8 Minimal API, Entity Framework Core and relational database (of your choice).
[!IMPORTANT] This library is still under development of new implementations and in the process of creating the related documentation.
appsettings.json to suit your application's needs.As an alternative to SQL Server you can use one of these databases:
The library is available on NuGet, just search for Identity.Module.API in the Package Manager GUI or run the following command in the .NET CLI:
dotnet add package Identity.Module.APIThe configuration can be completely managed by adding this section to the appsettings.json file:
[!WARNING] The library is still under development, so the configuration may change in future updates.
"Kestrel": {
"Limits": {
"MaxRequestBodySize": 5242880
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Warning",
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:HH:mm:ss}\t{Level:u3}\t{SourceContext}\t{Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7,
"restrictedToMinimumLevel": "Warning",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"
}
}
// The custom MinioS3Sink sink must be added via code (not here)
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "MinimalApi.Identity"
}
},
"ConnectionStrings": {
"AzureSQL": "Server=tcp:[SERVER].database.windows.net,1433;Initial Catalog=IdentityManager;Persist Security Info=False;User ID=[USERNAME];Password=[PASSWORD];MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;",
"MySQL": "Server=[HOSTNAME];Port=3306;Database=IdentityManager;Uid=[USERNAME];Pwd=[PASSWORD]",
"PostgreSQL": "Host=[HOSTNAME];Port=5432;Database=IdentityManager;Username=[USERNAME];Password=[PASSWORD];Include Error Detail=true",
"SQLite": "Data Source=Data/IdentityManager.db", // OR "SQLite": "Data Source=MinimalApi.Identity.db;Cache=Shared"
"SQLServer": "Data Source=[HOSTNAME];Initial Catalog=IdentityManager;User ID=[USERNAME];Password=[PASSWORD];Encrypt=False"
},
"JwtOptions": {
"Issuer": "[ISSUER]",
"Audience": "[AUDIENCE]",
"SecurityKey": "[SECURITY-KEY]", // Must be 512 characters long
"ClockSkew": "00:05:00",
"AccessTokenExpirationMinutes": 60,
"RefreshTokenExpirationMinutes": 60,
"RequireUniqueEmail": true,
"RequireDigit": true,
"RequiredLength": 8,
"RequireUppercase": true,
"RequireLowercase": true,
"RequireNonAlphanumeric": true,
"RequiredUniqueChars": 4,
"RequireConfirmedEmail": true,
"MaxFailedAccessAttempts": 3,
"AllowedForNewUsers": true,
"DefaultLockoutTimeSpan": "00:05:00"
},
"SmtpOptions": {
"Host": "smtp.example.org",
"Port": 25,
"Security": "StartTls",
"Username": "Username del server SMTP",
"Password": "Password del server SMTP",
"Sender": "MyApplication <noreply@example.org>",
"MaxRetryAttempts": 10
},
"AppSettings": {
"DatabaseType": "sqlserver",
"MigrationsAssembly": "MinimalApi.Identity.Migrations.SQLServer",
"AssignAdminUsername": "admin",
"AssignAdminEmail": "admin@example.org",
"AssignAdminPassword": "StrongPassword",
"PasswordExpirationDays": 90,
"IntervalEmailSenderMinutes": 5,
"ErrorResponseFormat": "List",
"EnabledFeatureLicense": true,
"EnabledFeatureModule": true,
"ValidateMinLength": 3,
"ValidateMaxLength": 50,
"ValidateMinLengthDescription": 5,
"ValidateMaxLengthDescription": 100
},
"SwaggerSettings": {
"IsEnabled": true,
"AuthSettings": {
"IsRequired": false,
"Username": "admin",
"Password": "StrongPassword"
}
},
"MinioOptions": {
"Endpoint": "http://127.0.0.1:9000",
"AccessKey": "",
"SecretKey": "",
"BucketName": "logs",
"LogObjectKey": "serilog-demo.json"
},
"CorsOptions": {
"PolicyName": "DefaultCorsPolicy",
"AllowAnyOrigin": true,
"AllowAnyMethod": true,
"AllowAnyHeader": true,
"AllowedOrigins": [],
"AllowedMethods": [],
"AllowedHeaders": []
}[!NOTE] For migrations you can use a specific project to add to your solution, then configuring the assembly in AppSettings:MigrationsAssembly, otherwise leave it blank and the assembly containing the Program.cs class will be used.
The library uses Entity Framework Core to manage the database.
The connection string is configured in the AppSettings section of the appsettings.json file.
AppSettings:DatabaseType (supported values: sqlserver, azuresql, postgresql, mysql, sqlite)After setting the type of database you want to use, modify the corresponding connection string.
[!TIP] To update the database schema you need to create migrations, they will be applied automatically at the next application startup.
To create database migrations select MinimalApi.Identity.Core as the default project from the drop-down menu in the Package Manager Console
and run the command: Add-Migration MIGRATION-NAME
Example: Add-Migration InitialMigration -Project MinimalApi.Identity.Migrations.SQLServer
[!NOTE] if you use a separate project for migrations (It is recommended to add a reference in the project name to the database used, in this case it is SQL Server), make sure to set the
-Projectparameter to the name of that project.
It is possible to protect access to the Swagger UI with the following configuration in SwaggerSettings:
AuthSettings:IsRequired (supported values: true, false)AuthSettings:UsernameAuthSettings:PasswordYou can manage the state of the Swagger UI with the following configuration:
SwaggerSettings:IsEnabled (supported values: true, false)[!WARNING] The library is still under development, so the Program.cs configuration may change in future updates.
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var minioOptions = builder.Services.ConfigureAndGet<MinioOptions>(builder.Configuration, nameof(MinioOptions)) ?? new MinioOptions();
builder.Host.UseSerilogToStorageCloud((context, services, config)
=> config.ReadFrom.Configuration(context.Configuration), minioOptions);
var appSettings = builder.Services.ConfigureAndGet<AppSettings>(builder.Configuration, nameof(AppSettings)) ?? new();
var jwtOptions = builder.Services.ConfigureAndGet<JwtOptions>(builder.Configuration, nameof(JwtOptions)) ?? new();
var swaggerSettings = builder.Services.ConfigureAndGet<SwaggerSettings>(builder.Configuration, nameof(SwaggerSettings)) ?? new();
var corsOptions = builder.Services.ConfigureAndGet<CorsOptions>(builder.Configuration, nameof(CorsOptions)) ?? new();
builder.Services.AddRegisterDefaultServices<MinimalApiAuthDbContext>(builder.Configuration, appSettings, jwtOptions);
//If you need to register services with a lifecycle other than Transient, do not modify this configuration,
//but create one (or more) duplicates of this configuration, modifying it as needed.
builder.Services.AddRegisterServices(options =>
{
options.Interfaces = [typeof(IAuthService)]; // Register your interfaces here, but do not remove the IAuthService service.
options.StringEndsWith = "Service"; // This will register all services that end with "Service" in the assembly.
options.Lifetime = ServiceLifetime.Transient; // This will register the services with a Transient lifetime.
});
builder.Services.AddAuthorization(options =>
{
options.AddDefaultSecurityOptions();
// Here you can add additional authorization policies
});
var app = builder.Build();
var activeModules = RegisterServicesExtensions.ReadFeatureFlags(appSettings);
var appName = app.Environment.ApplicationName;
await RegisterServicesExtensions.ConfigureDatabaseAsync(app.Services);
// If behind a proxy, uncomment and configure the KnownProxies collection
//app.UseForwardedHeaders(new()
//{
// ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
// KnownProxies = { }
//});
app.UseHttpsRedirection();
app.UseStatusCodePages();
app.UseMiddleware<MinimalApiExceptionMiddleware>();
if (swaggerSettings.IsEnabled)
{
if (swaggerSettings.AuthSettings.IsRequired)
{
app.UseMiddleware<SwaggerBasicAuthMiddleware>();
}
app.UseSwagger();
app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", $"{appName} v1"));
}
app.UseRouting();
app.UseCors(corsOptions.PolicyName);
app.UseAuthentication();
app.UseAuthorization();
app.UseMapEndpoints(activeModules);
await app.RunAsync();
}
}The following authentication types are currently supported:
A default administrator account is created automatically with the following configuration:
AppSettings:AssignAdminEmailAppSettings:AssignAdminUsernameAppSettings:AssignAdminPasswordThis project is licensed under the MIT License - see the LICENSE file for details.
Don't forget that if you find this project helpful, please give it a ⭐ on GitHub to show your support and help others discover it.
The project is constantly evolving. Contributions are always welcome. Feel free to report issues and submit pull requests to the repository, following the steps below:
If you have any questions or need help, read here to find out what to do.