Getting (401) UnAuthorized error on some requests not all, but most - authentication

I don't think this is a code issue, but we have a list of hundreds of addresses to process. Some return data and we are able to get Long and Lat but most return (401) UnAuthorized errors. What would cause this to happen? We have tried passing Host Headers and everything else, the REST API seems to work better in our development environment but throws way more errors when deployed to our Job Server. Any help on this issue will be greatly appreciated. We would like to understand why some calls work and others don't, we pass the same apiKey each time so this is really confusing. Thanks
Here is a code snippet using c# (Work in progress):
//GET THE LATITUDE AND LONGITUDE BASED OFF THE PHYSICAL ADDRESS
String clientAddress = clientRow["home_address"].ToString() + ", " + clientRow["home_city"].ToString() + ", " + clientRow["home_state"].ToString() + ", " + clientRow["home_zip"].ToString();
Logger.Debug("CLIENT ADDRESS: {0}", clientAddress);
String geocoderUri = "https://geocode.search.hereapi.com/v1/geocode?q=" + clientAddress + "&apiKey=xxxxxxxxxxxxxxxxxxxxx"; //KEY REMOVED FOR POSTING ON STACK OVERFLOW
var syncClient = new WebClient();
var content = syncClient.DownloadString(geocoderUri);
//CREATE THE JSON SERIALIZER AND PARSE OUR RESPONSE
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AddressData));
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(content)))
{
var addressData = (AddressData)serializer.ReadObject(ms);
if (addressData.items.Count() > 0)
{
//INSERT THE LATITUDE AND LONGITUDE IN DB
String sLat = addressData.items[0].position.lat.ToString();
String sLong = addressData.items[0].position.lng.ToString();
Logger.Debug("CLIENT GEOLOCATION - Longitude: {0} Latitude: {1}", sLong, sLat);
insertLatLong(sLat, sLong, clientRow["clientID"].ToString(), 1);
}
}

Would you please try to use RestSharp lib for rest api?
Please see below sample code.
var client = new RestClient("https://geocode.search.hereapi.com/v1/geocode?q="+ clientAddress);
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer YOUR TOKEN");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

Related

The service is not available received when calling MS Graph API

