Google Chrome Browser Block ".AspNetCore.Identity.Application" Cookie In Deployment Only - authentication

After deploy asp.net core mvc 6 to iis server the user in case submit a true login not redirected to the controller and not authenticated, when I tracked the cookie in developer tools there is a ! mark on .AspNetCore.Identity.Application and when hover on it there is a message show (This cookie was blocked because it had the "Secure" attribute and the connection was not secure).
What I tried Before
Changing the cookie configuration
Exchange return LocalRedirect(returnUrl) To return RedirectionToAction("Index","Home")
Add [AllowAnonymous] attribute on LoginModel in Areas.Identity.Pages.Account
Remove Use.HttpsRedirection(); from program.cs

Because there are many apps host in the server so the browser blocked the cookie cause the other apps have the same cookie name which .AspNetCore.Identity.Application. So simply the issue can be solved by changing the name of the cookie:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
});
builder.Services.ConfigureApplicationCookie(options => options.Cookie.Name = "AppNameForExample");

Your cookies are configured to require an HTTPS connection. When you try to set them on a non-secure connection, they will be rejected. You can try these steps:
Obtain a valid SSL certificate: You'll need a certificate that is trusted by the browsers you're targeting. Check your web.config file settings for:
<httpCookies requireSSL="true" />
Configure IIS to use HTTPS: This involves binding the SSL certificate to the IIS website and enabling HTTPS.
Update your ASP.NET Core application to use HTTPS: In the Startup.cs file, you can use the following code to redirect all HTTP traffic to HTTPS:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Rewrite;
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var options = new RewriteOptions().AddRedirectToHttps();
app.UseRewriter(options);
// rest of the code...
}

Related

How to use Windows authentication on ASP.NET Core subpath only?

I am trying to configure Windows authentication on a subroute only in my ASP.NET Core MVC app.
My problem is that when I add
services.AddAuthentication().AddNegotiate()
I get an error
The Negotiate Authentication handler cannot be used on a server that directly supports Windows Authentication.
which lead me to adding web.config as the docs explained:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
</configuration>
and the error goes away. However, now the Windows authentication is popping up on each request.
I tried changing the location path to .testendpoint but that then throws the original error at the base path.
So is it possible and how do I make such only /testendpoint will ask for Windows authentication and the remaining of the application will work with whatever other auth I configured in my ASP.NET Core app?
Another way using endpoint routing:
We have an application schema for the application that will be used all over the app called eavfw.
Using a custom endpoint here called login/ntlm with metadata new AuthorizeAttribute(NegotiateDefaults.AuthenticationScheme) its only allowed to be visited by a valid windows authenticated user.
Here we then create the user in our DB using its AD username.
endpoints.MapGet("/.auth/login/ntlm", async httpcontext =>
{
var loggger = httpcontext.RequestServices.GetRequiredService<ILogger<Startup>>();
var windowsAuth = await httpcontext.AuthenticateAsync(NegotiateDefaults.AuthenticationScheme);
if (!windowsAuth.Succeeded)
{
loggger.LogWarning("Not authenticated: Challening");
}
if (windowsAuth.Succeeded)
{
loggger.LogWarning("Authenticated");
var name = string.Join("\\", windowsAuth.Principal.Claims.FirstOrDefault(c => c.Type.EndsWith("name")).Value.Split("\\").Skip(1));
var context = httpcontext.RequestServices.GetRequiredService<DynamicContext>();
var users = context.Set<SystemUser>();
var user = await context.Set<SystemUser>().Where(c => c.PrincipalName == name).FirstOrDefaultAsync();
if (user == null)
{
user = new SystemUser
{
PrincipalName = name,
Name = name,
// Email = email,
};
await users.AddAsync(user);
await context.SaveChangesAsync();
}
var principal = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] {
new Claim(Claims.Subject,user.Id.ToString())
}, "ntlm"))
{
};
await httpcontext.SignInAsync("ntlm",
principal, new AuthenticationProperties(
new Dictionary<string, string>
{
["schema"] = "ntlm"
}));
httpcontext.Response.Redirect("/account/login/callback");
}
}).WithMetadata(new AuthorizeAttribute(NegotiateDefaults.AuthenticationScheme));
using a auxility authentication cookie, we can now make it such that specific areas of our app that requires windows authentication, it can simply rely on Authorize("ntlm") as it automatically forward the authenticate call to check if already signin, and it as part of the signin call in the endpoint above actually sign in eavfw.external before it redirects to the general account callback page that will do some final validation before signing in eavfw from the eavfw.external cookie
services.AddAuthentication().AddCookie("ntlm", o => {
o.LoginPath = "/.auth/login/ntlm";
o.ForwardSignIn = "eavfw.external";
o.ForwardAuthenticate = "eavfw";
});
So there are a few ways to extend and use the authentication system in auth core depending on how MVC framework heavy your application is.
Just thought I'd share this tidbit of information:
First off, just because you installed Windows Authentication with Server Manager, doesn't mean it's enabled in IIS. It's NOT enabled, by default.
You have to open IIS Manager, click on your server (NOT the website - the name of the server machine hosting IIS). Then click on Authentication - you will see "Windows Authentication" is disabled. Enable it. Now it will work.
Check this is correctly set first, before making other config changes. The default project for dotNet5 and dotNet6 will work w/o any modifications if IIS is correctly configured for Windows Authentication.
In order to have a certain page/action method secured via Windows authentation, specify the corresponding authentication scheme in the action methods Authorize attribute.
[Authorize(AuthenticationSchemes = IISServerDefaults.AuthenticationScheme)]
public IActionResult UsingWindowsAuthentication()
Make sure to have Windows authentication enabled on your website.
In order to use other authentication schemes, e.g. "Individual Accounts", anonymous authentication is also enabled.
The controllers and/or action methods that must not use Windows Authentication have the default scheme specified.
For example, for an ASP.NET Core MVC project that uses the out of the box "Individual Accounts" authentication type as default authentication method, that is Identity.Application.
[Authorize(AuthenticationSchemes = "Identity.Application")]
public IActionResult Index()
See the documentation about how to set up and configure multiple authentication schemes.

