Error geting location data from latitude and longitude on Bingmaps - c#

I'm using Bingmaps API to get the AdminDistrict and CountryRegion of a Latitude and Longitude.
It works entering in a browser to this url:
http://dev.virtualearth.net/REST/v1/Locations/-30,-70/?includeEntityTypes=AdminDivision1,CountryRegion&o=xml&c=es-ES&key=myBingmapsApiKey
But in C# on WP7 I can't get get it work.
This is the code:
string wsUrl = "http://dev.virtualearth.net/REST/v1/Locations/-30,-70/?includeEntityTypes=AdminDivision1,CountryRegion&o=xml&c=es-ES&key=*myBingmapsApiKey*";
var request = new RestSharp.RestRequest(Method.GET);
var client = new RestSharp.RestClient(wsUrl);
try
{
RestSharp.RestResponse resource;
client.ExecuteAsync(request, (response) =>
{
resource = response;
string content = resource.Content;
string status_code = resource.StatusCode.ToString();
string response_status = resource.ResponseStatus.ToString();
});
}
catch (Exception e)
{
string error = "Error: " + e.ToString() + "\n. Stack Trace: " + e.StackTrace;
}
And the response is:
<?xml version="1.0" encoding="utf-8"?>
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">
<Copyright>Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
<BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
<StatusCode>401</StatusCode><StatusDescription>Unauthorized</StatusDescription>
<AuthenticationResultCode>InvalidCredentials</AuthenticationResultCode>
<ErrorDetails><string>Access was denied. You may have entered your credentials incorrectly, or you might not have access to the requested resource or operation.</string></ErrorDetails>
<TraceId>59ebcf604bb343d79a6e8b93ad5695fe|MIAM001452|02.00.71.1600|</TraceId>
<ResourceSets />
</Response>
The url is the same that is working on web browser.
What can be wrong?

probably at this point you already came up with a solution but searching on google i found this topic and the solution is to not send the key through the url like you doing, instead add it as parameter in the request like this:
string wsUrl = "http://dev.virtualearth.net/REST/v1/Locations/-30,-70/";
var request = new RestSharp.RestRequest(Method.GET);
request.AddParameter("includeEntityTypes", "AdminDivision1,CountryRegion");
request.AddParameter("key", myLey);
request.AddParameter("o", "xml");

If I understand this right then the REST API you use may cost money. Maybe your API key istn't set up for billable transactions?
The page says about billing of Location API:
*This category is not billable if it occurs within the context of an AJAX Control or Silverlight Control session.
Maybe the browser counts as AJAX control and the phone isn't exactly a "Silverlight Control".

Related

Impersonation and potential Kerberos Double-Hop in Dotnet Core API

I'm trying to get an API to pass client credentials through to the database (on a different server) but experiencing something that smells very much like a Kerberos double-hop issue to me, however the systems people say that Kerberos delegation is set up appropriately on the servers in question. Below is a method I wrote to test this, and at the bottom is the response body I get in Postman when sending my own credentials to the API via NTLM. I get a similar response when shipping the credentials of another account I have access to. When shipping credentials I know to be bad, IIS stops my request & responds with a 401 without sending the request to the API; this is expected and required.
What can be causing this other than a Kerberos double-hop? Is there a flaw in my implementation of impersonation? I don't have access to either server in question, but I can supply the entire ugly exception encountered by the controller if needed.
/// <summary>
/// This endpoint should not support PUT. This method is simply a means by which to test impersonation
/// </summary>
[HttpPut]
public IActionResult PutMethod()
{
var bogusPutResult = new ImpersonationResult();
if (!(this.User.Identity is WindowsIdentity user)) return Problem("Cannot authenticate user");
var row1 = _myDbContext.MyTable.Find(1);
bogusPutResult.BeforeImpersonation = $"{WindowsIdentity.GetCurrent().Name} got a row with value {row1.Value}";
WindowsIdentity.RunImpersonated(user.AccessToken, () =>
{
string message;
try
{
var row2 = _myDbContext.MyTable.Find(2); // All domain users have SELECT access
message = $" got a row with value {row2.Value}";
}
catch (Exception e)
{
message = $" ate this: {e.GetType()}--{e.Message}";
}
bogusPutResult.DuringImpersonation = $"{WindowsIdentity.GetCurrent().Name} {message}";
});
bogusPutResult.AfterImpersonation = WindowsIdentity.GetCurrent().Name;
return Ok(bogusPutResult);
}
And the JSON returned by the API...
{
"BeforeImpersonation": "MYDOMAIN\\srv-apiserviceaccount got a row with value 34 ",
"DuringImpersonation": "MYDOMAIN\\finglixon ate this: Microsoft.Data.SqlClient.SqlException--Login failed for user 'NT AUTHORITY\\ANONYMOUS LOGON'.",
"AfterImpersonation": "MYDOMAIN\\srv-apiserviceaccount"
}