We are doing a MS Graph API call to get the Sharepoint URL of a Team.
API URL: GET https://graph.microsoft.com/v1.0/groups/{GroupID}/sites/root/weburl
We get this :
Response:
{
"error": {
"code": "serviceNotAvailable",
"message": "The service is not available. Try the request again after a delay. There may be a Retry-After header.",
"innerError": {
"request-id": "9f23d067-e851-4c43-8701-abe137683b87",
"date": "2020-03-05T13:53:43"
}
}
}
What could be the issue?
I have been experiencing a similar problem in searching sites ( GET /sites?search=* ) with the Graph API since March 2nd. I have not been able to recover. I have experienced this over multiple O365 tenants, both free and licensed.
Microsoft docs say this error code is due to MSFT induced throttling, but my request rate is like 50 per hour.
This seems to be a Microsoft bug. I posted a stack overflow issue for this and #rafa-ayadi reported that MSFT was fixing it their side for one of his customers.
I bought an Azure Developer Support subscription for this issue, but MSFT closed it and referred me to Sharepoint Developer Support, for which I can find no link or pricing. So no luck yet in getting MSFT to acknowledge and fix for me.
/**
You need do authentication delegated. See the follow code:
First of all you need from portal.azure.com register app and get:
folder id it is tenantID
App Id. it is clientId
**/
URL urlObj = new
URL("https://login.microsoftonline.com/"+config.tenantID+"/oauth2/v2.0/token");
HttpURLConnection httpCon = (HttpURLConnection) urlObj.openConnection();
String urlParameters = "" + // para la v2.0
"grant_type"+"="+"password"+"&"+ /
"scope" + "=" + "https%3A%2F%2Fgraph.microsoft.com%2F.default" +"&" +
"client_id" + "=" + config.clientId +"&" +
"client_secret" + "=" + config.clientSecret +"&" +
"username" + "=" + config.username +"&" +
"password" + "=" + config.contrasena +"&";
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
int postDataLength = postData.length;
httpCon.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpCon.setRequestProperty("Content-Length",String.valueOf(postDataLength));
httpCon.setRequestMethod("POST");
httpCon.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(httpCon.getOutputStream());
writer.write(urlParameters);
writer.flush();
int status = httpCon.getResponseCode();
BufferedReader in = new BufferedReader(new
InputStreamReader(httpCon.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
String body = getBody(content.toString());
String token = null;
final ObjectNode node = new ObjectMapper().readValue(body, ObjectNode.class);
if (node.has("access_token")) {
token = node.get("access_token").asText();
}
httpCon.disconnect();
return token;
My similar problem accessing any resource in the sites API was caused by having both the Groups.Create and Groups.ReadWrite.All permissions granted at the same time for application type access.
Removing Groups.Create allowed the all CRUD calls to be successful without serviceNotAvailable errors, even command line calls that just access sites.
Be sure to update admin grant and your token if you change the permissions for a test.
User #user13034886 mentioned the permission clash in another post.

c# console application returning no results

This code runs fine in my windows form application using .net framework 4.6.2 but when I go to make it a console application so it can be ran from the task scheduler I get no results. I think I am losing something in translation.
RestClient restClient = new RestClient("https://api.vault.com");
string refreshToken = #"abc";
string encodedClientIdSecret = Base64Encode("AP-123");
string responseStr = "";
string url = "/v1/OAuth";
dynamic jsonObj = "";
RestRequest request = new RestRequest(url, Method.POST);
request.AddHeader("Authorization", encodedClientIdSecret);
request.AddParameter("grant_type", "refresh_token");
request.AddParameter("refresh_token", refreshToken);
IRestResponse response;
restClient.Execute(request);
response = restClient.Execute(request);
Console.WriteLine(response.Content + " || " + encodedClientIdSecret);
Console.ReadKey();
jsonObj = JsonConvert.DeserializeObject(response.Content);
responseStr = jsonObj.access_token;
return responseStr;
It basically tells me the value cannot be null, and when I look at response.Content I get nothing and the status code comes back as "0". Any thoughts?
Just added:
//Required For SSL/TLS Error Start
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
//Required For SSL/TLS Error End
and I got my results. Hope this helps someone else!

Pentaho - upload file using API

I need to upload a file using an API.
I tried REST CLIENT and didn't find any options.
Tried with HTTP POST and that responded with 415.
Please suggest how to accomplish this
Error 415 is “Unsupported media type”.
You may need to change the media type of the request or check whether that type of file us accepted by the remote server.
https://en.m.wikipedia.org/wiki/List_of_HTTP_status_codes
This solution uses only standard classes of jre 7. Add a step Modified Java Script Value in your transformation. You will have to add two columns in the flow: URL_FORM_POST_MULTIPART_COLUMN and FILE_URL_COLUMN, you can add as many files as you want, you will just have to call outputStreamToRequestBody.write more times.
try
{
//in this step you will need to add two columns from the previous flow -> URL_FORM_POST_MULTIPART_COLUMN, FILE_URL_COLUMN
var serverUrl = new java.net.URL(URL_FORM_POST_MULTIPART_COLUMN);
var boundaryString = "999aaa000zzz09za";
var openBoundary = java.lang.String.format("\n\n--%s\nContent-Disposition: form-data\nContent-Type: text/xml\n\n" , boundaryString);
var closeBoundary = java.lang.String.format("\n\n--%s--\n", boundaryString);
// var netIPSocketAddress = java.net.InetSocketAddress("127.0.0.1", 8888);
// var proxy = java.net.Proxy(java.net.Proxy.Type.HTTP , netIPSocketAddress);
// var urlConnection = serverUrl.openConnection(proxy);
var urlConnection = serverUrl.openConnection();
urlConnection.setDoOutput(true); // Indicate that we want to write to the HTTP request body
urlConnection.setRequestMethod("POST");
//urlConnection.addRequestProperty("Authorization", "Basic " + Authorization);
urlConnection.addRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundaryString);
var outputStreamToRequestBody = urlConnection.getOutputStream();
outputStreamToRequestBody.write(openBoundary.getBytes(java.nio.charset.StandardCharsets.UTF_8));
outputStreamToRequestBody.write(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(FILE_URL_COLUMN)));
outputStreamToRequestBody.write(closeBoundary.getBytes(java.nio.charset.StandardCharsets.UTF_8));
outputStreamToRequestBody.flush();
var httpResponseReader = new java.io.BufferedReader(new java.io.InputStreamReader(urlConnection.getInputStream()));
var lineRead = "";
var finalText = "";
while((lineRead = httpResponseReader.readLine()) != null) {
finalText += lineRead;
}
var status = urlConnection.getResponseCode();
var result = finalText;
var time = new Date();
}
catch(e)
{
Alert(e);
}
I solved this by using the solution from http://www.dietz-solutions.com/2017/06/pentaho-data-integration-multi-part.html
Thanks Ben.
He's written a Java class for Multi-part Form submission. I extendd by adding a header for Authorization...

Using Twitter login API

