Security header is not valid error message - c#

I'm getting this message
TIMESTAMP=2017-03-29T16:36:41Z&CORRELATIONID=9d5672f086c52&ACK=Failure&VERSION=204&BUILD=31674279&L_ERRORCODE0=10002&L_SHORTMESSAGE0=Security error&L_LONGMESSAGE0=Security header is not valid&L_SEVERITYCODE0=Error
I'm sure that I'm using the right credentials, I've copied them from sandbox account, from View API Signature page.
I'm trying to connect to sandbox environment with the url https://api-3t.sandbox.paypal.com/nvp.
Here is how my payload looks like:
METHOD=MassPay&
USR=usr_api1.name.com&
PWD=9M8SWRPX6JMXDHAP&
SIGNATURE=AFcWxV21C7fd0v3bYYYRCpSSRl31AIajEwSIe41AAl--j033rVmjUPI7&
VERSION=204&
RECEIVERTYPE=EmailAddress&
CURRENCYCODE=USD&
L_EMAIL0=some.user%40company.com&
L_AMT0=25
And I have TLS1.2 enabled. Is there any way to trace the problem except for incorrect credentials? Or maybe I have to set-up my test/dev account? By the way, my dev account isn't Business, but test account is Business and not Client.
Here is code that makes the request:
var sb = new StringBuilder();
foreach (var field in dic)
{
sb.Append($"{field.Key}={HttpUtility.UrlEncode(field.Value)}&");
}
sb.Remove(sb.Length - 1, 1);
var payload = sb.ToString().Trim();
var req = WebRequest.Create(SandBoxHost + "?" + payload);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
using (var resp = req.GetResponse()){}

Credentials and URL were correct. However, I found out that you are not able to send Mass Payment via txt file if your sandbox Business account does not have verified credit card. You need to specify this moment when you are creating a new sandbox user. Guess it would not work with API as well if you don't specify credit card.
The real problem was in one of the field names. I used USR instead of USER.

Related

RestSharp isn't consistent when calling wordpress/woocomerce site

In my dev environment, I have a wordpress/woocommerce site locally all hosted under IIS.
Using the following code restsharp works:
var fullEndPoint = string.Concat(site, "/wp-json/wc/v3/", endpoint)
var client = new RestSharp.RestClient(fullEndPoint)
{
Authenticator = OAuth1Authenticator.ForProtectedResource(consumerkey, woosecret, "", "")
};
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(serializedData);
client.Execute(request);
When I change the fullEndPoint, consumerkey and woosecret to be our main test site which mirrors our live site (running on apache/linux), I receive
Sorry you are not allowed to create Resource.
If I post to our test site the same data using postman, it goes through and works.
For the purposes of testing, if I then change the above declaration of client to be:
var client = new RestClient("https://wordpress.mytestsite.com/wp-json/wc/v3/products?oauth_consumer_key=ck_a24ad9ddea2d9fe71d9172c415fd51b4dc83a6dc&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1627038994&oauth_nonce=T9gfeZGdmNx&oauth_version=1.0&oauth_signature=OJB1TBpLpA%2Bet0A%2FDFbozOT9nf8%3D");
where fullendpoint is the code shown in postman's code windows for Restsharp, again the code works, so I know the error is misleading. So Why doesn't restsharp work in the initial way for me when I point to my test site?
Edit:
If I change client such that I'm now setting it up as:
var client = new RestSharp.RestClient(fullEndPoint)
{
Authenticator = OAuth1Authenticator.ForClientAuthentication(consumerkey, woosecret, username, password)
};
where username and password equal the user set up in woo commerce against the consumer key for read/write access, I still receive an access denied error

SOAP error when connecting to NetSuite web services: "Namespace prefix ' soapenv' not defined"