Verifying token using firebase admin SDK in .net - exeption: 'Incorrect number of segments in $ID token.'

I'm building a Web.API to send notifications to iOS application via Firebase. I have integrated the Firebase admin SDK in .net project. As per the https://firebase.google.com/docs/reference/admin/dotnet, I implemented the below code. However I get an error when I call "VerifyIdTokenAsync". The error is "Incorrect number of segments in $ID token."
var defaultApp = FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile(strFilePath),
});
// Retrieve services by passing the defaultApp variable...
var defaultAuth = FirebaseAuth.GetAuth(defaultApp);
FirebasVerifyIdTokenAsynceToken decodedToken = await defaultAuth.(deviceToken);
string uid = decodedToken.Uid;
I checked several post and documentation online but all refer to the same code with no much further troubleshooting information. Please help.
An ID token (which is a type of JWT) must have exactly 3 segments, separated by periods: header.body.signature. The above error message is saying that the string you're passing as the ID token has some other number of segments. So your input string is not an ID token at all.
Thank you Hiranya Jayathilaka. You are right. I was using the APNS token instead of the registration token ID. I followed this article to fetch the registration token ID.
We need to make a post request to
https://iid.googleapis.com/iid/v1:batchImport
Set headers to
Content-Type:application/json Authorization:key=YOUR_SERVER_KEY
And the body will contain the below
{
"application": YOUR_APPLICATION_BUNDLE_ID,
"sandbox":false,
"apns_tokens":[
YOUR_APNS_TOKEN,
] }
Also, when you make a call to the
https://fcm.googleapis.com/fcm/send
and you are sending push notification to a single device you should use the below JSON
string json = "{\"to\": \"" + regID + "\",\"notification\": {\"title\": \"New deal\",\"body\": \"20% deal!\"},\"priority\":10}";
If you are sending push notification to multiple devices, use the below JSON
string json = "{\"registration_ids\": [\"" + regID1 + "\", \"" + regID2 + "\" \"" + regIDN + "\"],\"notification\": {\"title\": \"New deal\",\"body\": \"20% deal!\"},\"priority\":10}";
Finally, I have my push notifications on my phone!

AWS S3 Presigned URL Get returning ListBucketResult instead

