I'm trying to authenticate a user for the Azure management API. I'm following this tutorial for that:
http://msdn.microsoft.com/en-us/library/windowsazure/ee460782.aspx
However, when I execute it, I always get a "certificate not found" error. What could cause this? My code is exactly the same as in the example:
// Values for the subscription ID and List Hosted Services operation.
//
string subscriptionId = "****************";
// The opperation to be performed. This value can be modified to reflect the operation being performed.
string operationName = "hostedservices";
// Build a URI for https://management.core.windows.net/<subscription-id>/services/<operation-type>
Uri requestUri = new Uri("https://management.core.windows.net/"
+ subscriptionId
+ "/services/"
+ operationName);
// Create the request and specify attributes of the request.
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUri);
// Define the requred headers to specify the API version and operation type.
request.Headers.Add("x-ms-version", "2010-10-28");
request.Method = "GET";
request.ContentType = "application/xml";
// The thumbprint value of the management certificate.
// You must replace the string with the thumbprint of a
// management certificate associated with your subscription.
string certThumbprint = "*************";
// Create a reference to the My certificate store.
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
// Try to open the store.
try
{
certStore.Open(OpenFlags.ReadOnly);
}
catch (Exception e)
{
if (e is CryptographicException)
{
Console.WriteLine("Error: The store is unreadable.");
}
else if (e is SecurityException)
{
Console.WriteLine("Error: You don't have the required permission.");
}
else if (e is ArgumentException)
{
Console.WriteLine("Error: Invalid values in the store.");
}
else
{
throw;
}
}
// Find the certificate that matches the thumbprint.
X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false);
certStore.Close();
// Check to see if our certificate was added to the collection. If no, throw an error, if yes, create a certificate using it.
if (0 == certCollection.Count)
{
throw new Exception("Error: No certificate found containing thumbprint " + certThumbprint);
}
// Create an X509Certificate2 object using our matching certificate.
X509Certificate2 certificate = certCollection[0];
// Attach the certificate to the request.
request.ClientCertificates.Add(certificate);
try
{
// Make the call using the web request.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Display the web response status code.
Console.WriteLine("Response status code: " + response.StatusCode);
// Display the request ID returned by Windows Azure.
if (null != response.Headers)
{
Console.WriteLine("x-ms-request-id: "
+ response.Headers["x-ms-request-id"]);
Console.ReadKey();
}
// Parse the web response.
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
// Display the raw response.
Console.WriteLine("Response output:");
Console.WriteLine(reader.ReadToEnd());
Console.ReadKey();
// Close the resources no longer needed.
response.Close();
responseStream.Close();
reader.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Related
I am very new in google Document AI, I tried to use this code but still have this response. Do you have any idea what I'm doing wrong?
I have installed from nuget Google.Cloud.DocumentAI.V1
Status(StatusCode="InvalidArgument", Detail="Request contains an invalid argument.", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"#1643889903.765000000","description":"Error received from peer ipv4:142.250.186.42:443","file":"......\src\core\lib\surface\call.cc","file_line":1067,"grpc_message":"Request contains an invalid argument.","grpc_status":3}")
public async void Start()
{
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", #"path-to-json");
try
{
//Generate a document
string pdfFilePath = #"path-to-invoice-pdf";
var bytes = File.ReadAllBytes(pdfFilePath);
ByteString content = ByteString.CopyFrom(bytes);
// Create client
DocumentProcessorServiceClient documentProcessorServiceClient = await DocumentProcessorServiceClient.CreateAsync();
// Initialize request argument(s)
ProcessRequest request = new ProcessRequest
{
ProcessorName = ProcessorName.FromProjectLocationProcessor("ProjectID", "eu", "ProcessorID"),
SkipHumanReview = false,
RawDocument = new RawDocument
{
MimeType = "application/pdf",
Content = content
}
};
// Make the request
ProcessResponse response = await documentProcessorServiceClient.ProcessDocumentAsync(request);
Document docResponse = response.Document;
Console.WriteLine(docResponse.Text);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Quoted from this doc:
Note that if you wish to use DocumentProcessorServiceClient other than in the US, you must specify the endpoint when you construct the client. The endpoint is of the form {location}-documentai.googleapis.com, e.g. eu-documentai.googleapis.com. The simplest way to specify the endpoint is to use DocumentProcessorServiceClientBuilder:
DocumentProcessorServiceClient client = new DocumentProcessorServiceClientBuilder
{
Endpoint = "eu-documentai.googleapis.com"
}.Build();
I created a Web Api to accept a client certificate.
I am calling the web api from a console app using the following code.
var uri = new Uri("https://myservice.azurewebsites.net/api/values");
var handler = new WebRequestHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
var certResults = new X509Store(StoreLocation.LocalMachine);
var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
certStore.Open(OpenFlags.ReadOnly);
}
catch (Exception)
{
Console.WriteLine("Unable to access Certificate store");
}
var thumbprint = "<<self signed cert thumbprint>>";
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
certStore.Close();
HttpClient client = new HttpClient(handler);
if (certCollection.Count > 0)
{
handler.ClientCertificates.Add(certCollection[0]);
client.DefaultRequestHeaders.Add("Thumbprint", certCollection[0].Thumbprint);
}
var result = client.GetAsync(uri).GetAwaiter().GetResult();
Console.WriteLine($"status: {result.StatusCode}");
Console.WriteLine($"content: {result.Content.ReadAsStringAsync().GetAwaiter().GetResult()}");
Console.ReadLine();
}
On the server side, I added a middleware to get the certificate details.
{
//var certHeader = context.Request.Headers["X-ARR-ClientCert"];
var certificate = context.Connection.ClientCertificate;
if (certificate != null)
{
try
{
//var clientCertBytes = Convert.FromBase64String(certHeader);
//var certificate = new X509Certificate2(clientCertBytes);
bool isValidCert = IsValidClientCertificate(certificate);
if (isValidCert)
{
await _next.Invoke(context);
}
else
{
_logger.LogError("Certificate is not valid");
context.Response.StatusCode = 403;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message, ex);
await context.Response.WriteAsync(ex.Message);
context.Response.StatusCode = 403;
}
}
else
{
_logger.LogError("X-ARR-ClientCert header is missing");
context.Response.StatusCode = 403;
}
}
I tried running it on the local machine and on Azure App Services.
I set the flag clientCertEnabled to true in resources.azure.com.
Web Api is SSL enabled.
But the certificate is always coming as null in both
var certHeader = context.Request.Headers["X-ARR-ClientCert"]; and
var certificate = context.Connection.ClientCertificate;.
What am I doing wrong here?
Thanks in advance.
Was reasearching some of this stuff myself and seeing your question, I wonder if you are having one of the issues described in the link Securing ASP.NET WebAPI using Client Certificates
Specifically:
4 Add MyPersonalCA.cer to Local Machine -> Truted Root Certificate Authorities. This is key, espcially while you are developing and want to try things. If you don’t do it, Request.ClientCertificate won’t be populated because the cert chain is untrusted.
I am sending a request to third party website by PostAsJsonAsync as below:
var nbParamsJson = Newtonsoft.Json.JsonConvert.SerializeObject(nbParams);
var httpContent = new StringContent(nbParamsJson);
try
{
var response = await client.PostAsJsonAsync(siteUrl, httpContent);
}
catch (Exception exp)
{
}
which throws an exception: [The request was aborted: Could not create SSL/TLS secure channel.]
I know my website in test environment does not have a SSL certificate and probably is happening because the third-party website has SSL certificate.
I want to know is there any way to create SSL channel without moving to SSL.
I just added
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
before PostAsJsonAsync and it solved my issue.
I'm not sure of your async, but here is an adaptation from working code to send JSON data to an SSL website that you should be able to adapt to your specific case:
var baseurl = "https://example.com/api/upload/123";
var rqst = (HttpWebRequest)WebRequest.Create(baseurl);
rqst.Method = "PUT";
rqst.Accept = "application/json";
var authInfo = "authtoken";
rqst.Headers["Authorization"] = "Token " + authInfo;
rqst.UserAgent = "curl/7.37.0";
rqst.ContentType = "application/json; charset=utf-8";
using (var streamWriter = new StreamWriter(rqst.GetRequestStream()))
{
streamWriter.Write(GetJsonData());
}
try
{
var resp = rqst.GetResponse();
using (var sr = new StreamReader(resp.GetResponseStream() ?? throw new InvalidOperationException()))
{
var txt = sr.ReadToEnd();
textBox1.Text = txt;
}
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
I'm getting a 500 internal server error when trying to access cherwell REST api via Code trying to return a token to make other calls. I've verified that all the information (username, password, ClientID, and client secret) are all correct. I've also verified the server is up and accepting requests. Something must be wrong with my code. Any help would be great!
string token = "";
string responseBody;
string serverName = "ql1cwbeta1";
//initialize web client
using (WebClient webClient = new WebClient())
{
// pull down parameters for body
string grantType = ConfigurationManager.AppSettings["grant_type"];
string clientId = ConfigurationManager.AppSettings["client_id"];
string username = ConfigurationManager.AppSettings["username"];
string password = ConfigurationManager.AppSettings["password"];
string authMode = ConfigurationManager.AppSettings["auth_mode"];
//add parameters in headers
webClient.Headers.Add("Accept", "application/json");
// adding parameters in body
NameValueCollection values = new NameValueCollection
{
{"grant_type", grantType},
{"client_id", clientId},
{"username", username},
{"password", password},
{"auth_mode", authMode}
};
try
{
byte[] responseBytes = webClient.
UploadValues("http://" + serverName + "/CherwellAPI/token?auth_mode=" + authMode + "&api_key=" + clientId, "POST", values);
responseBody = Encoding.UTF8.GetString(responseBytes);
}
catch (Exception exception)
{
return exception;
}
Hope below code may help you.
public static string TokenRequest()
{
try
{
// Create HTTP Web Request for the token request
HttpWebRequest tokenRequest = (HttpWebRequest)WebRequest.Create(Values.TokenURL);
byte[] data = Encoding.ASCII.GetBytes("username=" + Username + "&password=" + Password + "&client_id=" + ClientId + "&grant_type=" + GrantType);
// Set request verb POST, content type and content length (length of data)
tokenRequest.Method = "POST";
tokenRequest.ContentType = "application/x-www-form-urlencoded";
tokenRequest.ContentLength = data.Length;
// Stream request data
using (Stream stream = tokenRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
// Get the response and read stream to string
using (WebResponse response = tokenRequest.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(stream))
{
// responseText = sr.ReadToEnd();
return sr.ReadToEnd();
}
}
}
}
catch (WebException ex)
{
// Catch error for bad URL (404) or bad request (400) resulting from bad input (username, password, client id, grant type in token request)
if (ex.Message.Contains("400"))
{
// do something for bad request
}
else if (ex.Message.Contains("404"))
{
// do something for not found
}
else
{
// unknown error, do something
}
return null;
}
catch (Exception ex)
{
// General Exception
return null;
}
}
For future reference - You can include the client ID as part of the querystring if all parameters are included in the querystring, but if you are also sending a payload, then authmode should be the only thing in the querystring.
It will accept all of these parameters as querystrings.
However, you should know that for Cherwell specifically, if you are using LDAP auth / user accounts, you may need to URL encode your username values.
There are certain special characters that will break the auth command. Specifically, including a backslash for a domain can cause issues if it's not escaped with %5C , which I believe can cause a 400 error.
Also a cause of an error can be if you've chosen an authmode that's not enabled for the browser apps in the Security Settings page of the admin console ;)
my problem is that i am getting a 400 bad request when i try to get a responce to my HTTP request.
Can anyone tell me why this is happening and possibly how i can fix it?
The exact error is :
BadRequestNo change in settings specified
I put in a breakpoint in my code before i pass in the configuration file, when i viewed it, it had changed what i wanted it to change and so the configuration file that already exists is definetly diffirent to the one i am trying to change it with.
Here is the api info for the configuration change : http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx
And Below is my code,Any help is greatly appreciated, thank you
public void changeConfiguration(string serviceName, string deploymentSlot, string config, string deploymentName)
{
//encoding the config file
byte[] encodedConfigbyte = new byte[config.Length];
encodedConfigbyte = System.Text.Encoding.UTF8.GetBytes(config);
string temp = Convert.ToBase64String(encodedConfigbyte);
//creating the URI with the subscriptionID,serviceName and deploymentSlot
Uri changeConfigRequestUri = new Uri("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices/" + serviceName + "/deploymentslots/" + deploymentSlot + "/?comp=config");
//creating a request using the URI
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(changeConfigRequestUri);
//Adding a header to the request
request.Headers.Add("x-ms-version", "2010-10-28");
request.Method = "POST";
//Create a string to hold the request body, temp being the config file
string bodyText = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<ChangeConfiguration xmlns=\"http://schemas.microsoft.com/windowsazure\"" + ">"
+ "<Configuration>" + temp + "</Configuration></ChangeConfiguration>";
//encoding the body
byte[] buf = Encoding.ASCII.GetBytes(bodyText);
request.ContentType = "application/xml";
request.ContentLength = buf.Length;
//searches the cert store for a cert that has a matching thumbprint to the thumbprint supplied
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
certStore.Open(OpenFlags.ReadOnly);
}
catch (Exception e)
{
if (e is CryptographicException)
{
Console.WriteLine("Error: The store is unreadable.");
}
else if (e is SecurityException)
{
Console.WriteLine("Error: You don't have the required permission.");
}
else if (e is ArgumentException)
{
Console.WriteLine("Error: Invalid values in the store.");
}
else
{
throw;
}
}
X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
certStore.Close();
if (certCollection.Count == 0)
{
throw new Exception("Error: No certificate found containing thumbprint ");
}
X509Certificate2 certificate = certCollection[0];
//cert is added to the request
request.ClientCertificates.Add(certificate);
//the requestBody is written to the request
Stream dataStream = request.GetRequestStream();
dataStream.Write(buf, 0, buf.Length);
dataStream.Close();
try
{
//retrieving responce
WebResponse response = (HttpWebResponse)request.GetResponse();
}
catch (WebException e)
{
string test = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();
}
}
}
BadRequest means a parameter was incorrect. My guess is that you are using a deploymentSlot of 0 instead of staging or production like it is mentioned here:
http://msdn.microsoft.com/en-us/library/ee460786.aspx
Other then that, it would be great if you could show us the parameters you are passing in and we can maybe tell from that what is wrong.