Stripe 401 - No valid API key provided - C# - c#

I get following error: "The remote server returned an error: (401) Unauthorized" in this line:
using (HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse) {}
Here is the complete code:
string clientSecretKey = ConfigurationManager.AppSettings["ClientSecretKey"];
const string ChargeUrl = "https://api.stripe.com/v1/charges?amount={0}&currency={1}&source={2}&description={3}";
string requestUrl = HttpUtility.UrlPathEncode(
String.Format(ChargeUrl, 1000, "usd", "tok_19xLu8HN9aKw9vrkUsflNWOI", "Test charge to text#example.com") );
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
request.Headers.Add("Authorization", "sk_test_example");
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
using (HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse)
{/* some code */}
At the beginning I thought the error was caused because the token can't used more than one time, but I changed it and got the same error. I'm not sure what is causing the error.

The issue here is that you are passing the API key but not using Bearer authentication which is what Stripe's API expects. You need to change your Authorization header like this:
request.Headers.Add("Authorization", "Bearer sk_test_example");
I know you mentioned in the comments that you can't use a third-party library but I wanted to mention one just in case. Stripe.net lets you use Stripe's API in .Net easily without having to rewrite the logic yourself. Handling errors, encoding parameters and sub-hashes properly, managing authentication and JSON decoding, all of this will take a lot of time and trial and error to build from scratch while this library would handle all of this for you.

You're initializing a variable for the secret key but not using it. Try modifying the request url to start with "https://" + clientSecretKey + ":#api..."
This is, of course, assuming clientSecretKey is the Stripe key.
Be careful putting a secret key somewhere on your server that it isn't hidden from a user / client.

Related

Cannot access azure storage table using SAS via c#. Works in postman and browser

I am trying to obtain and parse a table from azure storage.
I generated a Shared Access Signature in azure storage explorer.
If I paste the generated url into browser or postman I get the table back as xml.
However, trying to do a HttpWebRequest with the url results in
System.Net.WebException: 'The remote server returned an error: (415) Unsupported Media Type.'
I have tried different content and accept types
const string url = #"https://laptopdeploymentfiles.table.core.windows.net/PaulLoginScript?st=2019-08-21T08%3A10%3A22Z&se=2019-08-22T08%3A10%3A22Z&sp=r&sv=2018-03-28&tn=paulloginscript&sig=***";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
var webResponse = request.GetResponse();
I have tried both
request.Accept = "application/xml";
and
request.ContentType = "application/xml";
but still get the same error.
I have also tried creating and accessing a new table with only simple data. The data accessed via the brower is valid xml, but I still get the same error from a c# app.
The solution was to use both the following contenttype and accept formats
request.Accept = "application/json";
request.ContentType = "application/json";
The solution was to use both the following contenttype and accept formats
request.Accept = "application/json";
request.ContentType = "application/json";
Tested your specific scenario and got it working by using the HttpClient class.
Here's the code I used to get it working:
// Create an instance of HttpClient with the BaseAddress
var client = new HttpClient
{
BaseAddress = new Uri("https://<STORAGE_NAME>.table.core.windows.net/")
};
// Add an Accept Header to tell the service you're expecting the data in JSON format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Get the actual table
var result = await client.GetAsync("<REST_OF_THE_URI");
When omitting the Accept-header, this code gives the error message:
Atom format is not supported.
EDIT
Taken from Query Tables - Request headers about the Accept header you can specify:
Optional. Specifies the accepted content type of the response payload. Possible values are:
application/atom+xml (versions prior to 2015-12-11 only)
application/json;odata=nometadata
application/json;odata=minimalmetadata
application/json;odata=fullmetadata
I think you need to tell your request what kind of data to expect. Try adding this:
request.ContentType = "application/xml";
I've not tested, so I can't promise this will work. Let me know if it does!
EDIT:
Paul, I tested this code below:
const string url = #" -- used my own xml file in Azure Blob Storage --";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/xml";
var webResponse = request.GetResponse();
It worked with no errors. webResponse was populated just fine. I just whipped up a console app and put these 5 lines of code in it, and then stepped through in debug mode to see what would happen.
I wonder what is different about your environment? Could you try isolating these lines of code?
EDIT 2:
Just a thought... are you sure the XML in your file is valid?

Can not Access a URL using Webrequest