I am trying to get a presigned URL to access an image in my private bucket, by using the GetPreSignedUrlRequest method.
My code is as follows:
public string GetPresignedImageURL(string keyString)
{
string urlString = "";
try
{
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
{
BucketName = bucket,
Key = keyString,
Expires = DateTime.Now.AddMinutes(5)
};
urlString = _client.GetPreSignedURL(request);
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
return urlString;
}
I passed in the key of the object I am getting e.g. 0BE1137F0F3E4703A0F0689346B49871_0.jpg.
However, this is the response URL I get. It did not append the object's key to the response, only the signature headers.
https://<bucket>.ap-southeast-1.amazonaws.com/?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<credential>/20190701/ap-southeast-1/s3/aws4_request&X-Amz-Date=20190701T065534Z&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature>
If I paste this link into the browser, it shows that it is a ListBucketResult request.
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>bucket</Name>
<Prefix/>
<Marker/>
<MaxKeys>1000</MaxKeys>
<IsTruncated>false</IsTruncated>
<Contents>
<Key>0BE1137F0F3E4703A0F0689346B49871_0.jpg</Key>
<LastModified>2019-07-01T06:52:17.000Z</LastModified>
<ETag>"89db9b468ba0eb45600ed9603fe9f41d"</ETag>
<Size>1621409</Size>
<Owner>...</Owner>
<StorageClass>STANDARD</StorageClass>
</Contents>
<Contents>
<Key>18F6F2B700A747F983DB26EBC8F3E92F_0.jpg</Key>
<LastModified>2019-06-28T08:44:40.000Z</LastModified>
<ETag>"61aa2a6270ec840b185331646ee884a2"</ETag>
<Size>88703</Size>
<Owner>...</Owner>
<StorageClass>STANDARD</StorageClass>
</Contents>
</ListBucketResult>
I am not sure if this is a bug, or if I am missing something here. I would like to know how I can get the presigned URL of the image to either display in the browser or as a direct download link (using content-disposition, which didn't work either) instead of the bucket's keys list. Thank you!
Check your keyString variable. Print it out before sending the request so that you are sure it isn't null. The only difference between the get presigned url for single object vs get presigned url for listing all objects is the Key that you send as a parameter.
See more here: https://docs.aws.amazon.com/sdkfornet1/latest/apidocs/html/T_Amazon_S3_Model_GetPreSignedUrlRequest.htm

Referral Url's on Facebook Page tab

I have a Facebook Page Tab app and I'm trying to find out where visitors to the page tab are coming from. I've read on http://developers.facebook.com/docs/authentication/signed_request/ that you can get these from app_data in the signed request but whenever I try getting the signed request app_data isn't there.
I used FB.getLoginStatus to get the signed request when inside the tab on Facebook, but
When I debug the signed request with http://developers.facebook.com/tools/echo I get the error "Bad Signature"
Your signed_request was probably not signed with our app_id of xxxxx Here is the payload:
{
"algorithm": "HMAC-SHA256",
"code": "xxxx",
"issued_at": xxxx,
"user_id": "xxxx2"
}
I'm using the C# SDK with Javascript
You can decode the signed request with the code in this topic:
Decode Signed Request Without Authentication
if (Request.Params["signed_request"] != null)
{
string payload = Request.Params["signed_request"].Split('.')[1];
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var o = JObject.Parse(json);
var lPid = Convert.ToString(o.SelectToken("page.id")).Replace("\"", "");
var lLiked = Convert.ToString(o.SelectToken("page.liked")).Replace("\"", "");
var lUserId= Convert.ToString(o.SelectToken("user_id")).Replace("\"", "");
}
It should be easy to get the app_data by adding
var lAppData = Convert.ToString(o.SelectToken("app_data")).Replace("\"", "");
To the have the app_data for your tab app you need to add it to the redirect url when acquiring permissions. You redirect url should something like:
http://facebook.com/YOUR_PAGE?sk=app_YOUR_APP_ID&app_data=add,whatever,parameters,you,want,here
I can only guess that the reason you got this error is because you just pasted your signed request in the address bar instead of the one used by the echo tool. The error is because your signed request is signed by your app_id and you're trying to use it with echo which has another app_id. But that's just a guess :)
My primary language is PHP but hope I was able to help :)

Creating new album in picasa in .NET

