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