Blazor application is getting Forbidden (403) when calling an external API (which works fine in PostMan) - outlook-restapi

Visual Studio 2019, .NET 3.0 preview, Created a blazor application. Trying to get weather data from https://api.weather.gov/gridpoints/ALY/59,14/forecast.
I am using HttpClient in C#. This is getting forbidden (403) response
Tried to add CORS policty
private async Task<IWeatherDotGovForecast> RetrieveForecast()
{
string url = #"https://api.weather.gov/gridpoints/ALY/59,14/forecast";
var response = await _httpClient.GetAsync(url);
if (response != null)
{
var jsonString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<WeatherDotGovForecast>(jsonString);
}
//return await _httpClient.GetJsonAsync<WeatherDotGovForecast>
// ("https://api.weather.gov/gridpoints/ALY/59,14/forecast");
return null;
}
I expected JSON data from https://api.weather.gov/gridpoints/ALY/59,14/forecast
Instead, I am getting Forbidden (403) status code

Your problem is not related to Blazor but weather.gov requires a User-Agent header in any HTTP request.
Applications accessing resources on weather.gov now need to provide a User-Agent header in any HTTP request. Requests without a user agent are automatically blocked. We have implemented this usage policy due to a small number of clients utilizing resources far in excess of what most would consider reasonable.
Use something like this:
var _httpClient = new HttpClient();
string url = #"https://api.weather.gov/gridpoints/ALY/59,14/forecast";
_httpClient.DefaultRequestHeaders.Add("User-Agent", "posterlagerkarte");
var response = await _httpClient.GetAsync(url);

Related

Revenuecat Webhook Issue

I have implemented webhook for revenuecat in .net core C#. But for some reason I am getting 400 badrequest with empty response. I am mostly sure that I am not getting the json response in webook through revenuecat for any of the event occurring.
I have also added endpoint on revenue cat webhook with authentication. I have tried several time and as I have not way to test this on local machine. I need help from revenue cat team to provide some reference doc with sample implementation just to get proper json response. Below is the code snippet that I am using to get json response from the webhook endpoint added in revenuecat.
var webHookSecret = _configuration[Constants.RevenueCatWebHookSecret]; var headerAuthorization = HttpContext.Request.Headers["Authorization"].ToString(); #region Check authorization if (webHookSecret == headerAuthorization) { json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); } else { _logger.Information($"Un-Authorized token access in revenuecat webhook. Returning BadRequest response."); throw new APIException(HttpStatusCode.Unauthorized, new APIError(_configuration, "InternalServerError")); }

Azure DevOps REST API call to Accounts-endpoint retrieves TF400813 error

I'm trying to read all accounts my user is associated with. The Documentation claims that this should be possible by calling:
GET https://app.vssps.visualstudio.com/_apis/accounts?api-version=5.1
Because the docs are kind of confusing it could be that I have to call
GET https://app.vssps.visualstudio.com/_apis/accounts?ownerId={GUID}&api-version=5.1
instead.
I'm using OAuth-Authentication. In order to get it work I created an ASP.NET Core application. I created an app registration in DevOps and I retrieve an OAuth token with the following scopes without any problem:
vso.auditlog
vso.connected_server
vso.dashboards
vso.entitlements
vso.environment_manage
vso.graph
vso.identity
vso.loadtest
vso.machinegroup_manage
vso.memberentitlementmanagement
vso.profile
vso.project
vso.securefiles_read
vso.security_manage
vso.taskgroups_read
vso.tokenadministration
vso.tokens
vso.variablegroups_read
vso.wiki
According to the docs only vso.profile should be necessary for this request.
However the result I receive is always:
HttpRequestException: Response status code does not indicate success: 401 (TF400813: The user '{AZURE_TENANT_ID}\{MY_MAIL_ADDRESS}' is not authorized to access this resource.).
Other requests are working just fine e.g.:
GET https://dev.azure.com/{organization}/{project}/_apis/build/builds?api-version=5.1
The accounts-request is special because it can be sent without setting the context to a specific organisation or project. I guess this the reason for the different results.
EDIT
After trying ot today using the both URLs mentioned above I now get 400 as the response status code. This is a sample Bearer-Token I got after I decoded it:
{
"nameid": "1340eb0b-cabf-476c-a950-a070c34ca367",
"scp": "vso.profile",
"aui": "a2d8bdf0-9406-415a-aa79-bee9e2600c37",
"appid": "e1bea2a2-****-****-****-************",
"iss": "app.vstoken.visualstudio.com",
"aud": "app.vstoken.visualstudio.com",
"nbf": 1587395030,
"exp": 1587398630
}
Here is some simplified C# code I use:
HttpClient client = _clientFactory.CreateClient("DevOps");
var token = await _authHelper.GetTokenAsync(tokenType);
client.DefaultRequestHeaders.Add("Authorization", $"Bearer { token.AccessToken}");
var uri = "https://app.vssps.visualstudio.com/_apis/accounts?api-version = 5.1";
try
{
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return content;
}
catch (Exception ex)
{
// ex.Message = Response status code does not indicate success: 400 (Bad Request).
// ...
throw;
}

Azure Text to Speech started returning "400 Bad Request" all the sudden

