Files
EonaCat.SecureToken/EonaCat.SecureToken/Middleware/SecureTokenMiddleware.cs
T
2026-06-20 06:27:57 +02:00

82 lines
3.1 KiB
C#

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using EonaCat.SecureToken.Validation;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace EonaCat.SecureToken.Extensions
{
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
/// <summary>
/// Middleware that validates a SecureToken from the Authorization header
/// and makes the claims available on <see cref="HttpContext.Items"/>.
/// This is a lightweight alternative to full ASP.NET Core authentication middleware.
/// For full integration, use the authentication handler instead.
/// </summary>
public sealed class SecureTokenMiddleware
{
private readonly RequestDelegate _next;
private readonly TokenValidationOptions _options;
private readonly ILogger<SecureTokenMiddleware> _logger;
/// <summary>HttpContext.Items key where validated claims are stored.</summary>
public const string ClaimsItemKey = "SecureToken.Claims";
public SecureTokenMiddleware(RequestDelegate next, TokenValidationOptions options, ILogger<SecureTokenMiddleware> logger)
{
_next = next;
_options = options;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, ITokenService tokenService)
{
var authHeader = context.Request.Headers[HeaderNames.Authorization].FirstOrDefault();
if (authHeader?.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase) == true)
{
var token = authHeader.Substring("Bearer ".Length).Trim();
var result = await tokenService.ValidateAsync(token, _options, context.RequestAborted);
if (result.IsSuccess)
{
context.Items[ClaimsItemKey] = result.UnwrapClaims();
}
else
{
_logger.LogDebug("Token validation failed: {Result}", result);
}
}
await _next(context);
}
}
/// <summary>
/// Provides extension methods to extract SecureToken claims from <see cref="HttpContext"/>.
/// </summary>
public static class HttpContextExtensions
{
/// <summary>
/// Returns the validated token claims from the current request, or null if
/// no valid token was presented.
/// </summary>
public static Core.TokenClaims? GetTokenClaims(this HttpContext context) =>
context.Items.TryGetValue(SecureTokenMiddleware.ClaimsItemKey, out var claims)
? claims as Core.TokenClaims
: null;
/// <summary>
/// Returns true if the current request has a validated token with the given role.
/// </summary>
public static bool HasRole(this HttpContext context, string role)
{
var claims = context.GetTokenClaims();
return claims?.Roles.Contains(role) == true;
}
}
}