Microsoft Azure AD authentication giving 'System.Net.Http.HttpRequestException' - c#

I am facing a strange imtermittent issue with Azure AD authentication.
We are using CORS enabled web api in our project (origins are specified in web.config which are fetched by custom attribute, and this attribute is used for controllers).
Athorization part is done using adal.js
code is as follows:
startup.cs
using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
[assembly: OwinStartup(typeof(test.testapi.WebApi.Startup))]
namespace Test.testapi.WebApi
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
Startup.auth.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Claims;
using Microsoft.Owin.Security.ActiveDirectory;
using System.Configuration;
using Owin;
using System.Net;
namespace test.testapi.WebApi
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
//Following line is not required if you are using HTTPS calls to APIs
//ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
});
}
}
}
When the control goes to startup.auth.cs it gives System.Net.Http.HttpRequestException
Error
Now thing is while i was working on my local dev environment i never got this issue(always authenticated fine ) but QA was facing this issue on QA server, so we started hosting web api from my machine, After which i also started getting this issue and that too quite frequently now.
what is this issue if anyone has faced this same issue.

Related

'WebHost' is inaccessible due to its protection level

I am trying to follow Microsoft's Ocelot API Gateway tutorial (https://learn.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/implement-api-gateways-with-ocelot).
First I intialized a new empty ASP.NET Core web app:
dotnet new web
Then I installed the Ocelot dependencies (https://www.nuget.org/packages/Ocelot/):
dotnet add package Ocelot --version 17.0.0
Then I took the code from the tutorial:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using System.IO;
namespace MyApp
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
var builder = WebHost.CreateDefaultBuilder(args);
builder.ConfigureServices(s => s.AddSingleton(builder))
.ConfigureAppConfiguration(
ic => ic.AddJsonFile(Path.Combine("configuration",
"configuration.json")))
.UseStartup<Startup>();
var host = builder.Build();
return host;
}
}
}
But then it complains that the WebHost class, called in BuildWebHost method, "is inaccessible due to its protection level". According to Microsoft (https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webhost), WebHost "provides convenience methods for creating instances of IWebHost and IWebHostBuilder with pre-configured defaults.", and looks like so:
public static class WebHost
...
Why does it complain that WebHost is inaccessible, when the class is in fact public? What am I missing here?
From the documentation, WebHost is in the namespace Microsoft.AspNetCore. But in your code, It hasn't the using to this namespace.
In Visual Studio, you can try Go to definition on WebHost to discover where the type come.
As sujested by #leiflundgren, as your code has the using Microsoft.AspNetCore.Hosting, then the compiler thinks you want use Microsoft.AspNetCore.Hosting.WebHost.
https://github.com/dotnet/aspnetcore/blob/main/src/Hosting/Hosting/src/Internal/WebHost.cs
namespace Microsoft.AspNetCore.Hosting;
internal sealed partial class WebHost : IWebHost, IAsyncDisposable
{
....
}
But this class has the scope internal, then it isn't exposed and can be used by your code. Hence the following error :
WebHost is inaccessible due to its protection level.

Add a Startup.cs file in MVC5 project without authentication

How can I bind the startup.cs file adding manually to the project?
I created it from Add > New Item > OWIN Startup class but is ignored by the app.
The Startup class
using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(WebApplication1.Startup))]
namespace WebTest
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
}
}
}
Thanks
Update
I can do it thanks to this
OwinStartup not firing
[assembly: OwinStartup(typeof(**WebApplication1**.Startup))]
In the OwinStartup attribute you specify a class WebApplication1.Startup but the class shown says WebTest.Startup

Authorize signalr core hub using identiyserver4

