Http endpoint for IOT hub resource - c#

How to get the http endpoint of an iot hub in azure. I need to build a solution to ping the http url to test whether iot hub is active or down. Similar to availability check.

So you can create an Azure Function or whatever you favor, to invoke this REST API to obtain the status. Example response will be like this
{
"totalDeviceCount": 0,
"enabledDeviceCount": 0,
"disabledDeviceCount": 0
}
To Authenticate against AZURE API you need to obtain the BEARER token first.
Example :
private const string Resource = "https://management.azure.com/";
string authority = $"https://login.windows.net/"TenantId";
var authContext = new AuthenticationContext(authority);
var credential = new ClientCredential("ClientId", "ClientSecret");
var authResult = authContext.AcquireTokenAsync(Resource, credential).Result;
var httpClient = new HttpClient();
Now when you call any azure resource api, pass the bearer token along
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + authResult.AccessToken);

Related

OpenID Connect Authentication Successful. Now what?

I'm writing a windows service in C# that needs to authenticate with an API and make some calls. I'm able to authenticate successfully with this API I'm talking to, but I can't seem to figure out how to use the response. The response looks like this:
{"access_token":"Es-Zjs_LI0tcXyLe3aEfgKPNLHN7CwyUhTss-cTld1A","expires_in":1800,"token_type":"Bearer","scope":"example","auth_state":1,"company":"examplecompany"}
I can get the access token out of that string if I want, but no matter how I pass it to a request, I get a 401 error. This is what my current iteration looks like:
string results = "";
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://example.ca/endpoint"),
//Headers =
//{
// { "authorization", "Bearer"},
//},
};
try
{
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
results = body;
}
}
catch (Exception ex)
{
results = "ERROR: " + ex.Message;
}
return results;
Where "token" is the string "Es-Zjs_LI0tcXyLe3aEfgKPNLHN7CwyUhTss-cTld1A" in this example. I had previously tried stitching the access_token value as a string to the "Bearer" string in the commented out section in the middle there. What am I doing wrong? Do I need to make a JwtSecurityToken out of the response?
AuthenticationResult authResult = await daemonClient.AcquireTokenForClient(new[] { MSGraphScope })
.ExecuteAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
I've used the authResult.AccessToken. Not sure if it works in your scenario. The return type in my case was Microsoft.Identity.Client.AuthenticationResult type when I retrieved the token for a Graph API that I was using.
Be aware that the token you have received ("Es-Zjs_LI0tcXyLe3aEfgKPNLHN7CwyUhTss-cTld1A") is a reference token and not a JWT-token. Make sure your API accepts that type of token.
To use the token effectively in production then I would consider using the various helper methods found in the IdentityModel library and especially the Worker application helpers.
While I understand it's largely situational depending on what API you're trying to connect to, for me the solution was to use this method to pass in the authentication token:
request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + token);

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)

Azure App Insights API to get traces using Query in c#

I'm trying to use Azure App Insights API using https://dev.applicationinsights.io/
Got the metrics data using this "https://api.applicationinsights.io/v1/apps/889f31e2-8281-4d8b-bb80-53a9f83d4a09/metrics/requests/duration?interval=PT1H", Passed the api key through headers.
But not able to get the Query:
Tried this:
https://api.applicationinsights.io/v1/apps/889f31e2-8281-4d8b-bb80-53a9f83d4a09/Query/traces | where operation_Id contains 62c5a318-c2cf-434e-a102-0e6efc0a84e7?interval=P7D
Getting Status Code as NotFound.
Any suggestions, Am I missing something?
According to my research, if you want to do query with Azure Application insight rest api, the URL should be like as below
https://api.applicationinsights.io/v1/apps/{appId}/query?query={1}&timespan={2}
For example
var client = new HttpClient();
var appId = "";
var query = "traces | where operation_Id contains '33f491236bb412419002b006e1c3058b'";
var timespan = "P7D";
var apiKey=""
string url = string.Format("https://api.applicationinsights.io/v1/apps/{0}/query?query={1}&timespan={2}",
appId,
query,
timespan);
var request = new HttpRequestMessage();
request.Method = HttpMethod.Get;
request.Headers.Add("x-api-key", apiKey);
request.RequestUri = new Uri(url);
using (var response = await client.SendAsync(request)) {
var str = await response.Content.ReadAsStringAsync();
Console.WriteLine(JsonConvert.DeserializeObject<JObject>(str));
Console.Read();
}
For more details, please refer to the document. Besides, you also can try the API vai the explorer.
Update
If you want to Azure AD auth to access Azure application insights API, please refer to the following steps
Register Azure AD application in your tenant
Configure API permissions
Create a client secret for the application
Configure assign contributor to the AD application in your Application Insights resource
call the api
// install sdl MSAL.NET to get access token
var client = new HttpClient();
var appId = "";
var query = "traces | where operation_Id contains '33f491236bb412419002b006e1c3058b'";
var timespan = "P7D";
var apiKey=""
string url = string.Format("https://api.applicationinsights.io/v1/apps/{0}/query?query={1}&timespan={2}",
appId,
query,
timespan);
string ClientId = "<your ad application clientID>";
string ClientSecret = "<your ad application ClientSecret>";
string tenant = "";
var app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithClientSecret(ClientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenant}"))
.Build();
string[] scopes = new string[] { "https://api5.applicationinsights.io/.default" };
var result =await app.AcquireTokenForClient(scopes).ExecuteAsync();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
var request = new HttpRequestMessage();
request.Method = HttpMethod.Get;
request.RequestUri = new Uri(url);
using (var response = await client.SendAsync(request)) {
var str = await response.Content.ReadAsStringAsync();
Console.WriteLine(JsonConvert.DeserializeObject<JObject>(str));
Console.Read();
}
For more details, please refer to the document

