109 lines
4.3 KiB
C#
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}");
|
|
}
|
|
}
|
|
} |