I am trying to use https://api.periscope.tv/api/v2/loginTwitter to get a response from the server so that I can obtain a cookie for periscope API calls.
I have all of the required values for the request query, but I continue to get the "Bad Request" error (error code 400). Is anyone able to use the loginTwitter API still?
Request headers:
POST /api/v2/loginTwitter?bundle_id=com.bountylabs.periscope&phone_number=&session_key=xxxxxxxx&session_secret=xxxxxxxx&user_id=xxxxxxxx&user_name=xxxxxxxx&vendor_id=81EA8A9B-2950-40CD-9365-40535404DDE4 HTTP/1.1
Authorization:
OAuth oauth_consumer_key="xxxxxxxx",oauth_nonce="cecf203cda273c845cd5121007232666",oauth_signature="xxxxxxxx%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1474786616",oauth_token="xxxxxxxx",oauth_version="1.0"
Oauth signature:
POST&https%3A%2F%2Fapi.periscope.tv%2Fapi%2Fv2%2FloginTwitter%3Fbundle_id%3Dcom.bountylabs.periscope%26phone_number%3D%26session_key%xxxxxxxx%26session_secret%3xxxxxxxx%26user_id%3xxxxxxxx%26user_name%xxxxxxxx%26vendor_id%3D81EA8A9B-2950-40CD-9365-40535404DDE4&bundle_id%3Dcom.bountylabs.periscope%26oauth_consumer_key%3xxxxxxxx%26oauth_nonce%3Dcecf203cda273c845cd5121007232666%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1474786616%26oauth_token%xxxxxxxx%26oauth_version%3D1.0%26phone_number%3D%26session_key%xxxxxxxxMX%26session_secret%xxxxxxxxt%26user_id%xxxxxxxx4%26user_name%xxxxxxxx%26vendor_id%3D81EA8A9B-2950-40CD-9365-40535404DDE4
I have solved the problem thanks to help from another. The problem was that I was passing the request parameters in the URL without encoding them into json. For any that are looking to resolve this problem, here is the solution I arrived at with c#.
var httpWebRequest = ( HttpWebRequest )WebRequest.Create( "https://api.periscope.tv/api/v2/loginTwitter" );
httpWebRequest.ContentType = "application/json; charset=UTF-8";
httpWebRequest.Method = "POST";
using( var streamWriter = new StreamWriter( httpWebRequest.GetRequestStream() ) ){
string json = "{" +
"\"bundle_id\":\"com.bountylabs.periscope\"," +
"\"phone_number\":\"\"," +
"\"session_key\":\""+final_oauth_token+"\"," +
"\"session_secret\":\""+final_oauth_token_secret+"\"," +
"\"user_id\":\""+user_id+"\"," +
"\"user_name\":\""+screen_name+"\"," +
"\"vendor_id\":\"81EA8A9B-2950-40CD-9365-40535404DDE4\"" +
"}";
streamWriter.Write( json );
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = ( HttpWebResponse )httpWebRequest.GetResponse();
using( var streamReader = new StreamReader( httpResponse.GetResponseStream() ) ){
var result = streamReader.ReadToEnd();
display.Text = "cookie: "+result;
}
}
The result yields a cookie in the server's response.
Reference for more detail on this process: Twitter login POST request in Periscope API

How do I add just a username within an authentication header in stripe-payments?

I'm trying to get a simple post request to work to create a customer via the Stripe.js API.
https://stripe.com/docs/api/java#authentication
I'm doing this in vb.net and don't want to use the stripe.net library.
I keep getting authorization failed. All I have to pass is the username in the header, or in this case the username is my test api key.
Here's a chunk of the code:
Dim asPostRequest As HttpWebRequest = WebRequest.Create(String.Format(ApiEndpoint))
Dim as_ByteArray As Byte() = Encoding.UTF8.GetBytes(stripeccw.ToString)
asPostRequest.Method = "POST"
asPostRequest.ContentType = "application/json"
'asPostRequest.Headers("Authorization") = "Basic" + apikey
'asPostRequest.Credentials("bearer", apikey)
'asPostRequest.Headers.Add("Authorization") = apikey
'asPostRequest.Credentials("Username") = apikey
'asPostRequest.Credentials = New NetworkCredential(apikey, "")
asPostRequest.ContentLength = as_ByteArray.Length
Dim as_DataStream As Stream = asPostRequest.GetRequestStream()
as_DataStream.Write(as_ByteArray, 0, as_ByteArray.Length)
as_DataStream.Close()
Where I've commented out... those are different ways that I've tried. I know some are just stupid attempts, but just getting frustrated. I know for a fact my api key is correct. I can verify this by navigating to https://api.stripe.com/v1/customers and entering it in for my username only.
Hoping someone can spot something simple :)
Thank you!
If I were in your shoes, the first thing I'd do is take a look at how Stripe.Net does it. Even if you don't want to use that library yourself, that doesn't mean you can't use the source code as a reference.
From Requestor.cs:
internal static WebRequest GetWebRequest(string url, string method, string apiKey = null, bool useBearer = false)
{
apiKey = apiKey ?? StripeConfiguration.GetApiKey();
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method;
if(!useBearer)
request.Headers.Add("Authorization", GetAuthorizationHeaderValue(apiKey));
else
request.Headers.Add("Authorization", GetAuthorizationHeaderValueBearer(apiKey));
request.Headers.Add("Stripe-Version", StripeConfiguration.ApiVersion);
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "Stripe.net (https://github.com/jaymedavis/stripe.net)";
return request;
}
private static string GetAuthorizationHeaderValue(string apiKey)
{
var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:", apiKey)));
return string.Format("Basic {0}", token);
}
private static string GetAuthorizationHeaderValueBearer(string apiKey)
{
return string.Format("Bearer {0}", apiKey);
}
So it seems there are two ways to do it. You can either use "Bearer" format, which is:
asPostRequest.Headers.Add("Authorization", "Bearer " & apiKey)
or you can use "Basic" format which is:
asPostRequest.Headers.Add("Authorization", _
"Basic " & Convert.ToBase64String(Encoding.UTF8.GetBytes(apiKey & ":")))