I was using Azure Text-to-Speech API succesfully for months with this format:
<speak version='1.0' xmlns='w3.org/2001/10/synthesis' xml:lang='en-US'><voice name='Microsoft Server Speech Text to Speech Voice (fi-FI, HeidiRUS)'>My text</voice></speak>
But suddenly this request started returning:
HTTP/1.1 400 Bad request
We were using the same request successfully for months (with different phrase of course) but just some weeks ago the same request started returning this error. I don't get any additional information so I don't know where to look. Azure documentation says:
A required parameter is missing, empty, or null. Or, the value passed
to either a required or optional parameter is invalid. A common issue
is a header that is too long.
I also tried making the request more specific by adding gender and language and replacing single quotes with double quotes, but no use:
<speak version="1.0" xmlns="w3.org/2001/10/synthesis" xml:lang="fi-FI" xml:gender="Female"><voice name="Microsoft Server Speech Text to Speech Voice (fi-FI, HeidiRUS)">Text.</voice></speak>
Did something change in the API? Or what is missing in my request?
I got a 200 OK with the right content when I send the following payload:
<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='en-US'><voice name='Microsoft Server Speech Text to Speech Voice (fi-FI, HeidiRUS)'>This is my test</voice></speak>
Here is my C# code to send this:
// Generate request
string body = $#"<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='{voiceLang}'><voice name='{voiceName}'>{text}</voice></speak>";
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage())
{
// Set the HTTP method
request.Method = HttpMethod.Post;
// Construct the URI
request.RequestUri = new Uri(ttsHostUri);
// Set the content type header
request.Content = new StringContent(body, Encoding.UTF8, "application/ssml+xml");
// Set additional header, such as Authorization and User-Agent
request.Headers.Add("Authorization", "Bearer " + accessToken);
request.Headers.Add("Connection", "Keep-Alive");
// Update your resource name
request.Headers.Add("User-Agent", "YOUR_RESOURCE_NAME");
request.Headers.Add("X-Microsoft-OutputFormat", "riff-24khz-16bit-mono-pcm");
// Create a request
using (var response = await client.SendAsync(request).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
// Asynchronously read the response
using (var dataStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
// ... Process your audio here
}
}
}
}
The only difference that I can see on our payloads is the xmlns value where I have a full url (with http://) whereas yours doesn't get it.
The error may be elsewhere: are you sure you are authenticating yourself when querying the endpoint?
We also suddenly got the 400 error and in our case we had missed to encapsulate the text for the XML request with
<![CDATA[ your text here ]]>
after we did that in our code we got no more reported 400 errors by the users.

Azure Microsoft Graph API - Subscription - validation request failed

I try to set up a notification for changes in Azure user data (https://learn.microsoft.com/en-us/graph/webhooks).
I send a request from a local client to the Azure Graph API and I have a publicly available server (with SSL) in the payload of the request as notification URL.
Azure now sends a posts request to my server (like in the documentation - exact post request see below) and I try to send the token I got back (like in the documentation). But I always get the following error message "Subscription validation request failed. Response must exactly match validationToken query parameter."
Post request from Azure:
Path: /?validationToken=Validation%3a+Testing+client+application+reachability+for+subscription+Request-Id%3a+3b3f9821-ce3f-23d9-879b-00a23f3
Body: is empty
I tried every part and encoding of the path (like just the request ID or the whole path) but I always get the error message. So whats the right thing to send back?
Firstly, the validation token you receive should be treated as an opaque value and returned unchanged and the error Subscription validation request failed. Response must exactly match validationToken query parameter is trying to tell you that something changed.
Since the validation token comes to you as a URL query parameter, make sure you're working with a properly decoded value in your code before returning it.
Here is the relevant documentation from Microsoft Docs: Notification endpoint validation
POST https://{notificationUrl}?validationToken={opaqueTokenCreatedByMicrosoftGraph}
Other requirements(from the same reference):
response within 10 seconds
200 (OK) status code.
content type must be text/plain.
body must include the validation token.
Code Samples
ASP.NET MVC Sample - Specifically look at the NotificationController.cs file
[HttpPost]
public async Task<ActionResult> Listen()
{
// Validate the new subscription by sending the token back to Microsoft Graph.
// This response is required for each subscription.
if (Request.QueryString["validationToken"] != null)
{
var token = Request.QueryString["validationToken"];
return Content(token, "plain/text");
}
Node.js code sample - Specifically look at listen.js
/* Default listen route */
listenRouter.post('/', (req, res, next) => {
let status;
let clientStatesValid;
// If there's a validationToken parameter in the query string,
// then this is the request that Office 365 sends to check
// that this is a valid endpoint.
// Just send the validationToken back.
if (req.query && req.query.validationToken) {
res.send(req.query.validationToken);
// Send a status of 'Ok'
status = 200;
}
You should return the validationToken from the query string with an HTTP 200 response code. You also have to do that within a few seconds, or the graph will fail the request and your call to create the subscription will fail.
Here is an example of the validation endpoint in ASP.NET Web API 2:
public ActionResult<string> Post([FromQuery]string validationToken = null)
{
if(!string.IsNullOrEmpty(validationToken))
{
Console.WriteLine($"Token: '{validationToken}'");
return Ok(validationToken);
}
}

(400) Bad Request on Azure server while communicating with service

I have a website and service in Azure webrole. The application uses a ServiceCommunicator class to communicate with the Service. The following code is working fine on my local machine..
private string _url;
public ServiceCommunicator(string url)
{
_url = url;
}
public object GetDataFromService()
{
//create request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url);
request.Method = "GET";
request.ContentLength = 0;
//get response
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
But when this is deployed on cloud (it uses Server 2008 R2 Enterprise) the code throws following exception
The remote server returned an error: (400) Bad Request.
I am unable to understand why is it happening as the code works properly on local machine.

Resources