ASP.NET Core JWT Token not working via HttpClient

I'm new to JWT authentication and I've configured my ASP.NET Core 3 API for token authentication using the tutorial here:
https://chrissainty.com/securing-your-blazor-apps-authentication-with-clientside-blazor-using-webapi-aspnet-core-identity/
I've added the [Authorize] attribute to the controller, and using Postman I can login and get a token, and use the token via Postman to retrieve the data from the controller - all works as expected to here.
My issue is when I login using the C# HttpClient via a Xamarin app, and then I use the the token that is sent back I get a 401 error accessing the controller either via Postman or HttpClient.
The code I'm using is as follows:
var client = new HttpClient();
var model = new JwtLoginModel()
{
Email = email,
Password = password,
RememberMe = false
};
var json = JsonConvert.SerializeObject(model);
HttpContent httpContent = new StringContent(json);
var response = await client.PostAsync(Constants.BaseApiAddress + "api/Login", new StringContent(json, Encoding.UTF8, "application/json"));
var content = await response.Content.ReadAsStringAsync();
JObject jwtDynamic = JsonConvert.DeserializeObject<dynamic>(content);
var accessToken = jwtDynamic.Value<string>("token");
Using the returned accessToken via Postman (and HttpClient), both return a 401 error.
Can anyone suggest what I'm doing wrong?
Thanks all for the help
In the end I decided it was easier to go with Identity Server 4 implementation which is working perfectly

Resetting a user's password using Microsoft Graph

I'm trying to write a web portal that users can use to reset their own Azure AD password. Because of the requirements of my client, the Azure AD SSPR is not an option.
To achieve this I'm using Microsoft Graph. According to the documentation, it is possible to reset a users password using Microsoft Graph if you have User.ReadWrite.All or Directory.AccessAsUser.All permissions.
Then the permissions documentation, the remarks it states that even if you have the Directory.ReadWrite.All permissions you won't be able to reset a users password.
I've done a test to see if this will work but I get an HTTP 403 Forbidden response.
The code I'm using is:
string ResourceUrl = "https://graph.windows.net/";
string AuthorityUrl = "https://login.microsoftonline.com/companyxxx.onmicrosoft.com/oauth2/authorize/";
//Create a user password cradentials.
var credential = new Microsoft.IdentityModel
.Clients
.ActiveDirectory
.UserPasswordCredential("username#xxxx.com", "passwordxxx");
// Authenticate using created credentials
var authenticationContext = new AuthenticationContext(AuthorityUrl);
var authenticationResult = authenticationContext
.AcquireTokenAsync(ResourceUrl, "xxxxxxxx-3017-4833-9923-30d05726b32f", credential)
.Result;
string jwtToken = authenticationResult.AccessToken;
var cred = new Microsoft.Rest
.TokenCredentials(authenticationResult.AccessToken, "Bearer");
HttpClient client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
queryString["api-version"] = "1.6";
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
var uri = "https://graph.windows.net/xxxxxxxx-18fe-xxxx-bb90-d62195600495/users/xxxxxxxx-aa58-4329-xxxx-b39af07325ee?" + queryString;
//var content = new StringContent("{\"passwordProfile\": {\"password\": \"Test123456\", \"forceChangePasswordNextLogin\": true }}");
var response = client.PatchAsync(new Uri(uri), content, jwtToken);
The PatchAsync method is an extension method as below:
public static class HttpClientExtensions
{
public static async Task<HttpResponseMessage> PatchAsync(this HttpClient client,
Uri requestUri, HttpContent iContent, string jwtToken)
{
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, requestUri)
{
Content = iContent,
};
request.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/json");
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", jwtToken);
HttpResponseMessage response = new HttpResponseMessage();
try
{
response = await client.SendAsync(request);
}
catch (TaskCanceledException e)
{
Console.WriteLine("ERROR: " + e.ToString());
}
return response;
}
}
Could someone please clarify if this is possible using the credentials grant flow with a username and password for authentication. If so how do I achieve this?
You're mixing up Microsoft Graph and Azure AD Graph API. These are two different APIs and calls to one are not interchangeable with the other.
You are correct in that you need to use the Directory.AccessAsUser.All scope for this activity. This scope allows the API to do anything to the AAD that the signed in user would be able to do themselves (i.e. change their own password).
Once you have a valid access_token for the user with Directory.AccessAsUser.All permission, you can update the user's passwordProfile:
PATCH https://graph.microsoft.com/v1.0/me
Content-type: application/json
{
"passwordProfile" : {
"forceChangePasswordNextSignIn": true,
"password": "password-value"
}
}

Categories

Resources