144 lines
5.7 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|