Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add mle #111

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public JwtToken(MerchantConfig merchantConfig)

KeyAlias = merchantConfig.KeyAlias;
KeyPass = merchantConfig.KeyPass;
Certificate = Cache.FetchCachedCertificate(P12FilePath, KeyPass);
X509Certificate2Collection certs = Cache.FetchCachedCertificate(P12FilePath, KeyPass);
Certificate = Cache.GetCertBasedOnKeyAllias(certs, merchantConfig.KeyAlias);
}

public string BearerToken { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace AuthenticationSdk.core
*============================================================================================*/
public class MerchantConfig
{
public MerchantConfig(IReadOnlyDictionary<string, string> merchantConfigDictionary = null)
public MerchantConfig(IReadOnlyDictionary<string, string> merchantConfigDictionary = null, Dictionary<string, bool> mapToControlMLEonAPI = null)
{
var _propertiesSetUsing = string.Empty;

Expand All @@ -37,7 +37,7 @@ public MerchantConfig(IReadOnlyDictionary<string, string> merchantConfigDictiona
{
_propertiesSetUsing = "Dictionary Object";

SetValuesUsingDictObj(merchantConfigDictionary);
SetValuesUsingDictObj(merchantConfigDictionary, mapToControlMLEonAPI);
}
else
{
Expand All @@ -48,7 +48,7 @@ public MerchantConfig(IReadOnlyDictionary<string, string> merchantConfigDictiona
{
_propertiesSetUsing = "App.Config File";

SetValuesFromAppConfig(merchantConfigSection);
SetValuesFromAppConfig(merchantConfigSection, mapToControlMLEonAPI);
}
else
{
Expand All @@ -64,6 +64,8 @@ public MerchantConfig(IReadOnlyDictionary<string, string> merchantConfigDictiona

// Validations
ValidateProperties();
//validate MLE configs
ValidateMLEProperties();
}

#region Class Properties
Expand Down Expand Up @@ -162,6 +164,12 @@ public MerchantConfig(IReadOnlyDictionary<string, string> merchantConfigDictiona

public string PemFileDirectory { get; set; }

public bool UseMLEGlobally { get; set; }

public Dictionary<string, bool> MapToControlMLEonAPI { get; set; }

public string MleKeyAlias { get; set; }

#endregion

public void LogMerchantConfigurationProperties()
Expand Down Expand Up @@ -195,7 +203,7 @@ public void LogMerchantConfigurationProperties()
Logger.Debug($"Merchant Configuration :\n{merchCfgLogString}");
}

private void SetValuesFromAppConfig(NameValueCollection merchantConfigSection)
private void SetValuesFromAppConfig(NameValueCollection merchantConfigSection, Dictionary<string, bool> mapToControlMLEonAPI)
{
MerchantId = merchantConfigSection["merchantID"];
PortfolioId = merchantConfigSection["portfolioID"];
Expand Down Expand Up @@ -223,9 +231,30 @@ private void SetValuesFromAppConfig(NameValueCollection merchantConfigSection)
ProxyUsername = merchantConfigSection["proxyUsername"];
ProxyPassword = merchantConfigSection["proxyPassword"];
PemFileDirectory = merchantConfigSection["pemFileDirectory"];

if (merchantConfigSection["useMLEGlobally"] != null && "true".Equals(merchantConfigSection["useMLEGlobally"], StringComparison.OrdinalIgnoreCase))
{
UseMLEGlobally = bool.Parse(merchantConfigSection["useMLEGlobally"]);
}
else
{
UseMLEGlobally = false;
}

MapToControlMLEonAPI = mapToControlMLEonAPI;

if (merchantConfigSection["mleKeyAlias"] != null)
{
MleKeyAlias = merchantConfigSection["mleKeyAlias"]?.Trim();
}

if (string.IsNullOrWhiteSpace(MleKeyAlias?.Trim()))
{
MleKeyAlias = Constants.DefaultMleAliasForCert;
}
}

private void SetValuesUsingDictObj(IReadOnlyDictionary<string, string> merchantConfigDictionary)
private void SetValuesUsingDictObj(IReadOnlyDictionary<string, string> merchantConfigDictionary, Dictionary<string, bool> mapToControlMLEonAPI)
{
var key = string.Empty;

Expand Down Expand Up @@ -434,6 +463,31 @@ private void SetValuesUsingDictObj(IReadOnlyDictionary<string, string> merchantC
{
PemFileDirectory = merchantConfigDictionary["pemFileDirectory"];
}

if (merchantConfigDictionary.ContainsKey("useMLEGlobally") && "true".Equals(merchantConfigDictionary["useMLEGlobally"], StringComparison.OrdinalIgnoreCase))
{
UseMLEGlobally = bool.Parse(merchantConfigDictionary["useMLEGlobally"]);
}
else
{
UseMLEGlobally = false;
}

if (mapToControlMLEonAPI != null)
{
MapToControlMLEonAPI = mapToControlMLEonAPI;
}

if (merchantConfigDictionary.ContainsKey("mleKeyAlias"))
{
MleKeyAlias = merchantConfigDictionary["mleKeyAlias"]?.Trim();
}

//if MleKeyAlias is null or empty or contains only whitespace then set default value
if (string.IsNullOrWhiteSpace(MleKeyAlias?.Trim()))
{
MleKeyAlias = Constants.DefaultMleAliasForCert;
}
}
}
catch (KeyNotFoundException err)
Expand Down Expand Up @@ -547,5 +601,29 @@ private void ValidateProperties()
P12Keyfilepath = $"{KeyDirectory}{pathDirectorySeparator}{KeyfileName}.p12";
}
}

private void ValidateMLEProperties()
{
bool mleConfigured = UseMLEGlobally;

if (MapToControlMLEonAPI != null && MapToControlMLEonAPI.Count > 0)
{
foreach (bool value in MapToControlMLEonAPI.Values)
{
if (value)
{
mleConfigured = true;
break;
}
}
}

//if MLE=true then check for auth Type
if (mleConfigured && !Enumerations.AuthenticationType.JWT.ToString().Equals(AuthenticationType, StringComparison.OrdinalIgnoreCase))
{
Logger.Error("MLE is only supported in JWT auth type");
throw new Exception("MLE is only supported in JWT auth type");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ public static class Cache

private static readonly string regexForFileNameFromDirectory = "(^([a-z]|[A-Z]):(?=\\\\(?![\\0-\\37<>:\"/\\\\|?*])|\\/(?![\\0-\\37<>:\"/\\\\|?*])|$)|^\\\\(?=[\\\\\\/][^\\0-\\37<>:\"/\\\\|?*]+)|^(?=(\\\\|\\/)$)|^\\.(?=(\\\\|\\/)$)|^\\.\\.(?=(\\\\|\\/)$)|^(?=(\\\\|\\/)[^\\0-\\37<>:\"/\\\\|?*]+)|^\\.(?=(\\\\|\\/)[^\\0-\\37<>:\"/\\\\|?*]+)|^\\.\\.(?=(\\\\|\\/)[^\\0-\\37<>:\"/\\\\|?*]+))((\\\\|\\/)([^\\0-\\37<>:\"/\\\\|?*]+|(\\\\|\\/)$))*()$";

public static X509Certificate2 FetchCachedCertificate(string p12FilePath, string keyPassword)
private class CertInfo
{
public X509Certificate2Collection Certificates { get; set; }
public DateTime Timestamp { get; set; }
}

public static X509Certificate2Collection FetchCachedCertificate(string p12FilePath, string keyPassword)
{
try
{
Expand All @@ -34,30 +40,27 @@ public static X509Certificate2 FetchCachedCertificate(string p12FilePath, string

var matches = Regex.Match(p12FilePath, regexForFileNameFromDirectory);
var certFile = matches.Groups[11].ToString();

if (!cache.Contains(certFile))
if (!cache.Contains(certFile) || ((CertInfo)cache[certFile]).Timestamp != File.GetLastWriteTime(p12FilePath))
{
var policy = new CacheItemPolicy();
var filePaths = new List<string>();
var cachedFilePath = Path.GetFullPath(p12FilePath);
filePaths.Add(cachedFilePath);
policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
var certificates = new X509Certificate2Collection();
certificates.Import(p12FilePath, keyPassword, X509KeyStorageFlags.PersistKeySet);

var certificate = new X509Certificate2(p12FilePath, keyPassword);
cache.Set(certFile, certificate, policy);
return certificate;
}
else if (cache[certFile] is X509Certificate2 cachedCertificateFromP12File)
{
return cachedCertificateFromP12File;
}
else
{
return null;
CertInfo certInfo = new CertInfo();
certInfo.Certificates = certificates;
certInfo.Timestamp = File.GetLastWriteTime(p12FilePath);

cache.Set(certFile, certInfo, policy);
}
//return all certs in p12
return ((CertInfo)cache[certFile]).Certificates;
}
}
catch (CryptographicException e)
catch (Exception e)
{
if (e.Message.Equals("The specified network password is not correct.\r\n"))
{
Expand Down Expand Up @@ -97,5 +100,18 @@ public static RSAParameters FetchCachedRSAParameters(MerchantConfig merchantConf
return (RSAParameters)cache[certFile];
}
}

public static X509Certificate2 GetCertBasedOnKeyAllias(X509Certificate2Collection certs, String keyAlias)
{
foreach (var cert in certs)
{
if (cert.GetNameInfo(X509NameType.SimpleName, false).Equals(keyAlias, StringComparison.OrdinalIgnoreCase))
{
return cert;
}
}
throw new Exception($"{Constants.ErrorPrefix} Certificate with alias {keyAlias} not found.");

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,9 @@ public static class Constants
public static readonly string DeprecationPrefix = "Deprecated: ";

public static readonly string P12FileDirectory = "..\\..\\Resource";

public static readonly string DefaultMleAliasForCert = "CyberSource_SJC_US";

public static readonly int CertificateExpiryDateWarningDays = 90;
}
}
Loading