Selectively Accept Client Certificates in ASP.Net WebAPI - asp.net

I have a request to allow customers to select to authenticate to our service using mTLS (Mutual Authentication). The problem I have is I want to allow this only on one endpoint and only in special circumstances. I do not want to globally accept or require Client Certificates on each request. The setting in IIS allows Ignore, Accept, or Require.
When I set it to Accept and browse to the site in Chrome I get this pop-up
Is there a way to accept the certificates if they are passed to a specific endpoint but not change the behavior of other endpoints?

To enable SSL Negotiation settings on a specific route you can apply that setting to a specific location
<location path="Route/Goes/Here">
<system.webServer>
<security>
<access sslFlags="SslNegotiateCert"/>
</security>
</system.webServer>
</location>
Depending on how your IIS is setup this may cause a 500 error saying "This configuration section cannot be used at this path. This happens when the section is locked at a parent level." If that happens you need to enable the SSL Settings Read/Write flag as seen here:
Or using Powershell:
Set-WebConfiguration //System.WebServer/Security/access[#sslFlags] -metadata overrideMode -value Allow -PSPath IIS:/

Related

This attempt to set a cookie via a Set-Cookie was blocked because it had the "Secure" attribute

I have an ASP.NET webforms/mvc hybrid app deployed on IIS 10. I have two bindings for this app one with just a localhost:portNo binding and another with DNSDomainName:portNo binding. Both are Http bindings. SSL is turned off. I get the error
"This attempt to set a cookie via a Set-Cookie was blocked because it had the "Secure" attribute but was not received over a secure connection."
when I test the DNSDomainName:portNo binding (it is failing to set sessions). The localhost:portNo binding works without any issues. Why is this happening? and how do I fix this?
Your cookies are configured to require an HTTPS connection. When you try to set them on a non-secure connection, they will be rejected.
Check your web.config file settings for:
<httpCookies requireSSL="true" />
Change that setting to false, and your session cookies should start working.
NB: Once you publish your site, it should only ever be served over HTTPS, and this setting should be changed back to true.
Secure Cookie Attribute | OWASP Foundation
The localhost binding works because most browsers have special-case code to treat connections to that host name as "secure", even if they don't use HTTPS.
Locally-delivered resources such as those with http://127.0.0.1 URLs,
http://localhost and http://*.localhost URLs (e.g.
http://dev.whatever.localhost/), and file:// URLs are also considered
to have been delivered securely.
Secure contexts - Web security | MDN

IIS doesn't appear to be using a defaultProxy defined in machine.config

I have an ASP.NET Web API running locally which I'm debugging with Fiddler. The API is running under an application pool account and makes a number of calls out to an external API.
When I run an acceptance test against my local API and capture requests in Fiddler I don't see those external requests, just the HTTP calls made directly within the test's app domain. Having done some reading I see that I need to configure IIS to use a default proxy to route all traffic through Fiddler.
So, I tried adding this to my web.config's system.net:
<defaultProxy>
<proxy autoDetect="false" bypassonlocal="false" proxyaddress="http://127.0.0.1:8888" usesystemdefault="false" />
</defaultProxy>
This works well. Fiddler now shows me all the internal HTTP requests being made by the API. However, I don't want to affect other developers by committing this web.config change, so I tried moving this section to my machine.config.
Having done this, even though I can see the configuration being pulled through to my IIS application (screenshot below), I don't see the same requests in Fiddler which suggests to me the proxy is not being used. Even after an iisreset.
Can anyone shed any light on this?
Update 1
#lex-li pointed out that usesystemdefault in my screenshot is true whereas I'd set it to false in machine.config. It seems this particular value is not pulled through to the application configuration from machine.config for some reason. However, if I override just that value in web.config as below, the application still doesn't use the proxy.
<system.net>
<defaultProxy>
<proxy usesystemdefault="false" />
</defaultProxy>
</system.net>

Enabling SSL Client Certificate Required for specific Controller or Action in Asp.Net MVC

Is there any MVC specific way to require an SSL Client Certificate for a specific Action or Controller, i.e very much the way RequireHttps or Authorize works, but for ClientCerts?
I know about the trick where you create an empty folder in the site, a Controller with the same name as the folder and then set up a rule in web.config, but I don't want to do it this way, I am looking for an MVC solution if there is one.
(Example of the web.config trick:)
<location path="/ClientCert">
<system.webServer>
<security>
<access sslFlags="Ssl,SslRequireCert" />
</security>
</system.webServer>
</location>
I'm curious if there is a solution that can be encapsulated in an ActionFilter and/or HttpModule?
I don't believe so. Client Certificates are handled and mapped in IIS or HTTP.sys during connection negotiation, which is way lower down than MVC. If that client certificate is being used for mutual authentication with SSL/TLS, then the client certificate is needed just to establish a HTTPS session and connection.
This all happens well before MVC, or any code for that matter, is given a chance to run. This happens down in the kernel in HTTP.sys.

Request.IsAuthenticated return different value on https and http page

I created a project using asp.net mvc 5.1, asp.net identity 2.0. After I deploy it to IIS, when I go to secure page 'https://www.xxxx.com/Account/Login', after login, if I go to https://www.xxxx.com. Request.IsAuthenticated return true on _LoginPartial.cshtml page, but go to http://www.xxxx.com, always return false.
It sounds like you may have the option set to only send the authentication cookie over HTTPS, therefore if you navigate to a page over HTTP, the authentication cookie is not sent and the application believes you to be unauthenticated.
The setting in question is requireSSL in the system.web/authentication/forms section
<authentication mode="Forms">
<forms name="auth" loginUrl="~/login" requireSSL="true" />
</authentication>
and this controls whether the secure property is used on the authentication cookie.
Since you are using HTTPS, I would recommend preventing the site from being navigated over HTTP.
RequireSSL will only allow the cookie to be transferred across https. In case you have this specific requirement then you need to take additional precaution in the code.
But beware, of what you are doing at this point.
You can use Request.IsSecureConnection at appropriate place. This could be in the module or in the base class on or in the filter.
An out of dated article is here, but can serve as a pointer.
http://r2d2.cc/2011/08/05/how-to-switch-between-http-and-https-in-asp-net-mvc2-and-allow-ajax-requests-from-site-master/
Caution: Use with care, as you may need to take additional precaution on the server to avoid hijacking.

Forms Auth requireSSl and Https

If my login pages are https, does it matter if "requireSSl" is true in the forms tab of the web config?
Currently I am redirecting pages with IIS to HTTPS. When I set requiressl it seems to cause problems.
Can someone put the two settings in perspective. thanks
if you set https at the server level then requireSsl does not matter (setting it on or off should not make any difference). After setting https required, set a redirect as mentioned in this article:
http://www.jppinto.com/2009/01/automatically-redirect-http-requests-to-https-on-iis-6/
====
reference
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.requiressl.aspx
You can specify in the Web.config file for your ASP.NET application whether SSL (Secure Sockets Layer) is required to return the forms-authentication cookie to the server by setting the requireSSL attribute

Resources