Authenticate on a on-premise webservice - asp.net-core

I am having trouble with authentication in my asp-net web service. This service has an angular gui and some mvc api.
This service will be deployed on multiple servers inside my organisation windows or linux (or even docker). This seems to prevent me from using basic active directory authentication. Important part is I don't know before deployment the target ip:port of deployment.
I am trying to add an azure active directory based authentication.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
}
Everything works fine until I get into the Reply Url part of the authent process. It seems I can't find a way to avoid using a reply url.
In dev environement I have to add localhost as a valid reply url to my app and everything works fine. But what about future deployment? It seems very painfull to maintain a complete and up to date list of all the alive servers.
Is there a way to do the complete auth process client side and then go back to back end only when the final token has been received? I then suppose that the backend would have to validate the token against the authority has it was not implied in the process but that's fine.
What am I missing here?

Related

Why is vNet Integration breaking the Authentication setup on my Azure Function

I have an Azure Function where I have enabled Authentication with the Identity provider being Microsoft. With Postman, I get my token, call the root page ("Your Functions 4.0 app is up and running"), pass it in the Authorization header and it responds correctly.
Once I enable vNet Integration, the function respond with the error
The page cannot be displayed because an internal server error has occurred.
What did I missed?
The post is quite old and there is no information on the VNet integration setup, but anyway.
The issue might be because of the VNet Integration setting called Route All.
According to the official Azure documentation,
If Route All is disabled, your app only routes private traffic into your virtual network. If you want to route all your outbound app traffic into your virtual network, make sure that Route All is enabled.
So I believe the Route All is enabled in your configuration. And you should try to disable it:
Go to Vnet Integration
Disable toggle Route All as it is in the screenshot below

How to authenticate both Blazor web app and api?

I am using .NET 6 RC1 with Blazor Server for my Server and a separate Blazor Webassembly project for my client. Both authenticate with Azure Ad B2C. The authentication aspect is working fine.
The server hosts both a BlazorHub for the server side (admin) pages as well as a separate hub for the client to be able to authenticate and call into.
The client connects to the hub mentioned above, as well as perhaps calls any potential API endpoints.
The authentication setup I have is as follows
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(configuration, AzureB2C);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(configuration, AzureB2C);
The problem here is that if I have both of these defined, the Client (localhost:4201) works and can connect to the protected Hub on the server.
If I attempt to connect to the server endpoint (localhost:5001) I simply receive a browser 401 page, with nothing in the console and Visual Studio output except for a crbug/1173575, non-JS module files deprecated. warning and additionally in the browser console I receive an Uncaught pause_on_uncaught error.
If I comment out the section for AddMicrosoftIdentityWebApp, the client can still connect fine as before, and the Server fails to authenticate as described above.
If I instead comment out the section for AddMicrosoftIdentityWebApi, the server can authenticate and works as expected, but now the client fails to authenticate with the Hub because the JWT token is not being validated.
How do I mix both of these successfully so I can both authenticate in the Server and the Client?
I have found this on the Microsoft Identity Web github page which basically is what I am trying to accomplish, except the code they provided doesn't work for me the same as I have in my example.
I seem to have resolved my issue by doing the following.
Change the order of my Authentication methods.
AddMicrosoftIdentityWebApi is first.
AddMicrosoftIdentityWebApp is second.
Specify for my Hub that it will use the JwtBearerDefaults.AuthenticationScheme
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapHub<GameHub>("/hubs/gamehub")
.RequireAuthorization(new AuthorizeAttribute
{
AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme,
Policy = PlayerPolicy
});
endpoints.MapFallbackToPage("/_Host");
});
Now both authorize just fine!
I'd love to hear if anybody knows the solution for this keeping the original order of them.

Is it possible to use a bearer token to authenticate two webapi systems on the same server?

We have two webapi applications (core and support) configured on the same IIS web server running on our local domain. Our users authenticate on the core application using active directory and the core system returns a bearer token. This token is then used to authorize all API calls from our ReactJS client. In addition to the core application, we also have the support web application. Any calls to this system API end points also needs to be authorized.
Is it possible to use the same bearer token issued by the core application for the support application?
We have configured a separate webserver, database server and client to test the process. After building and deploying the two api web applications and the ReactJS client we are able to login via active directory, receive a bearer token and with this token authenticate on both the core and support platforms.
However, when we copy the same files and configurations to our clients server, we get a 401 authorization error on the support domain; the core domain works perfectly.
We have installed SSL certificates in both environments as well.
If we set the support application to Allow all Origins for CORS it works as there is no authorization. However, when we set the origins to the ReactJS and Core api projects we get the 401 error on the support domain.
We did not expect the token from the core application to authorize against the support application. However, this is working within our domain environment and we are not sure why. This has made it even more confusing as to why it does not work in the customers environment.
In case it helps anyone ... The reason this worked for us internally is because we had all web applications running within the same application pool. This meant they shared the same machine key and as such the bearer token from one would be authorized across all. As soon as we moved them into their own application pools we were able to replicate the same issue as the customer (ie. 401 authorization). The fix is to either have them in the same application pool or add the same machinekey to the applications web.config files.

What are the correct authentication settings for an on-premise ADFS flow?