Asp.Net Core & IIS Server : session cookie not set in production

I am working on an ASP.NET Core web application. My dotnet version is 3.1.401 and I am with Visual Studio Community 2019 Version 16.7.2. I am using a session cookie that was working well with IIS Express.
I deployed the app on IIS Server v 10.0.19041.507. My authentication cookie (without ASP.NET Core Identity) is working fine but on the contrary the session cookie is not set.
Here is what I have in startup.cs
services.AddSession(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.HttpOnly = true;
options.Cookie.Name = ".FjDRegisterLLAT.Session";
//options.IdleTimeout = TimeSpan.FromSeconds(900);
options.Cookie.IsEssential = true;
});
Let me precise that I removed the line : "app.UseCookiePolicy()" from startup.cs
In IIS, there is an option for the session state, but I really don't know how to configure this. Perhaps I should not even configure it as my authentication cookie is working and I didn't not change anything to it.
I still tried using the name of my cookie (see in statup.cs above) in place of the default one, but it does not change anything :
Here is a controller where I'am using the session cookie to retrieve data. I thought that when I would make a request to that controller, a value would be set along with the creation of the cookie like in development mode, but no !
[HttpPost]
public IActionResult Index(bool isCheckingOut)
{
User user = GetUser();
user.isCheckinOut = isCheckingOut;
HttpContext.Session.SetComplexData("user", user);
return RedirectToAction("SetStatus");
}
UPDATED_1
In development mode, my cookie is set with the name and options as set in Startup.cs.
UPDATED_2
Apparently it has nothing to do with the application settings nor the IIS Server configuration. The session cookie is set properly by Edge and FireFox. It turns out that chrome does not want it.

Is it okay to use JwtBearerOptions.RequireHttpsMetadata=false in production when behind a Reverse Proxy?

I have an angular application that communicates with a .Net Core REST API. I also have an authorization server that is installed on the same server as the API. The API validates the authorization token it receives from angular against the authorization server.
My plan was to set everything up behind a reverse proxy so that internal communication happens over http between the API and the authorization server in order to simplify the management of the certificates since there will be multiple instances of the services. External access would still happen over https.
In order to to do this I need to set the RequireHttpsMetadata property in JwtBearerOptions to False, but the documentation says that this should always be True when used in production. But considering that in my case the communication happens internally would it be okay if it's false?
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = "http://localhost:8080/xxxxxx";
options.RequireHttpsMetadata = false;
});
}
I was looking into the same issue and found a github issue discussing this same scenario.
The comments and code link there indicate that it validates the https connection for downloading metadata documents. So your reverse proxy should not impact this process and it should be left as true for security reasons.

AspNet Core Identity - cookie not getting set in production

I have a .NET Core 2 web app and I want to use ASP.NET Identity to authenticate my users. On .NET Core 1.x, my code was working fine.
I migrated to .NET Core 2, and authentication works when running locally in Visual Studio. But when I deploy to a live environment, authentication stops working: the authentication cookie isn't being set in production.
My Startup.cs code looks like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<AppUser, RavenDB.IdentityRole>()
.AddDefaultTokenProviders();
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseAuthentication();
}
To sign in, my code looks like this:
public async Task<ActionResult> SignIn(...)
{
var user = ...; // Load the User from the database.
await this.signInManager.SignInAsync(user, isPersistent: true);
...
}
This code works locally: the ASP.NET Identity auth cookie is set. However, when I deploy this to production enviro in Azure, the cookie never gets set.
What am I missing?
I solved the problem. It boiled down to HTTPS: it appears that signInManager.SignInAsync(...) sets a cookie that is HTTPS-only. I was publishing to a non-HTTPS site initially for testing.
Once I published to an HTTPS site, the cookie started working again.
The reason it was working locally was that I was running in HTTPS locally.
Had same problem with Chrome 60+. Cookie did not want to set on HTTP site or even HTTPS and Cordova.
options.Cookie.SameSite = SameSiteMode.None;
https://github.com/aspnet/Docs/blob/master/aspnetcore/security/authentication/cookie.md
Changing from default value (Lax) to None fixed it for me.
I had similar issue. In the startup.cs file, I had to change
app.UseCookiePolicy(new CookiePolicyOptions
{
Secure = CookieSecurePolicy.Always
});
to
app.UseCookiePolicy(new CookiePolicyOptions
{
Secure = CookieSecurePolicy.SameAsRequest
});
This allowed cookie authentication to work on both http and https.

thinktecture identity server 3 authentication works correctly in iis express, but keeps on throwing 401 unatuhorized when hosted in iis

Ok so i tried hosting the simplest oauth sample and the identity server both on iis, i have enable cors on the simplest oauth sample. So when i test the api using the javascript implicit client, on iis express it works flawlessly, it gets the token then when the token is sent the web api checks the token and authorizes the javascript client. the problem happens when i move the javascript imlicit client, the identity server, and the simple oath web api is hosted on iis, the javascript brings back the token correctly but when the token is sent to the web api it always return 401 unauthorized. So is there any configuration i have to add in order to run it on iis. i have made sure that anonymous authentication is the only enab;ed authentication mode. Any help or pointer is deeply appreciate.
I am trying to implement the samples given on iis. thanks for the help
I had the same issue. It was coming from my self signed certificate.
Try adding to your IdentityServerOptions
RequireSsl = false
and switch the WebApi Authority to use http.
Edit
Server Side Configuration
public void ConfigureIdentityServer(IAppBuilder app)
{
//Configure logging
LogProvider.SetCurrentLogProvider(new DiagnosticsTraceLogProvider());
//This is using a Factory Class that generates the client, user & scopes. Can be seen using the exmaples
var IdentityFactory = Factory.Configure("DefaultConnection");
app.Map("/identity", idsrvApp =>
{
idsrvApp.UseIdentityServer(new IdentityServerOptions
{
SiteName = "Security Proof of Concept",
SigningCertificate = LoadCertificate(),
Factory = IdentityFactory,
CorsPolicy = CorsPolicy.AllowAll,
RequireSsl = false
});
});
}
JavaScript
After receiving the token make sure it's inserted in the Authorization Header..
JQuery Example
$.ajax({
url: 'http://your.url',
type: GET,
beforeSend: function (xhr) {
xhr.withCredentials = true;
xhr.setRequestHeader("Authorization", " Bearer " + apiToken);
}
});
WebApi Resource
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
//Location of identity server make full url & port
Authority = "http://localhost/identity",
RequiredScopes = new[] { "WebApiResource" }
//Determines if the Api Pings the Identity Server for validation or will decrypt token by it's self
//ValidationMode = ValidationMode.Local
});
Best way to determine what is happening is enable logging.