I am getting the following error when connecting to a NetSuite production account, through the Suitetalk API:
I don't have problems connecting to the Sandbox account for this client. I am connecting through a C# WCF project. I don't believe the problem is with the c# project, since this code is being used in Production with many other clients.
It seems to me like the SOAP message being returned is incorrectly formatted - there seems to be a line break before the 'soapenv' element in the SOAP message. I am getting this error when creating a "get" request against the API(using passport login). This error occurs on any API call though, I did try simply logging in through the API as well.
I have double checked the login details and account information for this client and everything seems in orders. Besides, if this information is incorrect, I should be getting authentication errors - not malformed SOAP messages.
Any help will be appreciated, thanks!
It turns out that I needed to use the webservices.na3.netsuite WSDL. I was under the impression that the regular "webservices.netsuite" WSDL would direct any requests to the correct server.
So when connecting to a NetSuite account through SuiteTalk, be sure to make use of the correct WSDL and specify the correct endpoint along with your login credentials. You can check which server your account is hosted on by looking at the URL when logged into your NetSuite account.
Update
I made use of the newest 'DataCenterAwareNetSuiteService' class to dynamically get the correct data center for the current account that I am trying to connect to:
class DataCenterAwareNetSuiteService : NetSuiteService
{
private System.Uri OriginalUri;
public DataCenterAwareNetSuiteService(string account, bool doNotSetUrl)
: base()
{
OriginalUri = new System.Uri(this.Url);
if (account == null || account.Length == 0)
account = "empty";
if (!doNotSetUrl)
{
//var temp = getDataCenterUrls(account);
DataCenterUrls urls = getDataCenterUrls(account).dataCenterUrls;
Uri dataCenterUri = new Uri(urls.webservicesDomain + OriginalUri.PathAndQuery);
this.Url = dataCenterUri.ToString();
}
}
public void SetAccount(string account)
{
if (account == null || account.Length == 0)
account = "empty";
this.Url = OriginalUri.AbsoluteUri;
DataCenterUrls urls = getDataCenterUrls(account).dataCenterUrls;
Uri dataCenterUri = new Uri(urls.webservicesDomain + OriginalUri.PathAndQuery);
this.Url = dataCenterUri.ToString();
}
}
The above is called like so:
new DataCenterAwareNetSuiteService("*account number*", false);
With the latest version of NetSuite, some changes have been made to URLs. For instance, now you can have more than one SandBox URL. Because of this, the URL format has changed. The account number used when authenticating is also now different. For sandboxes the account Id is now passed up as ACCOUNTNUMBER_SANDBOXID, for example 12345678_SB1.
You can determine the URLs for the SOAP and REST services by using the datacenterurls endpoint and supplying the account # you would like to determine the URLS for.
https://rest.netsuite.com/rest/datacenterurls?account=YOUR_ACCOUNT_NUMBER
The functionality below is based on the answer from #Charl above.
I have made a couple changes below that provides the same functionality without using inheritance.
This may be a simpler implementation for a newer programmer who does not know how to use an inherited class.
var accountId = "1234567"; // Insert your account ID here
var Service = new NetSuiteService();
Service.Url = new Uri(Service.getDataCenterUrls(accountId).dataCenterUrls.webservicesDomain + new Uri(Service.Url).PathAndQuery).ToString();

