The request was aborted: Could not create SSL/TLS secure channel. (RestSharp, SSL Client Certificates) - authentication

I have following code which is calling an API using basic authentication and SSL client certificate but its throwing exception and giving me following error.
"The request was aborted: Could not create SSL/TLS secure channel."
I tried to find a solution on Google but failed to find any solution. Can anyone help me out on this. Thanks.
// Variables
string basicAuthenticationUserName = "username";
string basicAuthenticationPassword = "password";
string clientCertificateFilePath = "Path-To-Certificate-File";
string clientCertificatePassword = "certificate-password";
string url = "https://" + basicAuthenticationUserName + ":" + basicAuthenticationPassword + "#apiserverurl/apimethod";
// Creating RestSharp Request Object
var request = new RestRequest(Method.POST)
{
RequestFormat = DataFormat.Json,
OnBeforeDeserialization = resp =>
{
resp.ContentType = "application/json";
}
};
// Adding Headers
request.AddHeader("Content-Length", "0");
request.AddHeader("Accept", "application/x-null-message");
// Importing Certificates
var certificates = new X509Certificate();
certificates.Import(clientCertificateFilePath, clientCertificatePassword, X509KeyStorageFlags.PersistKeySet);
// Creating RestSharp Client Object
var client = new RestClient
{
BaseUrl = new Uri(url),
ClientCertificates = new X509CertificateCollection { certificates },
Authenticator = new HttpBasicAuthenticator(managingLou, basicAuthenticationPassword)
};
// Executing Request
var response = client.Execute<T>(request);

I have faced the similar issue. Let me mention the steps here for your help.
After the installation of windows service, I went through the following steps to fix the issue:
Go To Start > Run and type Services.msc
Select your service > Right click and choose Properties
Select the 2nd tab "Log On"
Select the radio button "This account"
Enter the username and password of currently log in user. (Make sure Its the same user who has installed the service)
Apply the changes
Start the service

Related

Msgraph Calls only via IIS timing out

I wrote an API to call MSGraph to retrieve user informations over https://graph.microsoft.com/v1.0/users?$count=true&$search= and deliver it to my .Net5.0 webapp.
so far everything was working good til I tried to publish the API and run it on my IIS.
From my IIS it only runs into a timeout: "detail": "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (graph.microsoft.com:443)",
I tried to call MSGraph from the same server which works without any problems over postman also in my development environment.
Authentication for my API is done via the azure portal app-registration with client id and client secret.
like this:
[HttpGet]
[Route("TokenRequest")]
public string MSGraphTokenRequest()
{
var client = new RestClient("https://login.microsoftonline.com/350a94cb-4159-4140-b29d-1d98051105d5/oauth2/v2.0/token");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type="+grant_type+"&client_id="+client_id+"&client_secret="+client_secret+"&scope="+scope, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
return JsonConvert.DeserializeObject<Token>(response.Content).access_token;
}
and requesting the information:
[HttpGet]
[Route("GetUserTest")]
public IActionResult GetUserTest(string userPrincipalName)
{
var client = new RestClient("https://graph.microsoft.com/v1.0/users?$count=true&$search=\"userPrincipalName:" + userPrincipalName + "\"");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer " + MSGraphTokenRequest());
request.AddHeader("ConsistencyLevel", "eventual");
IRestResponse response = client.ExecuteAsync(request).Result;
if (((int)response.StatusCode) != 200)
{
return Problem(response.ErrorMessage);
}
else
{
return Json(response.Content);
}
}
Maybe somebody could guide me in the right direction I have no further ideas how to solve this.
Thanks in advance.
So my guess is that the IIS-Server is sending it requests with higher port numbers and these requests were intercepted by our company firewall which of course I asked my dev-ops beforehand, if with this could be a firewall related problem...
So the solution to the problem was to add a firewall rule for graph.microsoft.com.

Call Azure API from WebJob/ Shared code between WebJob and web api

I have a web api in an ASE and an associated web job. I am trying to call this web api from the web job but it always fails with winhttpexception: a security error has occurred. I have put in all the tls related settings but still getting the error.
Any suggestions on the error?
Also is there a way to share code between WebJob and web api?
I was able to resolve the issue by setting the below in my code.This resolved the Security Error.
using(var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender,certificate,chain,sslPolicyErrors) => true
})
You could create a console app and publish it as Azure WebJobs. For username and password you could click Get Publish Profile in your Azure webapp overview to get them.
Then you could use the following code in Console App to call your Azure Webapi.
string userName = "$xxxxxx";
string userPassword = "xxxxxxxxxxxxx";
string webAppName = "xxxxxx";
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{userName}:{userPassword}"));
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Basic " + base64Auth);
var baseUrl = new Uri($"https://{webAppName}.azurewebsites.net/api/values");
var result = client.GetAsync(baseUrl).Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsStringAsync();
readTask.Wait();
var value = readTask.Result;
Console.WriteLine(value.ToString());
}
}
Console.WriteLine("run successfully");
Output as below:

No Session handle to Renew Token in Xero-Partner-App

