asp.net Identity authentication .net core 2.1 - asp.net-core-mvc

I'm having an issue with a .net core 2.1 MVC application that is running on Linux boxes using kestrel behind an nginx web server. This environment has 2 web servers behind a load balancer.
The issue is the .AspNetCore.Identity.Application cookie used for authentication. I am able to authenticate and redirected to a controller decorated with the
[Authorize]
attribute (sometimes). However, on the next request, the cookie's gone and I get a 401. When we take one server out of the mix and force all traffic to one server, everything works as expected.
With Forms auth, the same problem could be overcome with specifying the machine key. What's the equivalent for .net core using identity? I found some links that went over my head. They mention doing something like this:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
I have no idea if this will fix the issue and I don't want to try things without knowing what they do.

I suspect what you experience has to do with data protection.
ASP.NET Core cookie authentication relies on the data protection layer to encrypt and decrypt data stored in the cookies. By default, a local key is created on each machine, meaning they can't decrypt cookies created by the other one, as stated in the official documentation.
I suggest that you go through the data protection configuration documentation page and evaluate your options. One of them is to store the keys on a UNC share and encrypt them with a certificate (all the links in this paragraph link to different sections of the same page).

Related

ASP.NET Core 2.1 Individual User Accounts without HTTPs

The ASP.NET Core 2.1 new template with Individual User Accounts cannot be created without HTTPs. There is anyway around this?
You should always use HTTPS and never HTTP. HTTP is insecure for a number of reasons. That is probably way it is not possible.

Web api 2 - windows + client cert auth - is it possible?