Retrieving user information in Azure Function (C#) from Angular-cli application

I'm having troubles retrieving user information inside an Azure Function and have no idea how to do this. I've tried different things already, but nothing seems to work...
First of all, I created an Angular-cli application and am able to login using the "adal-angular5" npm-package.
When I want to retrieve information from a HttpTriggering Azure function, I can't seem to find how to get more information about the user using the token from the angular app (or how to validate the logged in user). I'm including it in the headers of the message.
headers.append('Authorization', `Bearer ${this.adal5Service.userInfo.token}`);
I've created an app registration in Azure AD including my reply URL, Permissions to "Microsoft Graph" and "Windows Azure Active Directory"
Does anyone know how to do this? (If more information should be necessary to solve... just tell me, and I'll happily provide that)
Things I tried already
Code below with both requestUrl's (one is in comment) and with/without sending the token in the header
using (var client = new HttpClient())
{
//var requestUrl = $"https://graph.windows.net/me?api-version=1.6";
var requestUrl = $"https://graph.microsoft.com/v1.0/me/";
var request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = client.SendAsync(request).Result;
var responseString = response.Content.ReadAsStringAsync().Result;
var user = JsonConvert.DeserializeObject<AdUser>(responseString);
return user;
}

UWP app HttpClient HTTPS client certificate problems

I'm writing a UWP app in C# that is eventually destined for IoT, but right now I've only been debugging locally. I'm using Windows.Web.Http.HttpClient to connect to a self-hosted WCF REST web service that I've also written and have running as a Console app on the same machine for testing. The service requires mutual authentication with certificates, so I have a CA cert, service cert, and client cert.
My UWP code works like this:
Check app cert store for client cert and CA cert installed.
If not, install from PFX file and CER file, respectively.
Attach the Certificate to the HttpBaseProtocolFilter and add the filter to the HttpClient
Call the HttpClient.PostAsync
After I call PostAsync I get the following error: An Error Occurred in the Secure Channel Support. After plenty of searching online, and by common sense, I'm pretty sure HttpClient is barfing because of a problem establishing the mutually-authenticated SSL connection. But based on my troubleshooting I can't figure why.
To troublshoot further, I've written a plain old Console app using System.Net.Http.HttpClient, attached the client certificate to the request and everything works great. Sadly, System.Net isn't fully supported on UWP. I've also tried NOT attaching the certificate to the UWP HttpClient and the app prompts me with a UI to select an installed certificate. I select the correct cert and still get the same exception (this at least lets me know the cert is installed correctly and validating properly with the CA from the app's perspective). In additon, I hit the GET on the web service from a browser, select the client cert when prompted, and am able to download a file.
I've tried using Fiddler and, I assume because of the way it proxies traffic, it seems to work a little bit further, except my web service rejects the request as Forbidden (presumably because Fiddler is not including the correct client cert in the request). I haven't hit up Wireshark yet because it's a pain to get Wireshark to work using localhost on Windows.
My next step is to start changing the web service to not require client authentication and see if that is the problem.
Two questions: Why is Windows.Web.Http.HttClient not working in this case? And, less important, any recommendations on good HTTP monitoring tools to help me debug this further?
This MSDN post proved to have the answer. Seems like an oversight on MS part requiring a separate, meaningless call to the API beforehand. Oh well.
http://blogs.msdn.com/b/wsdevsol/archive/2015/03/26/how-to-use-a-shared-user-certificate-for-https-authentication-in-an-enterprise-application.aspx
Excerpt from the article:
However, the security subsystem requires user confirmation before allowing access to a certificates private key of a certificate stored in the shared user certificates store. To complicate matters, if a client certificate is specified in code then the lower level network functions assume the application has already taken care of this and will not prompt the user for confirmation.
If you look at the Windows Runtime classes related to certificates you won’t find any method to explicitly request access to the certificate private key, so what is the app developer to do?
The solution is to use the selected certificate to 'Sign' some small bit of data. When an application calls CryptographicEngine.SignAsync, the underlying code requests access to the private key to do the signing at which point the user is asked if they want to allow the application to access the certificate private key. Note that you must call 'Async' version of this function because the synchronous version of the function: Sign, uses an option that blocks the display of the confirmation dialog.
For example:
public static async Task<bool> VerifyCertificateKeyAccess(Certificate selectedCertificate)
{
bool VerifyResult = false; // default to access failure
CryptographicKey keyPair = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(
selectedCertificate, HashAlgorithmNames.Sha1,
CryptographicPadding.RsaPkcs1V15);
String buffer = "Data to sign";
IBuffer Data = CryptographicBuffer.ConvertStringToBinary(buffer, BinaryStringEncoding.Utf16BE);
try
{
//sign the data by using the key
IBuffer Signed = await CryptographicEngine.SignAsync(keyPair, Data);
VerifyResult = CryptographicEngine.VerifySignature(keyPair, Data, Signed);
}
catch (Exception exp)
{
System.Diagnostics.Debug.WriteLine("Verification Failed. Exception Occurred : {0}", exp.Message);
// default result is false so drop through to exit.
}
return VerifyResult;
}
You can then modify the earlier code example to call this function prior to using the client certificate in order to ensure the application has access to the certificate private key.
Add the Certificate file your Project
Add the Certificate to the Manifested file (give file path in attachment)
the Frist Service Call of in Ur Project use to ignore the certificate validation Following Code is most Suitable for Login Function.
try
{
var filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationInformationMissing);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.WrongUsage);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain);
Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient(filter);
TimeSpan span = new TimeSpan(0, 0, 60);
var cts = new CancellationTokenSource();
cts.CancelAfter(span);
var request = new Windows.Web.Http.HttpRequestMessage()
{
RequestUri = new Uri(App.URL + "/oauth/token"),
Method = Windows.Web.Http.HttpMethod.Post,
};
//request.Properties. = span;
string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(Server_Username + ":" + Server_Password));
var values = new Dictionary<string, string>
{ { "grant_type", "password" },{ "username", Uname}, { "password", Pwd }};
var content = new HttpFormUrlEncodedContent(values);
request.Headers.Add("Authorization", "Basic " + encoded);
request.Content = content;
User root = new User();
using (Windows.Web.Http.HttpResponseMessage response = await client.SendRequestAsync(request).AsTask(cts.Token))
{
HttpStatusCode = (int)response.StatusCode;
if (HttpStatusCode == (int)HttpCode.OK)
{
using (IHttpContent content1 = response.Content)
{
var jsonString = await content1.ReadAsStringAsync();
root = JsonConvert.DeserializeObject<User>(jsonString);
App.localSettings.Values["access_token"] = root.Access_token;
App.localSettings.Values["refresh_token"] = root.Refresh_token;
App.localSettings.Values["expires_in"] = root.Expires_in;
var json = JsonConvert.SerializeObject(root.Locations);
App.localSettings.Values["LocationList"] = json;
App.localSettings.Values["LoginUser"] = Uname;
}
}
}
}
catch (Exception ex)
{
ex.ToString();
}