Error from Xero :
Token does not match an expected REQUEST token
The issue seems to be related to the comment from the Xero help site?
This error will also occur if the session handle is not used in the
access token renewal process.
I have confirmed I do not get this on the return object of the following :
public async Task<AccessTokenDto> Authorise(string oauth_token, string oauth_verifier, string org)
{
var xeroacessToken =
_authenticator.RetrieveAndStoreAccessToken(_user.Name,
oauth_token, oauth_verifier, org);
}
I am not sure how I get the session handle and then how to use this in my service call to renew the token? As per the example I was expecting this on my token.
oauth_session_handle=ODJHMGEZNGVKMGM1NDA1NZG3ZWIWNJ
"Session Handle used to renew the access token"
Code that works the first time with the token that has been retrieved from the database:
var tokenStore = new MemoryTokenStore();
tokenStore.Add(xerotoken);
var api = new RA.Xero.Partner.Core(tokenStore, XeroUser(UserId)), _hostingEnvironment)
{
UserAgent = "My Partner App " + input.ConsumerKey,
};
I tried to see if using the Partner Authentication directly would work :
var tokenStore = new MemoryTokenStore();
tokenStore.Add(xerotoken);
Settings ApplicationSettings = new Settings();
X509Certificate2 certificate = RA.Xero.Partner.Core.Certificate(_hostingEnvironment);
var partnerAuthentication = new RA.Xero.Public.PartnerAuthenticator(
ApplicationSettings.Uri,
ApplicationSettings.AuthorizeUri,
ApplicationSettings.CallBackUri,
tokenStore,
certificate
);
var consumer = new Consumer(ApplicationSettings.Key,
ApplicationSettings.Secret);
var token = partnerAuthentication.GetToken(consumer,
XeroUser(UserId));
I have checked the keys are the partner keys in my app and any hints or sample code would be great.

NTLM Auth with RestSharp

I am attempting to create some tests using RestSharp for a project I am working on.
This project uses Single Sign-on NTLM Authentication.
I am attemping to use a NTLMAuthenticator but my getUser request is always failing. I am not positive what URL to put in for the CredentialCache, the project or the SSO Id Provider.
SharedRequests shared = new SharedRequests();
var credential = new CredentialCache
{
{
new Uri("project or ID Provider URL or something else?"),
"NTLM",
new NetworkCredential("doamin\Username", "Password")
}
};
RestClient client = new RestClient();
client.BaseUrl=new Uri("projectURL");
client.Authenticator = new NtlmAuthenticator(credential);
client.PreAuthenticate = true;
RestRequest request = shared.GetCurrentUser();
IRestResponse response = client.Execute(request);
my response always gets a 500 error which is what is expected when no auth cookies are present.

HttpClient 4.2.3 using both SSL encryption and NTLM authentication fails

I am trying to use a REST call to Sharepoint 2010 via HTTPClient 4.2.3 from a Liferay 6.1 portlet.
I have imported the cert into my local MAC's JVM cacerts and am trying to load the cacerts as the keystore.
My code is:
String opsCalendarURL1 = "https://hostname/sites/team-sites/operations/_vti_bin/owssvr.dll?";
String opsCalendarURL2 = "Cmd=Display&List={6E460908-D470-4F8A-AF76-CC279E25E0B1}&XMLDATA=TRUE";
String opsCalenderURLEncoded = opsCalendarURL1 + URLEncoder.encode( opsCalendarURL2 , "UTF8" );
System.out.println(opsCalenderURLEncoded);
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
// SSL
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File("/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/cacerts"));
try {
trustStore.load(instream, "changeit".toCharArray());
} finally {
try { instream.close(); } catch (Exception ignore) {}
}
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", 443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
System.out.println("----------------------------------------");
HttpHost targetHost = new HttpHost("hostname", 443, "https");
httpclient.getCredentialsProvider().setCredentials(
AuthScope.ANY,
new NTCredentials("username", "password","machine","domain"));
HttpGet httpget = new HttpGet(opsCalenderURLEncoded);
System.out.println("executing request: " + httpget.getRequestLine());
System.out.println("to target: " + targetHost);
HttpResponse response2 = httpclient.execute(targetHost, httpget);
HttpEntity entity = response2.getEntity();
System.out.println("----------------------------------------");
System.out.println(response2.getStatusLine());
System.out.println(response2.getProtocolVersion());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
httpclient.getConnectionManager().shutdown();
}
The response I always get back is:
HTTP/1.1 401 Unauthorized
I don't see an SSL handshake in the wire logs and get a 401 unauthorized response. I have tried various combinations of the sample codes with same results.
Note - that I've used FireFox and CURL to do the same thing I'm trying to do here programmatically, and it works fine. So the server appears to be set up correctly. The CURL verbose log show the SSL handshake happening first and the NTLM succeeds as the next step.
I can attach the wire logs if needed.
Thanks a lot for your time!
I appreciate any help and pointers.
The issue seems to be with IIS 7.5 and HTTPClient using NTLM v2 and Windows 2008 R2.
I switched to Java HTTPURLConnection and it works pretty well.
Post with some detail on another issue with the same code here