I currently have an asp.net web api 2 site hosted in IIS secured with windows authentication. A requirement has now come in for us to support client certificate authentication in addition to windows, and I'm struggling to find out:
- if this is possible at all
- if there are any working examples available
I thought might be able to add an additional owin middleware or messagehandler or filter, but can't see any existing ones that do this specifically for windows rather than just relying on IIS. I know thinktecture identitymodel can do client cert, but not sure if the two can be combined?
Example of forms +win that i thought might be similar is here https://techblog.dorogin.com/mixed-windows-forms-authentication-for-ajax-single-page-application-e4aaaac0424a
Right so I managed to figure it out. Thankfully, if a controller returns a 401, IIS automatically adds the negotiate/ntlm headers, so if a user is on a windows browser, it will then automatically authenticate as usual. So with that in mind, to keep windows auth working, I:
updated the site in both IIS and VS to allow anonymous AND windows auth
added the [AuthorizeAttribute] as a global action filter (which causes the 401 to be returned if the user is not authenticated by the time they hit the filter)
To get client certificate auth working, I used the magnificent Thinktecture.IdentityModel library, which allowed me to add only one line to my Startup.cs file (we're using OWIN so this was easy)
app.UseClientCertificateAuthentication();
See https://github.com/IdentityModel/Thinktecture.IdentityModel/blob/master/samples/OWIN/AuthenticationTansformation/KatanaAuthentication/Startup.cs for an example

Azure Active Directory OpenIdConnect Refresh Interval

I have an application hosted in Azure using Azure Active Directory and OpenIDConnect for authentication - generally all works well. However I'm having an issue where some requests generate a call to https://login.microsoftonline.com/ and then on to the requested page - no password is requested. I'm assuming that this is some kind of token refresh?
The problem is that the site uses a fair amount of ajax and these requests stop working because they get redirected to https://login.microsoftonline.com/ This happens after maybe 15 minutes, however the nbf and exp properties of the JWT token show a validity period of approximately an hour.
I've set the BackchannelTimeout property of OpenIdConnectAuthenticationOptions to 30 minutes, however this doesn't seem to have made any difference.
Can anyone offer any advice on what may be happening and the options to change or work around the behaviour?
Your question can be answered in the same way as this other thread: MVC AD Azure Refresh Token via ADAL JavaScript Ajax and KnockoutJs
In short: the OpenId Connect middleware is designed to support redirect based web applications. Ajax calls are not well suited to be protected via cookies, and the issue you are experiencing is one of the reasons why. Javascript based API calls are better protected using tokens rather than cookies.
For some links that might provide an alternative approach, see the link above.
I created a nuget package for .NET web applications which is refreshing the Azure Active Directory Token in the background.
More info: https://www.nuget.org/packages/RefreshTokenForAjaxRequest.Azure.ActiveDirectory/

AJAX Call to MVC Controller that Calls a WebService

We are working on an internal MVC3 app that purely uses Windows Authentication. There's a view that does an AJAX call to a controller action that does some processing before calling a web service. The problem we are running into is that if Anonymous access is turned off (as in Windows Authentication is on), calling the service from the controller actions results in a 401: Unauthorized error.
We have run into a problem of the double hop issue where credentials aren't passed correctly from server to server when calling a service within a service. I'm wondering if the AJAX call is somewhat mimicing the same behavior and not transmitting the correct Windows credentials to the controller which then doesn't pass the correct credentials to the web service.
I've seen some posts that shows how to pass a username and password along with the jQuery call but nothing mentions, an effective way, to bring along Windows Authentication with it.
Has anyone run into a similar issue? We would rather not leave Anonymous access on the web service as it is somewhat sensitive data that we would like to control access to.
Do you have identity impersonation turned on as described in this question:
How to get Windows user name when identity impersonate="true" in asp.net?
A colleague did some research over the weekend and determined it may have something to do with Kerberos authentication setup on the server as well as the jQuery call. In order to get around it, we just refactored the web service into a library that the application just references. We made it a web service initially as we thought in the future this data would need to be accessed from other applications. Running into this issue, we will most likely make it into a NuGet package.
Thanks for the comments.

ASP .NET Cross Site Forms Authentication works in Dev but not production

I have two MVC3 sites, both hosted on the same server that I've configured to use the same authentication cookies.
The first site is an intranet site using Windows authentication. This site has one simple Action that checks to see if the user was authenticated, if the user has been, it creates a FormsAuthentication cookie that it adds to the response. This cookie is created for a generic user that I determine from the User's AD groups. The response then redirects the user to a second site that uses Forms Authentication.
When I run this on my local machine, everything works as described above. When I deploy this to our local web server, it doesn't. I've tested to see if the user's group is correctly determined and that it creates a valid user for the cookie, and I have verified that this is correct on the web server.
Here is how I'm doing all of the above:
First, I made both sites use the same same Machine Key for encryption and decryption.
When I create the cookie in Site1, I ensure that it has the same name and Domain as the cookies created on Site2.
var cookie = FormsAuthentication.GetAuthCookie(userName, false);
cookie.Domain = FormsAuthentication.CookieDomain; //This is the Domain of my 2nd site as they are different
HttpContext.Response.Cookies.Add(cookie); //Add my cookie to the response
HttpContext.Response.RedirectPermanent(urlForSite2);
Again, when I run this on my local machine it works without a problem. But when deployed, it's either not passing the cookie in the request, or the response is ignoring it, but I'm not sure how to verify either of these cases.
Feel free to ask any question regarding more details as to how I'm doing this if it will help in getting an answer I need.
Cross domain cookies are not allowed. If you have two separate domains; one cannot access the others cookies. Two separate virtual directories/applications will work when using the same machine key. http://blogs.technet.com/b/sandy9182/archive/2007/05/07/sharing-forms-cookie-between-asp-net-web-application.aspx
If you want to share login cookies between sub-domains you need to edit the Domain property of the login cookie to the 2nd level domain "abc.com" so that "www.abc.com" and "ww2.abc.com" will have access to the cookie. http://forums.asp.net/t/1533660.aspx
String usrName = User.Identity.Name.ToString();
HttpCookie authCookie = Security.FormsAuthentication.GetAuthCookie(usrName, false);
authCookie.Domain = "abc.com";
Response.AppendCookie(authCookie);
Actually, it is possible, but isn't as simple as the domain/sub-domain cookie sharing.
http://www.codeproject.com/KB/aspnet/CrossDomainSSOModel.aspx
While the example given in this article didn't apply directly to what I was doing, I could use some of the ideas expressed there to get what I needed working. It ended up being my configuration settings in site2 web.config.
My URLs are as follows
Site1 = http://site.stage
Site2 = http://site.stage.MyCompanyName.com
Site 1 requires a host entry addressing it to a specific IP address of the hosting machine. It's also an entry in my IE Security settings - Local Intranet Sites.
I should note that these applications are both virtual directories running under the same default website.
I thought I had solved my problem but setting the Domain in the config file to and empty string, but this didn't work. I'm not sure what can be done now. This still works when I run it on my local machine, but not when I run it on my server. The only difference is the urls.
My dev machine is using the urls
Site 1: http://localhost/CompanyName.TVAP.IntranetSite
Site 2: http://localhost/TVAPDev/
I hope this adds some clarification. This Answer should really be posted as an edit to my question, but when I originally posted it, I thought I had it working.
UPDATE: I think my answer is in my URLs above. My dev machine URLS both are using the same domain name, which in this case is localhost. I think if I alter my deployed websites to use the same domain, I will be OK. I'll post an update when I get it worked out.

Resources