Skip to content

A set of libraries to easily integrate and extend authentication in ASP.NET Core projects, using ASP.NET Core Identity.

License

Notifications You must be signed in to change notification settings

AngeloDotNet/MinimalApi.Identity

Repository files navigation

.NET Modular Dynamic Identity Manager

Visitors

A set of libraries to easily integrate and extend authentication in ASP.NET Core projects, using ASP.NET Core Identity.

🏷️ Introduction

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.

🧩 Features

  • Minimal API: Built using .NET 8 Minimal API for a lightweight and efficient implementation.
  • Entity Framework Core: Uses EF Core for data access, making it easy to integrate with your existing database.
  • Modular: The library is designed to be modular, allowing you to add or remove features as needed.
  • Dynamic: Supports dynamic management of users, roles, claims, forms, licensing and policies.
  • Flexible Configuration: Easily configurable via appsettings.json to suit your application's needs.
  • Outbox Pattern: Implement the transactional outbox pattern for reliable email sending.

πŸ› οΈ Installation

Prerequisites

As an alternative to SQL Server you can use one of these databases:

Setup

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.API

βš™οΈ Configuration

The 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": {
    "SQLServer": "Data Source=[HOSTNAME];Initial Catalog=IdentityManager;User ID=[USERNAME];Password=[PASSWORD];Encrypt=False",
    "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;",
    "PostgreSQL": "Host=[HOSTNAME];Port=5432;Database=IdentityManager;Username=[USERNAME];Password=[PASSWORD];Include Error Detail=true",
    "MySQL": "Server=[HOSTNAME];Port=3306;Database=IdentityManager;Uid=[USERNAME];Pwd=[PASSWORD]",
    "SQLite": "Data Source=Data/IdentityManager.db"
},
"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,
    "IsRequiredAuth": false,
    "Username": "admin",
    "Password": "StrongPassword"
}

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.

πŸ—ƒοΈ Database

Configuration

The library uses Entity Framework Core to manage the database.

The connection string is configured in the AppSettings section of the appsettings.json file.

  • Database Type: Set via AppSettings:DatabaseType (supported values: sqlserver, azuresql, postgresql, mysql, sqlite)

After setting the type of database you want to use, modify the corresponding connection string.

Migrations

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 -Project parameter to the name of that project.

πŸ“Ž Swagger / OpenAPI

It is possible to protect access to the Swagger UI with the following configuration:

  • RequiredAuth: set via SwaggerSettings:IsRequiredAuth (supported values: true, false)
  • Username: set via SwaggerSettings:Username
  • Password: set via SwaggerSettings:Password

You can manage the state of the Swagger UI with the following configuration:

  • Enable/Disable Swagger UI: set via SwaggerSettings:IsEnabled (supported values: true, false)

πŸ”° Feature Flags

🚧 coming soon

πŸ’‘ Usage Examples

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);

        builder.Host.UseSerilog((context, services, config) => config.ReadFrom.Configuration(context.Configuration));
        //.WriteToMinio(context.Configuration)

        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();

        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();
        await RegisterServicesExtensions.ConfigureDatabaseAsync(app.Services);

        app.UseHttpsRedirection();
        app.UseStatusCodePages();

        app.UseMiddleware<MinimalApiExceptionMiddleware>();

        if (swaggerSettings.IsEnabled)
        {
            if (swaggerSettings.IsRequiredAuth)
            {
                app.UseMiddleware<SwaggerBasicAuthMiddleware>();
            }
            
            app.UseSwagger();
            app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", $"{app.Environment.ApplicationName} v1"));
        }

        app.UseRouting();
        app.UseCors("cors");

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseMapEndpoints(appSettings);
        await app.RunAsync();
    }
}

πŸ” Authentication

The following authentication types are currently supported:

  • JWT Bearer Token

πŸ§‘β€πŸ’Ό Administrator Account

A default administrator account is created automatically with the following configuration:

  • Email: set via AppSettings:AssignAdminEmail
  • Username: set via AppSettings:AssignAdminUsername
  • Password: set via AppSettings:AssignAdminPassword

πŸ“š API Reference

See the documentation for a list of all available endpoints.

πŸ“¦ Packages

Name Type Version
Identity.Module.API Main Nuget Package
Identity.Module.AccountManager Dependence Nuget Package
Identity.Module.AuthManager Dependence Nuget Package
Identity.Module.ClaimsManager Dependence Nuget Package
Identity.Module.Core Dependence Nuget Package
Identity.Module.EmailManager Dependence Nuget Package
Identity.Module.LicenseManager Dependence Nuget Package
Identity.Module.ModuleManager Dependence Nuget Package
Identity.Module.PolicyManager Dependence Nuget Package
Identity.Module.ProfileManager Dependence Nuget Package
Identity.Module.RolesManager Dependence Nuget Package
Identity.Module.Shared Dependence Nuget Package

πŸ† Badges

SonarCloud

Quality Gate Status Bugs Code Smells Duplicated Lines (%) Lines of Code

Reliability Rating Security Rating Technical Debt Maintainability Rating Vulnerabilities

πŸ—ΊοΈ Roadmap

  • Move the configuration of the claims to a dedicated library
  • Move the configuration of the module to a dedicated library
  • Move the configuration of the roles to a dedicated library
  • Fix the TODOs
  • Replacing exceptions with implementation of operation results
  • Migrate SmtpOptions configuration to database
  • Migrate FeatureFlagsOptions configuration to database
  • Migrate SwaggerSettings configuration to database
  • Replacing the hosted service email sender using Coravel jobs
  • Change the entity ID type from INT to GUID
  • Make the ID entity type dynamic, so that it can accept both INT and GUID at runtime
  • Code Review and Refactoring

Future implementations

  • Migrate solution to .NET 10
  • Add support for multi tenancy
  • Add endpoints for two-factor authentication and management
  • Add endpoints for downloading and deleting personal data
  • Add authentication support from third-party providers (e.g. Auth0, KeyCloak, GitHub, Azure)

πŸ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.

⭐ Give a Star

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.

🀝 Contributing

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:

  1. Fork the repository
  2. Create a feature branch (starting from the develop branch)
  3. Make your changes
  4. Submit a pull requests (targeting develop)

πŸ†˜ Support

If you have any questions or need help, read here to find out what to do.

About

A set of libraries to easily integrate and extend authentication in ASP.NET Core projects, using ASP.NET Core Identity.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages