REST Api is not returning expected data - azure

I wrote an Auth API where it should retrieve the details from my user, but I'm getting error 404 instead. All my users are stored in an Azure Storage Account, and I was using the TableClient class to handle with my table. However I am not able to go any further when I started to do this Auth. I spent over one week only on this function, and I got no progress on this, here is my code:
[FunctionName(nameof(Auth))]
public static async Task<IActionResult> Auth(
[HttpTrigger(AuthorizationLevel.Admin, "POST", Route = "auth")] HttpRequest req,
[Table("User", Connection = "AzureWebJobsStorage")] TableClient tdClient,
ILogger log)
{
string url = String.Format("http://localhost:7235/api/");
HttpMessageHandler handler = new HttpClientHandler()
{
};
var httpClient = new HttpClient(handler)
{
BaseAddress = new Uri(url),
Timeout = new TimeSpan(0, 2, 0)
};
httpClient.DefaultRequestHeaders.Add("ContentType", "application/json");
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes("roy.mitchel#somecompany.com:pass1234");
string val = System.Convert.ToBase64String(plainTextBytes);
httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + val);
HttpResponseMessage response = httpClient.GetAsync(url).Result;
return new OkObjectResult(response);
}
How can auth my user using this class? Iam doing on the right way?
Thanks.

Debugging any API issues by looking at just the code, is (as you have discovered) a horribly painful process.
I'd strongly recommend using a MITM proxy (like burp) to get visibility of exactly what is sent to, and received from the API. By using this approach, it generally becomes really obvious what is wrong.
If you can't use this approach, then enable logging for the raw HTTP request and response, as outlined in this guide.

Related

Azure Functions with SignalR: Unauthorized when trying to get access to SignalR Service