Error connecting with client certificate from smart card / etoken to WCF Service

We have a WCF service configured to work with client certificates.
Our client is a .net 3.5 WPF application.
While testing, it works perfectly with certificates generated by Microsoft CA and others.
While testing it with a physical token (Aladdin/Safenet eToken Pro 64k) it also works well.
(On first try connecting to server the “Token Logon” window pops up.
After successful authentication to the token the server request works, and the next try to connect to server succeed without the token logon message showing)
Now, if we remove the token and re-insert it, when trying to connect with the same certificate we get an error “The request was aborted: Could not create SSL/TLS secure channel”. HResult 0x80131509
The only way to make it work again is restart the application.
Certificates are retrieved with System.Security.Cryptogragpy:
var store = new X509Store("My", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
//Getting the right certificate and then:
store.Close();
The connection to server is with this code:
string uriStr = txtUrl.Text + "/rest/auth/strong/Ping";
var client = WebRequest.Create(new Uri(uriStr)) as HttpWebRequest;
client.Method = "POST";
client.ContentType = "application/text; charset=unicode;";
client.ContentLength = 0;
client.PreAuthenticate = false;
client.KeepAlive = false;
client.ClientCertificates.Add(certificate); //Cert attached to the request
using (var res = client.GetResponse() as HttpWebResponse)
{
using (var responseStream = res.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
string s = reader.ReadToEnd();
ShowAndWriteToFile(s);
}
}
}
I looked at Verbose logging and Wireshark captures, Couldn't find the problem from there.
Other stuff I tried:
Clearing pin code cache – when clearing it before removing token, then on next attempt to connect to server the “Token logon” window pops up.
Clearing it after remove and re-insert didn’t change anything.
Restarting the WCF Service – after the token re-inserted, still same result.
Checking how other operations on the certificate behaves before and after token remove and re-insert.
For instance, if I Sign and verify some message with the certificate after the removal and re-insert of the token then the “Token logon” window pops up again and it continues working.
Trying to connect with self-created certificate put in the store – Worked, then deleting it from store and re-adding it – still worked.

Categories