78 lines
2.9 KiB
C#
78 lines
2.9 KiB
C#
using MessengerBroker.Configuration.Model;
|
|
using MessengerBroker.Models;
|
|
using MessengerBroker.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 MessengerBroker.Handlers
|
|
{
|
|
/// <summary>
|
|
/// Validates our permananet API keys sent over as Bearer tokens.
|
|
/// </summary>
|
|
public class CustomBearerAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
|
|
{
|
|
private readonly IMemoryCache memoryCache;
|
|
private readonly BrokerConfiguration configuration;
|
|
|
|
public CustomBearerAuthenticationHandler(
|
|
IOptionsMonitor<AuthenticationSchemeOptions> options,
|
|
ILoggerFactory loggerFactory,
|
|
UrlEncoder encoder,
|
|
IMemoryCache memoryCache,
|
|
BrokerConfiguration configuration)
|
|
: base(options, loggerFactory, encoder)
|
|
{
|
|
this.memoryCache = memoryCache;
|
|
this.configuration = configuration;
|
|
}
|
|
|
|
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
|
{
|
|
const string HEADER = "Authorization";
|
|
const string PREFIX = "Bearer ";
|
|
|
|
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(memoryCache.TryGetValue(token, out CachedIdentity oldCache))
|
|
{
|
|
var identity = Context.RequestServices.GetRequiredService<Identity>();
|
|
identity.Server = oldCache.Server;
|
|
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(oldCache.ClaimsPrincipal, Scheme.Name)));
|
|
}
|
|
else
|
|
{
|
|
var brokerId = Guid.Parse(token);
|
|
var server = configuration.SlaveServers.SingleOrDefault(x => x.BrokerId == brokerId);
|
|
|
|
var principal = new ClaimsPrincipal(
|
|
new ClaimsIdentity(
|
|
new List<Claim>
|
|
{
|
|
new Claim(ClaimTypes.NameIdentifier, token),
|
|
new Claim(ClaimTypes.Name, token)
|
|
}, Scheme.Name));
|
|
|
|
var cache = new CachedIdentity
|
|
{
|
|
ClaimsPrincipal = principal,
|
|
Server = server
|
|
};
|
|
|
|
memoryCache.Set(token, cache, TimeSpan.FromMinutes(5));
|
|
|
|
var identity = Context.RequestServices.GetRequiredService<Identity>();
|
|
identity.Server = server;
|
|
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(cache.ClaimsPrincipal, Scheme.Name)));
|
|
}
|
|
}
|
|
}
|
|
} |