Created
March 18, 2020 18:02
-
-
Save mrutherford2/06302f9969d3aca65c13e9f990b18c25 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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