Files
messengerapi/code/MessengerApi/Handlers/CustomBearerAuthenticationHandler.cs
masiton 4393977389
All checks were successful
Build and Push Docker Image / build (push) Successful in 1m3s
Build and Push Docker Image / docker (push) Successful in 43s
Initial commit carried over from private repo. This is V2.
2025-07-04 21:24:12 +02:00

82 lines
3.1 KiB
C#

using MessengerApi.Contracts.Models.Scoped;
using MessengerApi.Models;
using MessengerApi.Models.Scoped;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using System.Text.Encodings.Web;
namespace MessengerApi.Handlers
{
/// <summary>
/// Validates our permananet API keys sent over as Bearer tokens.
/// </summary>
public class CustomBearerAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private readonly IMemoryCache memoryCache;
public CustomBearerAuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory loggerFactory,
UrlEncoder encoder,
IMemoryCache memoryCache)
: base(options, loggerFactory, encoder)
{
this.memoryCache = memoryCache;
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
const string HEADER = "Authorization";
const string PREFIX = "Bearer ";
Context.RequestServices.GetRequiredService<Timing>(); // creates the object in scope.
if (!Request.Headers.TryGetValue(HEADER, out var authHeader) ||
!authHeader.ToString().StartsWith(PREFIX))
{
return Task.FromResult(AuthenticateResult.NoResult());
}
var token = authHeader.ToString().Substring(PREFIX.Length).Trim();
if(this.memoryCache.TryGetValue(token, out CachedIdentity oldCache))
{
var identity = Context.RequestServices.GetRequiredService<Identity>();
identity.User = oldCache.User;
identity.UserRoutes = oldCache.UserRoutes;
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(oldCache.ClaimsPrincipal, Scheme.Name)));
}
else
{
var unitOfWork = Context.RequestServices.GetRequiredService<IUnitOfWork>();
var user = unitOfWork.Users.SingleByApiKeyAndEnabled(Guid.Parse(token), true);
var routes = unitOfWork.UserRoutes.GetAllByUser(user).ToArray();
var principal = new ClaimsPrincipal(
new ClaimsIdentity(
new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Name),
new Claim(ClaimTypes.Name, user.Name)
}, Scheme.Name));
var cache = new CachedIdentity
{
ClaimsPrincipal = principal,
User = user,
UserRoutes = routes
};
this.memoryCache.Set(token, cache, TimeSpan.FromMinutes(5));
var identity = Context.RequestServices.GetRequiredService<Identity>();
identity.User = cache.User;
identity.UserRoutes = cache.UserRoutes;
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(cache.ClaimsPrincipal, Scheme.Name)));
}
}
}
}