Files
2026-03-11 11:18:25 -05:00

144 lines
5.7 KiB
C#

using System.Security.Cryptography;
using System.Security.Authentication;
using System.Xml;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Options;
using OnlineBankingAuth.Configuration;
using OnlineBankingAuth.Services;
using OnlineBankingAuth.Parsers;
using Landmark.OLA.Models.OnlineBanking;
namespace OnlineBankingAuth.Communication
{
public class DigitalInsightVendorClient : IDigitalInsightVendorClient
{
private readonly ISAMLParser<DISAMLAssertion> _samlParser;
private readonly SecuritySettings _settings;
private readonly IDigitalInsightService _serivce;
public DigitalInsightVendorClient(
ISAMLParser<DISAMLAssertion> samlParser,
IOptions<SecuritySettings> settings,
IDigitalInsightService service)
{
_samlParser = samlParser;
_settings = settings.Value;
_serivce = service;
}
public bool ValidateDIPublicKey(XmlElement x509)
{
var vendorTrustedCert = GetPublicKeyFromStore();
var innerText = x509.InnerText;
byte[] payloadCertBytes = Encoding.Default.GetBytes(innerText);
var payloadCert = new X509Certificate2(payloadCertBytes);
return vendorTrustedCert.GetPublicKeyString().Equals(payloadCert.GetPublicKeyString());
// @TODO: Assert other equalities besides the "publicKeyString"?
}
public DISAMLAssertion GetSAMLPayload(XmlDocument xmlDocument)
{
var lmcuPrivateCertificate = GetPrivateKeyFromStore();
// The "EncryptedAsserion" block is the only acceptable block we can use to construct SAML2.Saml20EncryptedAssertion
var encryptedXml = (XmlElement)xmlDocument.GetElementsByTagName("saml:EncryptedAssertion")[0];
var encryptedXmlDoc = new XmlDocument();
encryptedXmlDoc.LoadXml(encryptedXml.OuterXml);
// SAML2 library does the decrypting work
var privateKeyAlgorithm = (RSA)lmcuPrivateCertificate.GetRSAPrivateKey();
var encryptedAssertion = new SAML2.Saml20EncryptedAssertion(privateKeyAlgorithm, encryptedXmlDoc);
encryptedAssertion.Decrypt();
// The decrypted document should be signed by DI. The Vendor Public Key is used to assert that this is the case.
var vendorPublicKey = GetPublicKeyFromStore().GetRSAPublicKey();
var checkSignature = SAML2.Utils.XmlSignatureUtils.CheckSignature(encryptedAssertion.Assertion, vendorPublicKey);
if (!checkSignature)
{
throw new AuthenticationException("Signature does not match therefore the decrypted payload cannot be accepted.");
}
var decryptedAssertion = _samlParser.ParseAssertion(encryptedAssertion.Assertion.DocumentElement);
return decryptedAssertion;
}
public bool ValidateTimeStamp(DISAMLAssertion assertion)
{
return 0 <= DateTime.Compare(assertion.Conditions.NotAfter, DateTime.Now);
}
public string GetSuccessRedirectUrl()
{
return _settings.SAMLSuccessRedirectRoute;
}
public string GetFailureRedirectUrl(string message)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(message);
var encodedMessage = System.Convert.ToBase64String(plainTextBytes);
return _settings.SAMLFailureRedirectRoute + "&msg=" + encodedMessage;
}
private X509Certificate2 GetPrivateKeyFromStore()
{
// FOR TESTING LOCAL #1345. Note: the second argument is the password for the secure cert file
//return new X509Certificate2("Controllers" + Path.DirectorySeparatorChar + "dev.pfx", "Nvisia", X509KeyStorageFlags.Exportable);
///*
var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, _settings.PrivateCertAzureThumbprint, false);
X509Certificate2 lmcuPrivateCertificate;
if (certCollection.Count == 0)
{
throw new AuthenticationException("Could not GET private key from PrivateCertAzureThumbprint");
}
// Should only have 1 cert with that thumbprint
lmcuPrivateCertificate = certCollection[0];
return lmcuPrivateCertificate;
//*/
}
private X509Certificate2 GetPublicKeyFromStore()
{
// FOR TESTING LOCAL #1345
//return new X509Certificate2("Controllers" + Path.DirectorySeparatorChar + "pfd-sign.qal1signingcert2018");
///*
var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, _settings.PublicCertAzureThumbprint, false);
X509Certificate2 vendorTrustedCert;
if (certCollection.Count == 0)
{
throw new AuthenticationException("Could not GET public key from PublicCertAzureThumbprint");
}
// Should only have 1 cert with that thumbprint
vendorTrustedCert = certCollection[0];
return vendorTrustedCert;
//*/
}
public async Task<AuthTokenResponse> AuthenticateOnlineBankingAccount(OnlineBankingFormData data)
{
var onlineBankingData = _serivce.PopulateOnlineBankingDataFromConfig(data);
return await _serivce.LoginUser(onlineBankingData);
}
}
}