Skip to content

Instantly share code, notes, and snippets.

@mrutherford2
Created March 18, 2020 18:02
Show Gist options
  • Save mrutherford2/06302f9969d3aca65c13e9f990b18c25 to your computer and use it in GitHub Desktop.
Save mrutherford2/06302f9969d3aca65c13e9f990b18c25 to your computer and use it in GitHub Desktop.
using System;
using System.Threading.Tasks;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Web.Services;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Caching.Memory;
using Web.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Linq;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.Extensions.Options;
namespace Web.Infrastructure.Security
{
public class ClaimsLoader : IClaimsTransformation
{
private readonly ICrresClient _crresClient;
private readonly IMemoryCache _cache;
private readonly ILogger<ClaimsLoader> _logger;
private readonly Application _application;
public ClaimsLoader(ICrresClient crresClient, IMemoryCache cache, ILogger<ClaimsLoader> logger, IOptions<Application> options)
{
_crresClient = crresClient;
_cache = cache;
_logger = logger;
_application = options.Value;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
var identity = (ClaimsIdentity)principal.Identity;
var domainUser = Regex.Replace(identity.Name, ".*\\\\(.*)", "$1", RegexOptions.None);
if (_cache.Get<UserCacheModel>(domainUser) == null)
{
var tokenResponse = await _crresClient.GetToken(domainUser);
if (!tokenResponse.IsSuccessful) return new ClaimsPrincipal(identity);
var userResponse = await _crresClient.GetUserPublicProfileByUserId(domainUser, tokenResponse.Data);
if (!userResponse.IsSuccessful) return new ClaimsPrincipal(identity);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(tokenResponse.Data);
var roleClaims = jwt.Claims.Where(y => y.Type == "famerole").Select(x => x.Value);
var isAdmin = false;
foreach (var role in roleClaims)
{
var obj = JObject.Parse(role);
if (((string)obj["ApplicationAcronym"]).ToLower() == _application.FameApp.ToLower() &&
((string)obj["RoleName"]).ToLower() == _application.FameAdminRole.ToLower())
{
isAdmin = true;
}
}
var user = userResponse.Data;
// Save data in cache.
_cache.Set(domainUser, new UserCacheModel
{
UserId = user.UserId,
PersonId = user.PersonId,
FirstName = user.FirstName,
LastName = user.LastName,
Title = user.Title,
Token = tokenResponse.Data,
IsAdmin = isAdmin
});
}
var cacheEntry = _cache.Get<UserCacheModel>(domainUser);
// create a new ClaimsIdentity copying the existing one
var claimsIdentity = new ClaimsIdentity(
identity.Claims,
identity.AuthenticationType,
identity.NameClaimType,
identity.RoleClaimType);
claimsIdentity.AddClaim(new Claim("now", DateTime.Now.ToString()));
claimsIdentity.AddClaim(new Claim(CrresClaimTypes.PersonId, cacheEntry.PersonId.ToString()));
claimsIdentity.AddClaim(new Claim(CrresClaimTypes.FirstName.ToString(), cacheEntry.FirstName));
claimsIdentity.AddClaim(new Claim(CrresClaimTypes.LastName, cacheEntry.LastName));
claimsIdentity.AddClaim(new Claim(CrresClaimTypes.Title, cacheEntry.Title));
claimsIdentity.AddClaim(new Claim(CrresClaimTypes.Token, await GetCachedToken(domainUser, cacheEntry.Token)));
claimsIdentity.AddClaim(new Claim(CrresClaimTypes.Admin, cacheEntry.IsAdmin.ToString()));
return new ClaimsPrincipal(claimsIdentity);
}
private async Task<string> GetTokenAsync(string domainUser)
{
var result = await _crresClient.GetToken(domainUser);
return result.Data;
}
private async Task<string> GetCachedToken(string domainUser, string cachedToken)
{
var handler = new JwtSecurityTokenHandler();
var token = handler.ReadJwtToken(cachedToken);
if(token.ValidTo < DateTime.Now.AddMinutes(-5))
{
return await GetTokenAsync(domainUser);
}
return cachedToken;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment