first commit
This commit is contained in:
+143
@@ -0,0 +1,143 @@
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user