Files
monorepo/LCU.Library.Internal.Security/LCU.Library.Internal.Security/Service/AzureAdVerificationService.cs
T
2026-03-24 09:49:29 -05:00

109 lines
4.3 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.Security.Dao.Client;
using LCU.Library.Internal.Security.Models.Configuration;
using LCU.Library.Internal.Security.Models.Response;
namespace LCU.Library.Internal.Security.Service;
public class AzureAdVerificationService : IAzureAdVerificationService
{
private const string ClientId = "client_id";
private const string Scope = "scope";
private const string Username = "username";
private const string Password = "password";
private const string GrantType = "grant_type";
private const string State = "state";
private const string ClientSecret = "client_secret";
private const string GrantTypePassword = "password";
private readonly AzureAdJwtRetrievalConfiguration _configuration;
private readonly IDaoClient _daoClient;
public AzureAdVerificationService(IDaoClient daoClient, AzureAdJwtRetrievalConfiguration configuration)
{
_daoClient = daoClient;
_configuration = configuration;
}
public async Task<JwtSecurityToken?> GetTokenForWebApiUsingUsernamePasswordAsync(string userName, string password)
{
try{
var handler = new JwtSecurityTokenHandler();
var stateIdentifier = Guid.NewGuid().ToString();
var queryString = HttpUtility.ParseQueryString(string.Empty, Encoding.UTF8);
queryString.Add(ClientId, _configuration.ClientId);
queryString.Add(Scope, _configuration.Scope);
queryString.Add(Username, userName);
queryString.Add(Password, password);
queryString.Add(GrantType, GrantTypePassword);
queryString.Add(State, stateIdentifier);
queryString.Add(ClientSecret, _configuration.ClientSecret);
var result = await _daoClient.Post<AzureAdAuthorizationResponse>(_configuration.AuthenticationUrl, "", HttpUtility.UrlDecode(queryString.ToString()));
if (result == null || handler.ReadToken(result.AccessToken) is not JwtSecurityToken jsonToken){
throw new ServiceException($"Authentication for Username: {userName} could not be performed, a null JWT was returned, or the JWT could not be parsed.");
}
return jsonToken;
} catch (Exception exception){
throw new ServiceException($"Failure to get authentication for username: {userName}. Exception message: {exception.Message}");
}
}
public bool ValidateJwtHasAuthorizedRole(JwtSecurityToken jsonToken)
{
try
{
IEnumerable<string> RolesFromClaim(string claimName)
{
if (jsonToken.Payload.GetValueOrDefault(claimName)?.ToString() is { Length: > 0 } claims)
{
return JsonSerializer.Deserialize<IEnumerable<string>>(claims)!;
}
return Enumerable.Empty<string>();
}
var roles = RolesFromClaim("roles");
var groups = RolesFromClaim("groups");
return roles.Concat(groups).Any(x => _configuration.Role.Split("|").Any(y => y == x));
} catch (Exception exception){
throw new ServiceException($"Failure to validate roles for JwtSecurityToken. Exception message: {exception.Message}");
}
}
public bool ValidateJwtHasAuthorizedRole(JwtSecurityToken jsonToken, List<string> approvedRoles)
{
try
{
IEnumerable<string> RolesFromClaim(string claimName)
{
if (jsonToken.Payload.GetValueOrDefault(claimName)?.ToString() is { Length: > 0 } claims)
{
return JsonSerializer.Deserialize<IEnumerable<string>>(claims)!;
}
return Enumerable.Empty<string>();
}
var roles = RolesFromClaim("roles");
var groups = RolesFromClaim("groups");
return roles.Concat(groups).Any(x => approvedRoles.Any(y => y == x));
} catch (Exception exception){
throw new ServiceException($"Failure to validate roles for JwtSecurityToken. Exception message: {exception.Message}");
}
}
}