Initial commit carried over from private repo. This is V2.
This commit is contained in:
@ -0,0 +1,81 @@
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user