i am currently developing a real time analytic Dashboard with Stream Analytics -> Azure Functions -> SignalRService -> Angular Web App.
I am struggling when i want to authorize my function with the signalr service. Therefore i added the Connectionstring to my Appsettings. When i try to send a SignalRMessage, it says that i am unauthroized. Isnt it just setting the Connectionstring with the Accesskey in AppSettings of the Function?
Current Error:
Microsoft.Azure.SignalR.Common.AzureSignalRUnauthorizedException: 'Authorization failed. If you were using AccessKey, please check connection string and see if the AccessKey is correct. If you were using Azure Active Directory, please note that the role assignments will take up to 30 minutes to take effect if it was added recently. Request Uri: https://signalrtest2.service.signalr.net/api/v1/hubs/pa'
FunctionCode:
[FunctionName("CreateRealTimeAnalytics")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
[SignalR(HubName = "pa")] IAsyncCollector<SignalRMessage> signalRMessages)
{
// Extract the body from the request
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
if (string.IsNullOrEmpty(requestBody)) { return new StatusCodeResult(204); } // 204, ASA connectivity check
var data = JsonConvert.DeserializeObject<StreamUsageHeartbeatAnalytics>(requestBody);
var dataString = Newtonsoft.Json.JsonConvert.SerializeObject(data);
await signalRMessages.AddAsync(
new SignalRMessage
{
Target = "pa",
Arguments = new[] { dataString }
});
return new OkResult(); // 200
}
[FunctionName("Negotiate")]
public static SignalRConnectionInfo Negotiate(
[HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
[SignalRConnectionInfo(HubName = "pa")] SignalRConnectionInfo connectionInfo)
{
return connectionInfo;
}
To achieve the above requirement we have tried to add the below connection string format which is working fine So please make sure that you have provided proper Connection string with below format in your Appsettings.
Azure__SignalR__ConnectionString : Value(My connection string)
For more information please refer the below Links:-
MICROSOFT DOCUMENTATION - Azure Function SignalIR Bindings
SO THREAD:- Unable to read Azure SignalR Connection String from Azure App Service Configuration Application Settings

Client fails to show cookie sent by Azure Function App in browser storage

I have a function app that sets a cookie when reached:
[FunctionName("SendCookie")]
public async Task<HttpResponseMessage> SendCookie([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post","head", Route = null)] HttpRequest req, ILogger log)
{
var resp = new HttpResponseMessage();
var cookie = new CookieHeaderValue("cookieKey", "cookieValue");
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = "https://azurefunctionapp.azurewebsites.net";
cookie.Path = "/";
resp.Headers.AddCookies(new CookieHeaderValue[] {cookie});
return resp;
}
I can see in Fiddler the cookie is sent along with ARRAfinity. But I don't see it on firefox's browser storage:
Can someone share some guidance as to what i'm missing please?
thank you for your help
For this problem, you just need to remove cookie.Domain = "https://azurefunctionapp.azurewebsites.net";.
I test it in my side with the same code with yours'(but without cookie.Domain)
And the result show as below:
Or you can also set the domain as cookie.Domain = "azurefunctionapp.azurewebsites.net";(just remove the https://), it will also work fine.

Error "Exception while executing function" from Azure Service Bus Listener

We use an Azure Service Bus to post all of our requests from our Xamarin mobile app. The Azure Service Bus is bound to an Azure Function which is triggered each time a requests hits the Azure Service Bus.
We have found that we are getting errors from this Azure Function when we send data above a certain size. We can send up to 800 records without a problem but when we send >=850 records we get the following error:
[Error] Exception while executing function:
Functions.ServiceBusQueueTrigger. mscorlib: Exception has been thrown
by the target of an invocation. mscorlib: One or more errors occurred.
A task was canceled.
The service that is being invoked is an ASP.NET Web API RESTful service that saves the data records into a database. This doesn't generate any errors at all.
Here is my Azure Function code.
#r "JWT.dll"
#r "Common.dll"
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.ServiceBus.Messaging;
public static void Run(BrokeredMessage message, TraceWriter log)
{
log.Info($"C# ServiceBus queue trigger function processed message: {message.MessageId}");
if (message != null)
{
Common.Entities.MessageObjectEntity messageObject = message?.GetBody<Common.Entities.MessageObjectEntity>();
string msgType = messageObject?.MessageType;
var msgContent = messageObject?.MessageContent;
log.Info($"Message type: {msgType}");
double timestamp = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
string subscriber = "MYSUBSCRIBER";
string privatekey = "MYPRIVATEKEY";
Dictionary<string, object> payload = new Dictionary<string, object>()
{
{"iat", timestamp},
{"subscriber", subscriber}
};
string token = JWT.JsonWebToken.Encode(payload, privatekey, JWT.JwtHashAlgorithm.HS256);
using (var client = new HttpClient())
{
string url = $"http://myexamplewebservices.azurewebsites.net/api/routingtasks?formname={msgType}";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(subscriber, token);
HttpContent content = new StringContent((string)msgContent, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsync(new Uri(url), content);
if (response == null)
{
log.Info("Null response returned from request.");
}
else
{
if (response.Result.IsSuccessStatusCode && response.Result.StatusCode == System.Net.HttpStatusCode.OK)
{
log.Info("Successful response returned from request.");
}
else
{
log.Info($"Unsuccessful response returned from request: {response.Result.StatusCode}.");
}
}
}
log.Info("Completing message.");
}
}
This code has been working for several years and works across all our other apps / web sites.
Any ideas why we're getting errors wehen we post large amounts of data to our Azure Service Bus / Azure Function?
It may caused by "new httpclient", there is a limit to how quickly system can open new sockets so if you exhaust the connection pool, you may get some errors. You can refer to this link: https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
And could you please share some more error message ?
I can see that you are creating httpclient connection on each request which possibly be causing this issue. Httpclient creates a socket connection underneath it and has hard limit on it. Even when you dispose it it remains there for couple of mins that can't be used. A good practice is to create single static httpclient connection and reuse it. I am attaching some documents for you to go through.
AzFunction Static HttpClient , Http Client Working , Improper instantiation

.net core webapi causes iis application pool to shutdown

Background:
I'm building a .net core webapi does practically nothing more than checking if a given URL exists and returns the result. If a URL exists and is a redirect (301, 302), the api follows the redirect and returns that result as well. The webapi is called by an SPA which does an api-call for every given url in a checkrequest-queue. So, if someone adds 500 urls to the queue the SPA will loop through it and will send 500 calls to the API – something I could improve upon.
The problem:
My IIS application pool is being shut down on a regular basis due to high CPU usage and/or memory usage:
A worker process serving application pool 'api.domain.com(domain)(4.0)(pool)' has requested a recycle because it reached its private bytes memory limit.
The only way to get my API going again is to manually restart the application. I don't think the operations performed by the API are that demanding, but I surely must be doing something wrong here. Can somebody help me please? The code called by the SPA is:
var checkResponse = new CheckResponse();
var httpMethod = new HttpMethod(request.HttpMethod.ToUpper());
var httpRequestMessage = new HttpRequestMessage(httpMethod, request.Url);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
checkResponse.RequestMessage = httpResponseMessage.RequestMessage;
checkResponse.Headers = httpResponseMessage.Headers;
checkResponse.StatusCode = httpResponseMessage.StatusCode;
switch (httpResponseMessage.StatusCode)
{
case HttpStatusCode.Ambiguous:
case HttpStatusCode.Found:
case HttpStatusCode.Moved:
case HttpStatusCode.NotModified:
case HttpStatusCode.RedirectMethod:
case HttpStatusCode.TemporaryRedirect:
case HttpStatusCode.UseProxy:
var redirectRequest = new CheckRequest
{
Url = httpResponseMessage.Headers.Location.AbsoluteUri,
HttpMethod = request.HttpMethod,
CustomHeaders = request.CustomHeaders
};
checkResponse.RedirectResponse = await CheckUrl(redirectRequest);
break;
}
The Action on my ApiController:
[HttpPost]
public async Task<IActionResult> Post([FromBody] CheckRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await CheckService.CheckUrl(request);
return Ok(result);
}

Create custom extension through Graph API with Client Credentials auth

I have a .NET Web API that I am using to do some interaction with Microsoft Graph and Azure AD. However, when I attempt to create an extension on the user, it comes back with Access Denied.
I know it is possible from the documentation here however, it doesnt seem to work for me.
For the API, I am using client credentials. So my web app authenticates to the API using user credentials, and then from the API to the graph it uses the client.
My app on Azure AD has the Application Permission Read and Write Directory Data set to true as it states it needs to be in the documentation for a user extension.
I know my token is valid as I can retrieve data with it.
Here is my code for retrieving it:
private const string _createApprovalUrl = "https://graph.microsoft.com/beta/users/{0}/extensions";
public static async Task<bool> CreateApprovalSystemSchema(string userId)
{
using(var client = new HttpClient())
{
using(var req = new HttpRequestMessage(HttpMethod.Post, _createApprovalUrl))
{
var token = await GetToken();
req.Headers.Add("Authorization", string.Format("Bearer {0}", token));
req.Headers.TryAddWithoutValidation("Content-Type", "application/json");
var requestContent = JsonConvert.SerializeObject(new { extensionName = "<name>", id = "<id>", approvalLimit = "0" });
req.Content = new StringContent(requestContent, Encoding.UTF8, "application/json");
using(var response = await client.SendAsync(req))
{
var content = await response.Content.ReadAsStringAsync();
ApprovalSystemSchema schema = JsonConvert.DeserializeObject<ApprovalSystemSchema>(content);
if(schema.Id == null)
{
return false;
}
return true;
}
}
}
}
Is there anyone who may have a workaround on this, or information as to when this will be doable?
Thanks,
We took a look and it looks like you have a bug/line of code missing. You appear to be making this exact request:
POST https://graph.microsoft.com/beta/users/{0}/extensions
Looks like you are missing the code to replace the {0} with an actual user id. Please make the fix and let us know if you are now able to create an extension on the user.

Resources