Calling Asp.Net Web API endpoint from Azure function - c#

I am trying to develop following scenario using Azure functions.
I have developed Asp.Net Web API which handles the Database related operation. Now, I want to implement a scheduler like functionality which will run once a day and will clean up junk data from database. I've created an endpoint for that in my Web API but I want to execute it on regular basis so I think to implement scheduler using Azure function's TimerTrigger function, is there any way to call my web api's endpoint in TimerTrigger function.
How to handle my api's authentication in Azure function?
Thanks
Update:
Based on mikhail's answer, finally I got the token using following code:
var client = new HttpClient();
client.BaseAddress = new Uri(apirooturl);
var grant_type = "password";
var username = "username";
var password = "password";
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", grant_type),
new KeyValuePair<string, string>("username", username),
new KeyValuePair<string, string>("password", password)
});
var token = client.PostAsync("token", formContent).Result.Content.ReadAsAsync<AuthenticationToken>().Result;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(token.token_type, token.access_token);
var response = await client.GetAsync(apiendpoint);
var content = await response.Content.ReadAsStringAsync();

Azure Function is running in a normal Web App, so you can do pretty much anything there. Assuming you are on C#, the function body might looks something like
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
var response = await client.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();

You may be better off putting the entire database cleanup logic in the function and making it timer triggered, that way you keep your API out of it altogether.

Related

How to POST to a specific URL using the Microsoft Graph Client

I'm trying to send a POST request to the following URL using the MS Graph Client.
https://graph.microsoft.com/v1.0/sites/{SiteID}/lists/Documents/contentTypes/addCopyFromContentTypeHub
I looked at the various Request Builders and didn't see anything for "addCopyFromContentTypehub". There's a "ContentTypeAddCopyRequestBuilder", but that's a different action.
I tried getting access to the graph client's HttpProvider, but I can't figure out how to send the authentication with the request.
var requestUrl = graphServiceClient.Sites[siteId].Lists["Documents"].ContentTypes.AppendSegmentToRequestUrl("addCopyFromContentTypeHub");
var contentTypeId = "<ID>";
var body = $"{{\"contentTypeId\": \"{contentTypeId}\"}}";
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUrl))
{
httpRequestMessage.Content = new StringContent(requestUrl, Encoding.UTF8, "application/json");
//Errors here
var result = await graphServiceClient.HttpProvider.SendAsync(httpRequestMessage);
};
There error I get is:
"MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call."
My graph client uses an Azure AD App Registration to make all the calls so I need to include ".WithAppOnly()" on all my requests, but I don't see a way to do that using graphServiceClient.HttpProvider
Any help would be appreciated. Thanks!
You can authenticate HttpRequestMessage through Graph client
await graphServiceClient.AuthenticationProvider.AuthenticateRequestAsync(httpRequestMessage);
Code:
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUrl))
{
httpRequestMessage.Content = new StringContent(requestUrl, Encoding.UTF8, "application/json");
await graphServiceClient.AuthenticationProvider.AuthenticateRequestAsync(httpRequestMessage);
var result = await graphServiceClient.HttpProvider.SendAsync(httpRequestMessage);
};

How to call a web api that has Oauth 2.0

Hi so we have an external web api we want to call to get data out. It is using oauth 2.0. Can somebody please explain how we would go about doing this in .NET either vb.net or c#. I have in the past created api, however this one seems very complicated. Firstly you have to be signed into their oauth web page they have which generates some cookies, using these cookies by syncing them up in postman we can see the data, however we need this to be within our .net app. Can somebody please help how we go about this. Some code would be useful.
Thanks
This is how usually OAuth 2 authentication works.
You basically log in with username and password (optional second factor) and then you receive a token, the so called Json Web Token or JWT (it holds encrypted information about your user, your access roles or groups you are member of as well as some timestamp which is the expiration time of the token).
In every subsequent request you make to the server, you pass this token in the request header (or in your case as cookie).
Example code:
Login request:
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, new Uri(_baseUrl, "token"));
string body = JsonConvert.SerializeObject(new
{
Username = _userName,
Password = _password,
secondFactor = secondFactor
});
httpRequest.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(httpRequest);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
TokenResult r = JsonConvert.DeserializeObject<TokenResult>(responseContent);
if (!string.IsNullOrWhiteSpace(r.token))
{
_token = r.token;
_tokenValidity = r.expirationDate;
_refreshToken = r.refreshToken;
_refreshTokenValidity = r.refreshTokenExpirationDate;
return _token;
}
else
{
throw new Exception($"Failed to get token from server.\r\n{responseContent}");
}
}
Now you use the _token in subsequent requests in the request header:
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);
using HttpResponseMessage response = await client.GetAsync(new Uri(_baseUrl, relativePath));
if (response.IsSuccessStatusCode)
{
using var stream = await response.Content.ReadAsStreamAsync();
stream.Position = 0;
using var reader = new StreamReader(stream);
reader.ReadToEnd();
}
Please note, that usually the token has a certain lifetime after which it is basically useless. Some APIs offer a refresh token with which a new token can be requested without the user having to log in again with username and password, but that's beyond the scope of this question.
You said you have to use the token as cookie? Well there are APIs which work like this but personally I've never seen one like this, which is why I can't you help very much, but it shouldn't be much more than putting the token you got into a cookie with a certain name.
Hope this helps.
Not sure what you are asking. I have a controller code where I use web api call to authenticate user. You can use your own model to pass the data. If your web api expects token for request, then you might have to get the token first to give a call to any method. Hope this helps.
OktaUserDetailsModel Model = new OktaUserDetailsModel();
Model.username = model.UserName;
Model.password = model.Password;
using (var httpClient = new HttpClient())
{
HttpContent inputContent = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(Model), System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = httpClient.PostAsync(ConfigurationManager.AppSettings["OktaAPIuri"], inputContent).Result;
if (response.IsSuccessStatusCode)
{
string strResponse = (new JavaScriptSerializer()).Deserialize<string>(response.Content.ReadAsStringAsync().Result);
if (strResponse.ToUpper() == "TRUE")
return OktaSingleSignOnLogin(astrReturnUrl, model.UserName);
else
return ErrorPage();
}
else
{
return ErrorPage();
}
}

