82 lines
3.1 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|