I am trying to get access a URL using .Net but when I run my Program I get the Error The remote server returned an error: (403) Forbidden. Now, the issue is if I click the link http://thisIsMyUR, and enter the user name and password as in the below code. It totally works. I am not able to understand why this exception is coming? Please refer the code below.
Side Note: I am using this sample function below to fire Build of my project in Jenkins Server.
string url = "http://thisIsMyURL";
WebRequest webRequest = WebRequest.Create(url);
webRequest.Credentials = new NetworkCredential("admin", "pass");
WebResponse response = webRequest.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseText = reader.ReadToEnd();
Other than what was recommended by Bradley Uffner in the comments, you can try to provide an actual user agent during the request. I have seen certain servers which would not respond to requests without that header for some odd perceived security reason.
EDIT: as requested, i'll update with some more information.
Some servers may choose to ignore requests, giving some error code (or closing connection) when certain conditions are not met. A good way of checking if that is the case, is to actually send all the standard headers sent by your average web browser in the request. The "User agent" is one of those headers, and this example adds it to your request:
string url = "http://thisIsMyURL";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.UserAgent = "USER AGENT VALUE";
HttpWebRequest.Credentials = new NetworkCredential("admin", "pass");
WebResponse response = webRequest.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseText = reader.ReadToEnd();
The cast to HttpWebRequest is required so you have access to the UserAgent header field. Other standard HTTP fields can be accessed this way.
You can check which headers are sent by your browser of choice by inspecting its requests using the browser developer tools (usually Right click on webpage -> Inspect elements -> Network).
I figured it out with the help of some articles. A basic authentication needs to be added. Below is a sample.
var userName = "admin;"
var password = "password";
var encodedAuthentication = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(userName + ":" + password));
webRequest.Headers.Add("Authorization", "Basic " + encodedAuthentication);

Secure HttpWebRequest so I can send credentials possible?

I have the following code which connects to my php server and retrieves data from it. The only thing is, I need to send the username and password securely from this webrequest to the PHP server. Looking at the docs for the webrequest class, there is a credentials property as well as a preauthenticate property. I'm assuming these are for the network credentials (all my users are in AD).
Is it possible to secure this post request with credentials or is this just a bad idea? I've also found SetBasicAuthHeader - I'll read up on this and see if it might help. All traffic will be on SSL from ASPX site to the PHP site
// variables to store parameter values
string url = "https://myphpserver.php";
// creates the post data for the POST request
string postData = "Username=" + username + "&Password=" + "&UID=" + UniqueRecID;
// create the POST request
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = postData.Length;
// POST the data
using (StreamWriter requestWriter2 = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter2.Write(postData);
}
// This actually does the request and gets the response back
HttpWebResponse resp = (HttpWebResponse)webRequest.GetResponse();
string responseData = string.Empty;
using (StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()))
{
// dumps the HTML from the response into a string variable
responseData = responseReader.ReadToEnd();
}
SetBasicAuthHeader is for HTTP Basic Access Authentication so won't help here as you're handling authentication at application level. Really, this is no more insecure than just going to the page in a browser. I see you're using SSL so your request will be encrypted anyway and you have nothing to worry about.
If you're concerned for some other reason (although I can't think why), it sounds like you have control over the PHP end so you could just encrypt the password and add an extra POST parameter so the server knows to decrypt it.
When using HTTPS your data is safe in the message and transport scope. It means no one can decode it or sniff the packets. I suggest you read this article HTTPS Wiki

Twitter authorized / signed get request returing 401 not authorized

I'm trying to make an authorized get request to api.twitter.com/1/followers/ids.xml It keeps returning 401 not authorized. .Ive checked the header and base string against the ones generated in the OAuth tool in twitter developers app page and they are exactly the same. I've also tried changing the method to post instead of get to no avail.
here is the code:
ServicePointManager.Expect100Continue = false;
HttpWebRequest request =(HttpWebRequest)WebRequest.Create("http://api.twitter.com/1/followers/ids.xml");
request.Headers.Add(Uri.EscapeDataString("Authorization: "), authHeader);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
WebResponse response = request.GetResponse();
Is there a problem with the way I am sending the request?
You need to add either the screen_name or user_id of the twitter user you're interested in. For example: https://api.twitter.com/1/followers/ids.json?cursor=-1&screen_name=twitterapi

Can I send an empty HTTP POST WebRequest object from C# to IIS?

Do I need to just slap some random garbage data in a WebRequest object to get by the HTTP status code 411 restriction on IIS?
I have an HttpPost action method in an MVC 3 app that consumes a POST request with all the relevant information passed in the querystring (no body needed).
[HttpPost] public ActionResult SignUp(string email) { ... }
It worked great from Visual Studio's built in web host, Cassini. Unfortunately, once the MVC code was live on IIS [7.5 on 2008 R2], the server is pitching back an HTTP error code when I hit it from my outside C# form app.
The remote server returned an error:
(411) Length Required.
Here is the calling code:
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader responseReader = new StreamReader(responseStream)) {
// Do something with responseReader.ReadToEnd();
}
Turns out you can get this to go through by simply slapping an empty content length on the request before you send it.
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
request.ContentLength = 0;
Not sure how explicitly giving an empty length vs. implying one makes a difference, but IIS was happy after I did. There are probably other ways around this, but this seems simple enough.
I believe you are required to set a Content-Length header anytime you post a request to a web server:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.contentlength.aspx
You could try a GET request to test it.

Categories