I am using visual studio 2019 preview Angular / .net core API backend template with individual authorization.
I believe within this template, identityserver4 is being used.
Within the API there is a signalr core hub which I am trying to authorize. I have the Authorize attribute on the hub. I am also specifying the token in the angular signalr client URL query string.
Despite the above, the authorize attribute has no effect, I am able to access the hub with or without the token.
JS / angular client
ngOnInit() {
console.log(this.authService.getAccessToken().toPromise())
this._hubConnection = new signalR.HubConnectionBuilder()
//.withUrl('/handoverhub', {accessTokenFactory: () => this.token})
.withUrl('/handoverhub', { accessTokenFactory: () => {
return this.authService.getAccessToken().toPromise();
} })
.configureLogging(signalR.LogLevel.Information)
.build();
ASPNETCore code
Hub using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using HomecareShared.Models;
using HomecareShared.Models.DTOs;
using HomecareShared.Models.Handover;
using HomecareShared.Models.Notify;
using HomecareShared.Models.SharedResources;
using HomecareHandover.Repo;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.VisualBasic.ApplicationServices;
namespace HomecareHandover.Hubs {
[Authorize]
public class HandoverHub : Hub
Some snippets of startup
app.UseAuthentication();
app.UseAuthorization();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<HandoverHub>("/handoverhub"); //For handover
endpoints.MapHub<TaskHub>("/taskhub"); //For task
});
app.UseIdentityServer();
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddSignalR();
No error messages. I am able to get straight into the hub no problem.
I have had a similar problem but with AzureSignalR. I overcome the issue by implementing the code below. You also should call UseIdentityServer before UseEndpoints;
app.UseAuthentication();
app.UseAuthorization();
app.UseAzureSignalR(routes =>
{
routes.MapHub<ChatHub>("/hubs/chat");
routes.MapHub<NotificationHub>("/hubs/notifications");
});
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
});
By the way, another example about Hub authorization yet again in AzureSignalR and pure JWT but I put here so you may take a peek
https://github.com/ilkerkaran/MySignalRPlayGround/blob/master/SignalRServer.API/Startup.cs
FIXED!!!!
Turns out it was ordering in Startup.cs file.
I first implemented ilkerkaran's suggestion about calling identityserver before UseEndpoints. Then after 4 more hours, I moved app.UseAuthorization() below app.UseIdentityServer and that fixed it.
Hopefully, this helps someone else.

Calling an external webservice method from Azure function returns 401 but the same code works in a console app

I have added a web reference (WSDL) to a class library and then referenced that dll in a timer-triggered c# Azure function (read more about azure functions). The class library has a class EmployeeService which calls a method from the web service (sort of a webservice wrapper). When I call the class lib method (GetEmployees) from a console application, it authenticates to the web service and returns result but when I run the azure function for the same code and creds it returns 401. Not sure what I am doing wrong here :
#r "MyConsult.Service.dll"
#r "Newtonsoft.Json.dll"
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Newtonsoft.Json;
using System.Net;
using MyConsult.Service.Service;
public static void Run(TimerInfo myTimer, TraceWriter log)
{
log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
try
{
EmployeeService _empService = new EmployeeService();
var emps = _empService.GetEmployees();
int count = emps.Where(x => !string.IsNullOrEmpty(x.Email)).Select(x => x.Email).Distinct().Count();
log.Info($"employee count : {count}");
}
catch (Exception ex)
{
log.Info($"Exception Message: {ex.Message}");
log.Info($"Exception Stack Trace: { ex.StackTrace}");
}
}
Your console application is likely authenticating based on service configuration settings in your app.config. For your function, you'll need to programmatically apply those settings when constructing the client/proxy.

REST post method difficulty

There is an application which is used for taking surveys. I want to use REST api and add some questions to the survey. So basically I want to update some pages of the survey. Here are the links of that application.
My surveys name is trial and the page number that I want to update is 2.
fields#updateobject
Here is my code to do. But i think the http call I have used is not correct. and I am not able to figure out how to make the request.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
namespace ConsoleApplication1
{
class Program
{
private static object post;
private static object response;
static void Main(string[] args)
{
RunAsync().Wait();
}
static async Task RunAsync()
{
string webReq = "https://restapi.survey.com/v4/survey/trial/surveypage/2?_method=POST?api_token="/*token goes here*/;
// $.post{webReq};
}
}
}
Use System.Net.Http.HttpClient class for sending requests to any API. Tutorial and examples on sending various requests (GET, POST, etc.) can be found here.

Categories