I am trying to post an album to picasa, but always get "bad request" response.
Should I use HttpRequest class instead?
System.Net.WebClient wc = new System.Net.WebClient();
wc.Headers.Add("Authorization", "AuthSub token=\"" + token + "\"");
wc.Headers.Add("GData-Version", "2");
string data = "<entry xmlns='http://www.w3.org/2005/Atom' " +
"xmlns:media='http://search.yahoo.com/mrss/' " +
"xmlns:gphoto='http://schemas.google.com/photos/2007'>" +
"<title type='text'>" + name + "</title>" +
"<summary type='text'>" + descr + "</summary>" +
"<gphoto:location>asd</gphoto:location>" +
"<gphoto:access>" + access + "</gphoto:access>" +
"<gphoto:timestamp>1152255600000</gphoto:timestamp>" +
"<media:group>" +
"<media:keywords>adds</media:keywords>" +
"</media:group>" +
"<category scheme='http://schemas.google.com/g/2005#kind' " +
"term='http://schemas.google.com/photos/2007#album'></category>" +
"</entry>";
try
{
string response = wc.UploadString("https://picasaweb.google.com/data/feed/api/user/default", "post", data);
return response;
}
catch (Exception e)
{
return e.ToString();
}
Google makes a handy api for picasa [.net] integration:
http://code.google.com/apis/picasaweb/docs/1.0/developers_guide_dotnet.html
No sense writing all that code by hand!
Here is some code (vb.net, but it's straightforward):
Public Shared Function CreateAlbum(ByVal albumTitle As String) As AlbumAccessor
Dim newAlbum As New AlbumEntry()
newAlbum.Title.Text = albumTitle
Dim ac As New AlbumAccessor(newAlbum)
ac.Access = "public"
Dim feedUri As New Uri(PicasaQuery.CreatePicasaUri(ConfigurationManager.AppSettings("GData_Email")))
Dim albumEntry As PicasaEntry = CreateAuthenticatedRequest().Insert(feedUri, newAlbum)
Return New AlbumAccessor(albumEntry)
End Function
Public Shared Function CreateAuthenticatedRequest() As PicasaService
Dim service As New PicasaService(ConfigurationManager.AppSettings("GData_AppName"))
service.setUserCredentials(ConfigurationManager.AppSettings("GData_Email"), ConfigurationManager.AppSettings("GData_Password"))
Return service
End Function
I know this is older so you may already have an answer. I also know that Google does make an API but with .net it only works for the first version of Picasa and you are trying to work with version two, as am I. I came across your post and thought I would offer an answer for you in case you are still trying to work this out or someone else comes across the post and wants an answer.
I see a couple of things that may be causing your issue. The first is that you seem to be mixing and matching the authentication protocol with the version. For the second version of the Google Picasa API, I believe you need to be using OAuth2 protocol, not AuthSub protocol. I haven't tried with AuthSub. The second issue is that I do not believe you have enough information in your headers (missing content-length, content-type, and host[although you may not need host when using a webclient]). One way that I've found to make sure that my requests are working well (and honestly has been a lifesaver) is to go to the OAuth2Playground on Google: Oauth2Playground. Here you can create your tokens and requests and easily see their headers and post information when successful requests are made.
Here is a snippet of code that I wrote which allows for creation of an album. In order to create, you must have an authenticated token with an access code (you would want to first get user permissions and store their refresh token and then refresh to get the session access_token) The access_token is passed in the authorization line of the header. It also parses the response and gets a success variable from the response as well as the albumid. The entire xml feed for the album is returned on response, so you could go into the detail of reading that in and working with it directly if you wanted)
public bool CreatePicasaAlbum(GoogleUtility.Picasa.AlbumEntry.entry a, IGoogleOauth2AccessToken token)
{
TcpClient client = new TcpClient(picasaweb.google.com, 443);
Stream netStream = client.GetStream();
SslStream sslStream = new SslStream(netStream);
sslStream.AuthenticateAsClient(picasaweb.google.com);
byte[] contentAsBytes = Encoding.ASCII.GetBytes(a.toXmlPostString());
string data = a.toXmlPostString();
StringBuilder msg = new StringBuilder();
msg.AppendLine("POST /data/feed/api/user/default HTTP/1.1");
msg.AppendLine("Host: picasaweb.google.com");
msg.AppendLine("Gdata-version: 2");
msg.AppendLine("Content-Length: " + data.Length);
msg.AppendLine("Content-Type: application/atom+xml");
msg.AppendLine(string.Format(GetUserInfoDataString(), token.access_token));
msg.AppendLine("");
byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString());
sslStream.Write(headerAsBytes);
sslStream.Write(contentAsBytes);
StreamReader reader = new StreamReader(sslStream);
bool success = false;
string albumID = "";
while (reader.Peek() > 0)
{
string line = reader.ReadLine();
if (line.Contains("HTTP/1.1 201 Created")) { success = true; }
if (line.Contains("Location: https") && string.IsNullOrWhiteSpace(albumID))
{
var aiIndex = line.LastIndexOf("/");
albumID = line.Substring(aiIndex + 1);
}
System.Diagnostics.Debug.WriteLine(line);
if (line == null) break;
}
return success;
}
/// <summary>
/// User Info Data String for Authorization on TCP requests
/// [Authorization: OAuth {0}"]
/// </summary>
/// <returns></returns>
private string GetUserInfoDataString()
{
return "Authorization: OAuth {0}";
}
Sorry, I should add that I created an object that returns the feed string for the album entry xml as you had above. The feed xml matches the documentation. I leave the timestamp blank as the default stamp is when you create it, and I've not figured out what if anything can be put in category so I leave that blank too.
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gphoto='http://schemas.google.com/photos/2007'>
<title type='text'>Created from code</title>
<summary type='text'>Code created this album</summary>
<gphoto:location>somewhere</gphoto:location>
<gphoto:access>public</gphoto:access>
<gphoto:timestamp></gphoto:timestamp>
<media:group>
<media:keywords>test, album, fun</media:keywords>
</media:group>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'>
</category>
</entry>
One other edit: The IGoogleOauth2AccessToken is another class I created to house the token details. What you really need passed in is the access_token string that you get when you refresh the OAuth2 token. My token housing code just has the access_code, token_type, and expires as part of the object. You just need the access token string for the authorization.

Categories

Resources