#region Using Statements using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text.Json; #endregion namespace ClearstreamAPIConnector { class Program { // callback used to validate the certificate in an SSL conversation private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors) { var result = cert.Subject.Contains("YourServerName"); return result; } /// /// Get our refresh token /// /// /// private static async Task GetRefreshTokenAsync(Token originalToken) { const string username = "stb2_01014165_1000181"; const string certPw = "clearstream"; #region Private Member //private static string clearstreamApiEndpointUrl = "https://api.clearstream.com/"; var clearstreamApiEndpointUrl = "https://api-t2s-test.clearstream.com/"; #endregion Token? tok = null; // First create a proxy object var proxy = new WebProxy { Address = new Uri($"http://l7fwout.usinet.it:3128"), BypassProxyOnLocal = false, UseDefaultCredentials = false, Credentials = CredentialCache.DefaultNetworkCredentials }; // check certificate chain ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { Console.WriteLine("Ssl Policy Errors:"); switch (sslPolicyErrors) { case SslPolicyErrors.None: Console.WriteLine("No error in certificate found"); break; case SslPolicyErrors.RemoteCertificateNotAvailable: Console.WriteLine("RemoteCertificateNotAvailable"); break; case SslPolicyErrors.RemoteCertificateNameMismatch: Console.WriteLine("RemoteCertificateNameMismatch"); break; case SslPolicyErrors.RemoteCertificateChainErrors: Console.WriteLine("RemoteCertificateChainErrors"); break; } // call our validation logic //return ValidateServerCertificate(sender, certificate, chain, sslPolicyErrors); Console.WriteLine("Overriding cert chain errors. Proceeding..."); return true; }; // configure endpoint and certificate try { var remoteAddress = $"{clearstreamApiEndpointUrl}authmanager/oauth2/access_token"; var certFile = @"./Cert/P12/xact-api-credentials-3des.p12"; var certificates = new X509Certificate2Collection(); certificates.Import(certFile, certPw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); // values to pass on to service var values = new Dictionary { { "grant_type", "refresh_token" },{"refresh_token",originalToken.refresh_token}, { "username", username}, }; // encode it in url form... var data = new FormUrlEncodedContent(values); // use modern http client implementation to call endpoint using var httpHandler = new HttpClientHandler(); httpHandler.ClientCertificates.Add(certificates[0]); httpHandler.Proxy = proxy; using var client = new HttpClient(httpHandler); // handle communiction with API var response = await client.PostAsync(remoteAddress, data); // get our response content var responseContent = await response.Content.ReadAsStringAsync(); // get our token tok = JsonSerializer.Deserialize(responseContent); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}."); } return tok; } /// /// Get Elibility Token /// /// private static async Task GetElibilityTokenAsync() { //string scope = "allow ocapi-playground-v1"; var scopeDi = "allow digital-instruments"; var username = "stb2_01014165_1000181"; var password = "Creation1,"; var certPw = "clearstream"; #region Private Member //private static string clearstreamApiEndpointUrl = "https://api.clearstream.com/"; var clearstreamApiEndpointUrl = "https://api-t2s-test.clearstream.com/"; #endregion Token? tok = null; // First create a proxy object //var proxy = new WebProxy //{ // Address = new Uri($"http://l7fwout.usinet.it:3128"), // BypassProxyOnLocal = false, // UseDefaultCredentials = false, // Credentials = CredentialCache.DefaultNetworkCredentials //}; // check certificate chain ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { Console.WriteLine("Ssl Policy Errors:"); switch (sslPolicyErrors) { case SslPolicyErrors.None: Console.WriteLine("No error in certificate found"); break; case SslPolicyErrors.RemoteCertificateNotAvailable: Console.WriteLine("RemoteCertificateNotAvailable"); break; case SslPolicyErrors.RemoteCertificateNameMismatch: Console.WriteLine("RemoteCertificateNameMismatch"); break; case SslPolicyErrors.RemoteCertificateChainErrors: Console.WriteLine("RemoteCertificateChainErrors"); break; } Console.WriteLine("Overriding cert chain errors. Proceeding..."); return true; }; // configure endpoint and certificate try { var remoteAddress = $"{clearstreamApiEndpointUrl}authmanager/oauth2/access_token"; var certFile = @".\Cert\P12\xact-api-credentials-3des.p12"; X509Certificate2Collection certificates = new(); certificates.Import(certFile, certPw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); // values to pass on to service var values = new Dictionary { { "grant_type", "password" }, //{ "scope", scope}, {"scope", scopeDi }, { "username", username}, { "password", password}, }; // encode it in url form... var data = new FormUrlEncodedContent(values); // use modern http client implementation to call endpoint using var httpHandler = new HttpClientHandler(); httpHandler.ClientCertificates.Add(certificates[0]); //httpHandler.Proxy = proxy; using var client = new HttpClient(httpHandler); // handle communiction with API var response = await client.PostAsync(remoteAddress, data); // get our response content var responseContent = await response.Content.ReadAsStringAsync(); // get our token tok = JsonSerializer.Deserialize(responseContent); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}."); } return tok; } /// /// Get all associcated templates /// /// Bearer token derived from OAuth2.0 request /// JSON with all templates available as a static async Task GetAllTemplates(Token accessToken) { Console.WriteLine("Attempting to get all templates for our account"); if (accessToken == null) { throw new ArgumentNullException(nameof(accessToken)); } DiTemplateList templates = null; var certPw = "clearstream"; #region Private Member //private static string clearstreamApiEndpointUrl = "https://api.clearstream.com/"; var clearstreamApiEndpointUrl = "https://api-t2s-test.clearstream.com/"; #endregion var remoteAddress = $"{clearstreamApiEndpointUrl}digital-instruments/di/templates"; // First create a proxy object // var proxy = new WebProxy // { // Address = new Uri($"http://l7fwout.usinet.it:3128"), // BypassProxyOnLocal = false, // UseDefaultCredentials = false, // Credentials = CredentialCache.DefaultNetworkCredentials // }; try { var certFile = @"./Cert/P12/xact-api-credentials-3des.p12"; var certificates = new X509Certificate2Collection(); certificates.Import(certFile, certPw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); // use modern http client implementation to call endpoint using var httpHandler = new HttpClientHandler(); httpHandler.ClientCertificates.Add(certificates[0]); // httpHandler.Proxy = proxy; using var client = new HttpClient(new LoggingHandler(httpHandler)); // handle additional client header client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken.access_token}"); // handle communiction with API var response = await client.GetAsync(remoteAddress); // get our response content var responseContent = await response.Content.ReadAsStringAsync(); templates = JsonSerializer.Deserialize(responseContent); Console.WriteLine($"Received the following content from {remoteAddress}: '{responseContent}'"); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}."); } return templates; } /// /// Call the playground API asynchronously /// /// /// static async Task CallClearstreamPlaygroundApiAsync(Token accessToken) { if (accessToken == null) { throw new ArgumentNullException(nameof(accessToken)); } var jsonContent = string.Empty; var certPw = "clearstream"; #region Private Member //private static string clearstreamApiEndpointUrl = "https://api.clearstream.com/"; var clearstreamApiEndpointUrl = "https://api-t2s-test.clearstream.com/"; #endregion var remoteAddress = $"{clearstreamApiEndpointUrl}/playground/v1/echo?value=Hello%20World"; // // First create a proxy object // var proxy = new WebProxy // { // Address = new Uri($"http://l7fwout.usinet.it:3128"), // BypassProxyOnLocal = false, // UseDefaultCredentials = false, // Credentials = CredentialCache.DefaultNetworkCredentials // }; try { var certFile = @"./Cert/P12/xact-api-credentials-3des.p12"; var certificates = new X509Certificate2Collection(); certificates.Import(certFile, certPw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); // values to pass on to service var values = new Dictionary(); // use modern http client implementation to call endpoint using var httpHandler = new HttpClientHandler(); httpHandler.ClientCertificates.Add(certificates[0]); // httpHandler.Proxy = proxy; using var client = new HttpClient(httpHandler); // handle additional client header client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken.access_token}"); // handle communiction with API var response = await client.GetAsync(remoteAddress); // get our response content var responseContent = await response.Content.ReadAsStringAsync(); jsonContent = responseContent; } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}."); } return jsonContent; } /// /// Validate the whole certificate chain using the cacert certificate /// /// /// /// /// /// static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { Console.WriteLine("Checking server certificate..."); if (sslPolicyErrors == SslPolicyErrors.None) { Console.WriteLine("sslPolicyErrors == SslPolicyErrors.None. Thus returning true to validate certificate from clearstream."); return true; } Console.WriteLine("Cert issues found. Attempting to load cacert pem from Clearstream."); var privateChain = new X509Chain(); privateChain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; var cert2 = new X509Certificate2(certificate); var signerCert2 = new X509Certificate2(@".\Cert\ocapi-stb2_01014165_1000181-cacert.pem"); privateChain.ChainPolicy.ExtraStore.Add(signerCert2); privateChain.Build(cert2); var isValid = true; Console.WriteLine("Validate Certificate chain manually."); foreach (var chainStatus in privateChain.ChainStatus) { if (chainStatus.Status != X509ChainStatusFlags.NoError) { Console.WriteLine("chainStatus.Status != X509ChainStatusFlags.NoError"); isValid = false; break; } } Console.WriteLine($"Returning {isValid} as result of cert chain validation."); if (isValid == false) { Console.WriteLine("Overriding false value for cert result with 'true'"); isValid = true; } return isValid; } /// /// Main entry point for /// /// static async Task Main(string[] args) { try { // Console.WriteLine("Setting proxy to 'http://l7fwout.usinet.it:3128'"); // string resultString = string.Empty; var errorOccured = false; // // First create a proxy object // var proxy = new WebProxy // { // Address = new Uri($"http://l7fwout.usinet.it:3128"), // BypassProxyOnLocal = false, // UseDefaultCredentials = false, // Credentials = CredentialCache.DefaultNetworkCredentials // }; Console.WriteLine("Preparing the request..."); // check certificate chain ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { Console.WriteLine("Ssl Policy Errors:"); switch (sslPolicyErrors) { case SslPolicyErrors.None: Console.WriteLine("No error in certificate found"); break; case SslPolicyErrors.RemoteCertificateNotAvailable: Console.WriteLine("RemoteCertificateNotAvailable"); break; case SslPolicyErrors.RemoteCertificateNameMismatch: Console.WriteLine("RemoteCertificateNameMismatch"); break; case SslPolicyErrors.RemoteCertificateChainErrors: Console.WriteLine("RemoteCertificateChainErrors"); break; } // call our validation logic return ValidateServerCertificate(sender, certificate, chain, sslPolicyErrors); }; // validate cert by calling a function ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate); // first get the access token from clearstream API var accessToken = await GetElibilityTokenAsync(); if (accessToken != null && !string.IsNullOrEmpty(accessToken.access_token)) { Console.WriteLine("Received non null JWT token. Calling Playground Clearstream API"); Console.WriteLine($"Token: '{accessToken.access_token}'"); Console.WriteLine($"Refresh Token: {accessToken.refresh_token}"); Console.WriteLine($"Expires in: {accessToken.expires_in}"); // call the playground API //resultString = await CallClearstreamPlaygroundApiAsync(accessToken); //Console.WriteLine("For testing purposes, try to regain a new token based on the refresh token."); //var refreshToken = await GetRefreshTokenAsync(accessToken); //if (refreshToken != null) //{ // Console.WriteLine("Received non null refresh token. Dumping details now:"); // Console.WriteLine($"Token: '{refreshToken.access_token}'"); // Console.WriteLine($"Refresh Token: {refreshToken.refresh_token}"); // Console.WriteLine($"Expires in: {refreshToken.expires_in}"); //} // next try to call the FIRST real DI method and get the available templates var templates = await GetAllTemplates(accessToken); if (templates != null && templates.Count > 0) { Console.WriteLine("Dumping all received templates available for the account used:"); var firstTemplate = templates[0]; Console.WriteLine($"PartyId: {firstTemplate.partyId}"); } Console.WriteLine("Successfully called Digital Instruments API."); } else { Console.WriteLine("Received empty JWT token. Aborting."); errorOccured = true; } if (errorOccured) { Console.WriteLine("Clearstream VNext connectivity test completed with error(s)."); } else { Console.WriteLine("Clearstream VNext connectivity test completed successfully."); } } catch (Exception ex) { Console.WriteLine($"Got Exception while running the connetivity check. Message {ex.Message}, Stacktrace: {ex.StackTrace}"); Console.WriteLine("Clearstream VNext connecivity check FAILED."); } } } }