Comoda classe per la configurazione e gestione del servizio di autenticazione
11 giugno 2025
IIS | ASP.net core 8 MVC | C#

Abbiamo sviluppato la nostra classe Authentication per semplificare la configurazione del servizio corrispondente prevedendone l'integrazione con un eventuale Bearer Token (in quest'ultimo caso ipotizzando che il Token di autenticazione venga generato da un singolo micro servizio).
Distinguiamo dunque due distinti modelli di autenticazione:
- database locale;
- servizio di autenticazione remoto e recupero di un Bearer Token.
Nel primo caso la lista dei Claim associati all'utenza sarà caricata interrogando un database locale.
Nel secondo caso sarà estratta direttamente dal payload del Bearer Token.
L'incapsulamento del Token tra i claims del cookie offre tre vantaggi:
- Rende più comoda l'estrazione del Token autorizzativo che dovrà essere inserito nell'header delle richieste http;
- La scadenza del cookie determinerà anche la cancellazione del Token;
- La scadenza del Token può essere verificata direttamente all'interno del servizio di autenticazione.
Program.cs
var builder = WebApplication.CreateBuilder(args);
.
.
Authentication.AddAuthentication(builder,30, "/Authentication/Login", "/Home/Index", "/Home/Index");
.
.
var app = builder.Build();
.
.
app.UseAuthentication();
using Microsoft.AspNetCore.Authentication;
using System.Security.Claims;
namespace [mynamespace].UserAuthentication
{
public class Authentication
{
private const string CookieTypeName = "UserSession";
private const string id = "id";
public const string hostip = "hostip";
//LoginPath: redirect if action is colored with [Authorize] and user not authenticated
//LogoutPath: redirect url on SignOutAsync invocation
//AccessDeniedPath: redirect if action is colored with [AuthorizePolicy] and user does not have the necessary policy
public static void AddAuthentication(WebApplicationBuilder builder,
int ExpireMinutesUserSessionTimeSpan,
string? LoginPath = null,
string? LogoutPath = null,
string? AccessDeniedPath = null,
bool CheckBearerTokenExpiration = true)
{
builder.Services.AddAuthentication(CookieTypeName).AddCookie(CookieTypeName, options =>
{
options.Cookie.Name = CookieTypeName;
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(ExpireMinutesUserSessionTimeSpan);
options.Cookie.MaxAge = options.ExpireTimeSpan;
options.SlidingExpiration = true; //the expiration date of the cookie is updated automatically
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // https only
options.Cookie.IsEssential = true;
if (!String.IsNullOrEmpty(LoginPath)) options.LoginPath = new PathString(LoginPath);
if (!String.IsNullOrEmpty(LogoutPath)) options.LogoutPath = new PathString(LogoutPath);
if (!String.IsNullOrEmpty(AccessDeniedPath)) options.AccessDeniedPath = new PathString(AccessDeniedPath);
if (CheckBearerTokenExpiration)
{
//If the BearerToken exists, check whether it is still valid
var onTokenValidated = options.Events.OnValidatePrincipal;
options.Events.OnValidatePrincipal = async context =>
{
if (context.Principal!=null)
if (BearerToken.Token(context.Principal) != string.Empty)
{
await onTokenValidated(context);
if (BearerToken.Expired(context.Principal)) SignOutAsync(context.HttpContext);
}
};
}
});
}
public static async void SignInAsync(List<Claim> claims, HttpContext context, bool rememberme)
{
var identity = new ClaimsIdentity(claims, CookieTypeName);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity);
AuthenticationProperties aut = new AuthenticationProperties();
aut.IsPersistent = rememberme;
await context.SignInAsync(CookieTypeName, claimsPrincipal, aut);
}
public static async void SignOutAsync(HttpContext context)
{
await context.SignOutAsync(CookieTypeName);
}
public static bool IsAuthenticated(ClaimsPrincipal User)
{
if (User?.Identity != null)
{
return User.Identity.IsAuthenticated;
}
else return false;
}
public static int? Id(ClaimsPrincipal User)
{
if (User.Identity != null)
{
var result = User.Claims.FirstOrDefault(C => C.Type == id);
if (result != null) { return Convert.ToInt32(result.Value); } else { return null; }
}
else return null;
}
public static string? HostIp(ClaimsPrincipal User)
{
if (User.Identity != null)
{
var result = User.Claims.FirstOrDefault(C => C.Type == hostip);
return result != null ? result.Value : null;
}
else return null;
}
}
}
Torna all'inizio