I've been reading Vittorio Bertocci's blog to try to get up to speed on using ADFS to manage authentication and claims in either an MVC app or WebApi service. It looks like it's getting to be very approachable.
I am now trying to build out a POC using ADFS to do common claims resolution for internal sites/services in our enterprise. Our users would be on the internal network along with our endpoints. Right now we use Windows Integrated auth by default and each site does the work of looking up a user’s name, email, and other AD details and inspecting the claims principal for roles via IsInRole. The claims we get with integrated auth includes just a SamIdentifier and a bunch of group SIDs. I’d like ADFS to do that work for us but still give our users a challenge-free experience. Long term, we will likely add support for non-domain-joined devices on some sites/services, so that is another motivation to explore ADFS.
So I've set up a simple sample app in VS2013 using Organizational Accounts (On Premise) that will dump out a current user's claims, configured the metadata endpoint and audience uri, communicated that info along with the claims I'd like mapped to my ADFS admin (2012, btw), and deployed my site to a development server. So my host is still IIS, though I hope to use Owin middleware to set up authentication rather than web.config (WIF-style).
Given that IIS is my host, how do I configure authentication for my site: anonymous? And my web.config should specify "None" for the authentication mode and deny="?" for authorization, correct?
The other question I have that Vittorio didn't get into in his post about on-premise adfs was the nature of the bearer token and whether or not we need to explicitly configure the middleware to use cookies. My startup config looks like this right now:
public void ConfigureAuth(IAppBuilder app)
{
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
TokenValidationParameters = new TokenValidationParameters() { ValidAudience = ConfigurationManager.AppSettings["ida:Audience"] }
});
}
It looks like this middleware is expecting JWT tokens (given that there is a JwtSecurityTokenHandler on the class). Is there any configuration we need to do on the ADFS side to issue JWT tokens? My understanding is that I'll receive a SAML token by default.
And should we expect to use the CookieAuthentication middleware to manage the token or will the browser just keep including it for the life of the session?
Thanks, all!
UPDATE:
So based on Vittorio's help below and some further research, I now have a simple website with just one page protected with an [Authorize] attribute. My startup class's ConfigureAuth method now looks like this:
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
TokenValidationParameters = new TokenValidationParameters() { ValidAudience = ConfigurationManager.AppSettings["ida:Audience"] }
});
}
We've added my website as a relying party trust in ADFS and created a half dozen claims rules. Everything seems correct so far, but I'm still struggling. I hit the protected "claims" page and get a 401 response with a WWW-Authenticate:Bearer header. So far, so good.
But that's it. How does the browser know where to get authenticated and receive a token? If I was proving out the separate client scenario, my client would be configured with the location of the token authority, but in this simple website scenario, I'm clearly missing something.
UPDATE 2:
I wonder if the implementation for on-premise ADFS just isn't ready yet? Or perhaps the documentation just isn't there yet - or both...
I pulled out all the Owin packages and reverted to using the WSFederationAuthenticationModule and SessionAuthenticationModule, along with all the web.config settings in system.identityModel and system-identityModel.services that have been around a while. Basically, I made the solution look like the one you get from VS2013 when you selected Organizational Accounts --> On Premise. Everything works beautifully and I have all my configured claims coming from ADFS. I see the initial 302 redirect to ADFS, the challenge-response, and ultimately have a SAML token serialized into a secure session cookie. On the website, I echo back the claims like so:
var user = User as ClaimsPrincipal;
ViewBag.Claims = user.Claims;
return View();
This is why I suspect the middleware is incomplete: when you use that new template in VS2013, the wizard goes to the federation metadata endpoint you specify and builds out all the web.config settings by reading that xml and, in addition, sets some intelligent defaults. That's sort of what I expected to happen in the Owin middleware - it should have everything it needs to know since I pass in the same metadata endpoint. I was hoping that "magic" would replace using the FAM/SAM modules and all the accompanying config.
1) If you are configuring a web UX app, that is something meant to be consumed through browser redirects, you want to use http://www.cloudidentity.com/blog/2014/04/29/use-the-owin-security-components-in-asp-net-to-implement-web-sign-on-with-adfs/. You'll see that the cookie middleware does come into play in that case.
2) If you are configuring a web API, as in something that is consumed by a rich client or another server, or in general anything that is not a browser roundtripping, see http://www.cloudidentity.com/blog/2013/10/25/securing-a-web-api-with-adfs-on-ws2012-r2-got-even-easier/. In that case you do not need cookies, given that there is no session -every single call must carry the token.
HTH
V.
As Vittorio said you need to differentiate if you create a web page with web api or web api only. Follow his blog posts they are great!!
If you host a webapi only project in an IIS you need to set the authentication to "forms authentication".
This works also if your web api is covered behind a web application proxy. make sure that you configure your endpoint (published web application) not to preauthenticate. the value for "preauthenticate" should be "pass through".
bg Andrej

Can WCF do WindowsAuthentication with username password?

I'm building an wcf service that is meant to run in an intranet environment using Windows Authentication. I have been merrily working along with some kind of default settings on the local computer.
Problem now is that I need to test it installed to an off site demo computer. I just need to get it running with username password used against the wcf service computer's user accounts.
This is my client code:
using (ImportServiceClient client = new ImportServiceClient("ImportServiceSoap12", REMOTE_ADDRESS))
{
client.ClientCredentials.Windows.AllowNtlm = true;
client.ClientCredentials.Windows.ClientCredential =
new NetworkCredential(userName, password, computerName);
result = client.Sync(items.ToArray());
}
Is it possible to configure the wcf service such that it translates the credential to a windows account on it's machine?
I've been reading contradicting posts here and there, but I feel rather sure IIS shouldn't be part of the authentication. I'm unsure wether ASP.Net authentication node applies or if it's all binding configuration.
Ideally I'd like it to be an NTLM type authentication so that I wouldn't need to set up https.
Is it possible to configure the wcf service such that it translates the credential to a windows account on its machine?
No. Integrated Windows Authentication requires that both the server and the client are part of the same domain (or domains with a trust relationship, in any case). You can't usefully run IWA against local computer accounts on the server.
You will have to use some other (potentially custom) form of authentication and then impersonate to the user you want to run as in the server code.