call to API works async, but I need it run sync

I've been trying for a day to make this work synchronously, not async.
Here is the code that works:
HttpClientHandler handler = new HttpClientHandler();
handler.UseDefaultCredentials = false;
handler.Credentials = new NetworkCredential(username, password);
HttpClient clientPageFirst = new HttpClient(handler);
HttpResponseMessage responsePageFirst = await clientPageFirst.GetAsync(fullURL);
HttpContent contentPageFirst = responsePageFirst.Content;
string resultPageFirst = await contentPageFirst.ReadAsStringAsync();
Console.WriteLine(resultPageFirst);
It's for a C# console app, and there is another call there to another platform's API which works synchronously, but it uses tokens in the header to validate, not a network credential like this one (calling a local on premise CRM URL).
Can someone please help me change the
HttpResponseMessage responsePageFirst = await clientPageFirst.GetAsync(fullURL);
line so it is synchronous?
T.I.A.
Try this
HttpResponseMessage responsePageFirst = clientPageFirst.GetAsync("fullURL").Result;

how to signin using oauth2 authorization Code Grant flow in UWP Desktop app

I am trying to enable single sigon in my UWP app.
I tried using WebAuthenticationBroker and able to get the AuthCode
var authenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, requestUri, redirectUri);
The above code returns me the authorization code which i can use to exchange for access token when i make another call but it always gives me bad request error. For the access token call i am using regular httpclient library
JObject jsonObject = new JObject();
jsonObject["code"] = autorizationCode;
jsonObject["grant_type"] = "authorization_code";
jsonObject["redirect_uri"] = redirectUri.AbsoluteUri;
var json = jsonObject.ToString();
HttpStringContent requestBody = new HttpStringContent(json, UnicodeEncoding.Utf8, "application/json");
var httpResponseMessage = await client.PostAsync(new Uri("https://<my app url>.com/oauth2/token"), requestBody);
I tried from postman and i get the same error too.
Is that possible to get access token with 0auth2.0 authorization grant flow in windows desktop apps based on UWP platform? Does it expect the request to come from the actual host uri in case of fetching access token in exchange of authorization code?
Some of the parameters needs to be sent as encoded and having below code solved the issue
List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("code", autorizationCode));
var encodedReqBody = new FormUrlEncodedContent(postData)

Issues getting Amazon Alexa Address API to work

Im having major dramas getting the Amazon Alexa address api to work in the C# Web Api app i have created using AlexaSkillsKit.Net
var apiEndpoint = context.System.ApiEndpoint;
var deviceId = context.System.Device.DeviceId;
var apiAccessToken = context.System.ApiAccessToken;
var url = string.Format("{0}/v1/devices/{1}/settings/address", apiEndpoint, deviceId);
var client = new HttpClient();
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiAccessToken);
client.DefaultRequestHeaders.Add("User-Agent", "Request-Promise");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string response = client.GetAsync(url).Result.Content.ReadAsStringAsync().Result;
The response i get back is as follows:
{"type":"FORBIDDEN","message":"The authentication token is not valid."}
Im at a loss as to why im getting this error
I have given my app permissions to get the Full Address
I have got this to work, i just needed to send the Permissions Card back to the user
https://developer.amazon.com/docs/custom-skills/device-address-api.html

Categories

Resources