IIS MVC/WCF Certificate authentication on specified pages - c#

The problem I am facing is that I only want the clients (end users) to present a certificate on specified pages within the MVC/WCF application.
When I set the IIS options "Client certificates = Accept" the site always requires a certificate when browsed, shouldn't be this way when setting the option to "Required" ?
Googled for a while but web.config configurations to override the IIS certificate check and only do certificate check on certain pages does not turn up many results.
In a simplified way what I want to accomplish is:
User browses Home page
Reads some news articles
Goes to a page that requires authentication
Make the user/client present a certificate
Here on I will make some checks to the certificate programatically (this bit I have solved)
I don't provide any code cause I don't have any, everything I have is the certificate option in IIS.

Figured out the answer.
Location tag and in the applicationHost.config allow override the "access" section
applicationHost.config
<section name="access" overrideModeDefault="Allow" />
Application web.config
<location path="PathToSvcFile.svc">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true"/>
</authentication>
<access sslFlags="Ssl, SslNegotiateCert"/>
</security>
</system.webServer>

Related

proper implementation of "windows" authentication in web api?

I've created a Web Api 2 app which will only be used on the corporate network. I've read about Windows authentication in Web API so it seems to be possible. But I need to figure out the proper implementation for this. I've included the following xml in my Web.config:
<system.web>
<authentication mode="Windows" />
</system.web>
I seem to remember some type of event hook in old school webforms app. Something like BeginRequest() where a security check could be made before rendering a page. I included the following line of code as the first line in one of my controller methods but the returned value appears to just be an empty object without any meaningful info:
var identity = HttpContext.Current.User.Identity as WindowsIdentity;
Does Web API 2 support Windows authentication? Am I missing a step? Should Windows authentication work if I submit a general request from Postman for testing? I also tried this code but got a similar empty object:
var x = RequestContext.Principal;
I vaguely recall an IIS setting like "Enable Integrated Security." Can you please specify the exact setting? And would I be able to accomplish this if I'm running the app on IIS Express?
UPDATE
I followed the steps for IIS Express mentioned in one of the answers below but the code samples that I provided in my original post still didn't get a populated user object. I also updated applicationhost.config file to turn off anonymous authentication:
<anonymousAuthentication enabled="false" userName="" />
After I made that updated I resubmitted my test request via Postman but I get the following error:
<h3>HTTP Error 401.2 - Unauthorized</h3>
<h4>You are not authorized to view this page due to invalid authentication headers.</h4>
</div>
<div class="content-container">
<fieldset>
<h4>Most likely causes:</h4>
<ul>
<li>No authentication protocol (including anonymous) is selected in IIS.</li>
<li>Only integrated authentication is enabled, and a client browser was used that does not support integrated authentication.</li>
<li>Integrated authentication is enabled and the request was sent through a proxy that changed the authentication headers before they reach the Web server.</li>
<li>The Web server is not configured for anonymous access and a required authorization header was not received.</li>
<li>The "configuration/system.webServer/authorization" configuration section may be explicitly denying the user access.</li>
</ul>
</fieldset>
</div>
<div class="content-container">
<fieldset>
<h4>Things you can try:</h4>
<ul>
<li>Verify the authentication setting for the resource and then try requesting the resource using that authentication method.</li>
<li>Verify that the client browser supports Integrated authentication.</li>
<li>Verify that the request is not going through a proxy when Integrated authentication is used.</li>
<li>Verify that the user is not explicitly denied access in the "configuration/system.webServer/authorization" configuration section.</li>
<li>Check the failed request tracing logs for additional information about this error. For more information, click
here.
</li>
</ul>
</fieldset>
</div>
Do I need to configure my Postman request with some type of special header in order for this to work?
In addition to the previous answers, we also need to Pass credentials in cross-origin requests.
Server Side (Web API):
Set the SupportsCredentials property to true on the [EnableCors] attribute:
[EnableCors(origins: "http://exampleclient.com", headers: "*",
methods: "*", SupportsCredentials = true)]
Client Side (UI):
Set XMLHttpRequest.withCredentials to true.
jQuery:
$.ajax({
type: 'get',
url: 'http://www.example.com/api/auth',
xhrFields: {
withCredentials: true
}
Angular:
this.http.get('http://www.example.com/api/auth', { withCredentials: true }).subscribe((resp: any) => {
console.log(resp)
}
XMLHttpRequest:
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://www.example.com/api/auth');
xhr.withCredentials = true;
If you are using IIS Express, you need to update applicationhost.config file.
This is the file version of the IIS configuration tool where you can configure the web server itself. you can find this file in the following directory:
%userprofile%\documents\iisexpress\config\applicationhost.config
or
%userprofile%\my documents\iisexpress\config\applicationhost.config
When you find it, update it as:
<windowsAuthentication enabled="true">
<providers>
<add value="Negotiate" />
<add value="NTLM" />
</providers>
</windowsAuthentication>
For IIS:
Select your Application
Double Click - 'Authentication'
Enable Windows Authentication
Restart IIS Server
Check this for more details
Windows authentication that uses the local domain user and that is intended for intranet sites.
Example :
I implemented a TestAuthentication method/action with a fixed route path. For the demo I do not include Authorize attributes yet. The code checks the User property of the ApiController. This contains the same data as Thread.CurrentPrincipal or HttpContext.Current.User. Make sure Anonymous Authentication in IIS is disabled otherwise the Identity.Name will be empty.
public class WinAuthController : ApiController
{
[HttpGet]
[Route("api/testauthentication")]
public IHttpActionResult TestAutentication()
{
Debug.Write("AuthenticationType:" + User.Identity.AuthenticationType);
Debug.Write("IsAuthenticated:" + User.Identity.IsAuthenticated);
Debug.Write("Name:" + User.Identity.Name);
if (User.Identity.IsAuthenticated)
{
return Ok("Authenticated: " + User.Identity.Name);
}
else
{
return BadRequest("Not authenticated");
}
}
}
In Web.config file :
<system.web>
<authentication mode="Windows" />
</system.web>
In IE you can check the setting with Tools > Internet Options > Advanced and look for a setting Enable Windows Integrated Authentication. When you go to the tab Security and then Intranet and Custom Level, then you will find a setting at the bottom to specify if IE should logon automatically or prompt for the username and password.
Please visit below link, it has proper steps to follow for WEP API Windows authentication :
http://www.scip.be/index.php?Page=ArticlesNET38&Lang=EN
Below are the steps to configure windows authentication in web api for both local and server (IIS).
1) For Local:
a) To create a web api project in windows authentication mode, follow below steps:
After choosing ASP.Net Web Application, select Web API template and from the right side click Change Authentication button and select Windows Authentication.
b) For an existing web api project, just add the following lines in your applicationhost.config file.
<location path="YourProjectName">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
2) For Server (IIS)
To run windows authentication after hosting the application in IIS just add following lines in your web.config file inside system.web node:
<authentication mode="Windows" />
<authorization>
<allow verbs="OPTIONS" users="?" />
<deny users="?" />
</authorization>
In both the cases, just use the following lines in your code that windows authentication is working properly:
if(User.Identity.IsAuthenticated)
{
//do work
}

MVC 5 C# Window Authentication pop up when I navigate to a certain area

I have an application with multiple areas. I have no problem navigating to any of them once logged in.
I've added a new 'Reports' area, now when I navigate to that area I get an 'Authentication Required' pop up appear which I think is something to do with Windows authentication which isn't being used in the application.
I'm using <authentication mode="None" /> in web.config.
This only happens when the site is live and not local (which makes sense if it's a windows authentication issue).
All controllers in the areas use the same custom authentication attribute, any ideas why I wouldn't be able to navigate to this new area even though going to others is absolutely fine, any ideas what i'm missing? I don't remember having to do anything in other areas to allow access.
Thanks.
I found the issue. The URL that was causing the issue was
www.domain.co.uk/reports
I remembered a while ago I was doing some testing using SSRS and setup the Report Manager URL as localhost/reports. This must have been causing the issue as once I had changed the Report Manager URL I could access the URL I was having issues with as expected.
That setting in your web.config should be working.
It could be that it's not overriding the settings in the applicationhost.config file as it should.
To test this out navigate to the "\IISExpress\config\applicationhost.config" file and set <windowsAuthentication enabled="false" />
Other things you can try.
Remove forms authentication - sites often default to this.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true>
<remove name="FormsAuthentication />
</modules>
</system.webServer>
Disable security for that path.
<location path="secureddir/newform.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>

Display IFrame from same domain under SSL

I am trying to wrap a login section of our page in an iframe which has been created with SSL and display it on several pages across our companies website (kind of like a login widget).
However I keep getting an error on the page rendering the iframe indicating that:
Refused to display in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.`
The login widget and webpages that I want to display it on are hosted under the same domain, is this an issue?
I have searched around and nothing seems to be able to avoid this problem. Does anyone have a solution to this issue?
<iframe sandbox="allow-same-origin allow-forms allow-scripts" src="https://<sitename>/loginiframewidget.aspx"></iframe>
At the moment these are what I have in my web.config
<httpProtocol>
<customHeaders>
<add name="access-control-allow-headers" value="content-type" />
<!--<add name="Access-Control-Allow-Origin" value="*" />-->
<add name="Content-Security-Policy" value="frame-ancestors 'self' mysite.com.au"/>
<add name="X-Frame-Options" value="ALLOWALL"/>
</customHeaders>
</httpProtocol>
And the headers that appear in Chrome Dev Tools on the page are:
There are security issues with this implementation anyway.
The first is that you can't be sure the content of the unencrypted page hasn't been altered on transmission and has pointed the src of the iframe elsewhere.
The second is that even if a user logs in with SSL, their session ID in the cookie is being sent in the clear and is easy to spoof.
Would you consider running the entire site in SSL? These days servers cope with this better than you'd think, and you wouldn't need iframes any more.
Try setting the frame-ancestors directive of the Content-Security-Policy header, and the X-Frame-Option header for older versions of IE.
http://caniuse.com/#feat=contentsecuritypolicy
You can add these through IIS, or add them into your web.config file:
<system.webServer>
...
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="frame-ancestors 'self' mywebsite.com" />
<add name="X-Frame-Options" value="ALLOW-FROM http://mywebsite.com" />
</customHeaders>
</httpProtocol>
...
</system.webServer>
The headers should now be sent down to the browser:
No means big No, you just can't do it, you can't access SSL resources on non SSL page, and is your client willing to expose everything on internet? Allowing frame options will still not work because browser will not allow you to cross SSL boundaries.
HTTP is not at all secure, this is the reason, every site in google is now under SSL, because non SSL content can be altered by ISPs and Firewalls, in fact ISPs, Firewalls and other routers are continuously injecting scripts on page to monitor traffic.
Explain your client that today running an authenticated session under non HTTPS is equivalent to locking doors of home but leaving all windows open !!!.
With keep alive, SSL negotiation any way happens only once and performance is very negligible, you can improve site speed by outsourcing CDN to CloudFront or any other CDN with their subdomain SSL.
OAuth - But Recommended only under SSL anyway
You can implement your own OAuth Provider and use it to distribute OAuth tokens that can be used to validate in your website at server side. Your site can use secondary tokens issued by OAuth provider to validate user and you can redirect users to OAuth Provider which can run under SSL. This way, you can allow users to do limited non secure things under authentication on non SSL pages. Just like how you can use Facebook/Google login etc under non SSL sites as well.

Forms Authentication across Sub-Domains on local IIS

I know a cookie can be shared across multiple subdomains using the setting
<forms
name=".ASPXAUTH"
loginUrl="Login/"
protection="Validation"
timeout="120"
path="/"
domain=".mydomain.com"/>
in Web.config. But how to replicate same thing on local machine. I am using windows 7 and IIS 7 on my laptop. So I have sites localhost.users/ for my actual site users.mysite.com
localhost.host/ for host.mysite.com and similar.
localhost.users and localhost.host is cross domain. Cookies cannot be shared cross domain.
You could configure it like this so that the sub-domain differs but the root domain stays the same:
users.localhost
host.localhost
Now set the cookie domain in your web.config to localhost:
domain=".localhost"
and in your c:\Windows\System32\drivers\etc\hosts file add the following 2 entries:
127.0.0.1 users.localhost
127.0.0.1 host.localhost
Now you will be able to successfully share the authentication cookie between users.localhost and host.localhost.
Ah, and don't forget to put a step in your automated build process that will transform your web.config value to the correct root domain before shipping in production.
This is a reminder for anyone running in Framework 4.5 and trying to share the token with frameworks 4 and lower, please notice that this will cause you not to receive the auth cookie on any of the 4 and lower apps. ie: if in your web.config you have:
<httpRuntime maxRequestLength="80480" targetFramework="4.5" />
You can get it to work by removing the targetFramework="4.5" attribute to get it to work, though I don't know if there are any side effects in doing so:
<httpRuntime maxRequestLength="80480" />

ASPX FormsAuthentication.RedirectFromLoginPage function is not working anymore

Here is my issue. I have an ASPX web site and I have code in there to redirect from the login page with the call to "FormsAuthentication.RedirectFromLoginPage(username, false);" This sends the user from the root website folder to 'website/Admin/'. I have a 'default.aspx' page in 'website/Admin/' and the call to redirect works on a previous version of the website we have running currently, but the one that I am updating on a separate test server is not working. It gives me the error "Directory Listing Denied. This Virtual Directory does not allow contents to be listed." I have this in the config file:
<authorization>
<allow users="*" />
</authorization>
under the "authentication" option and...
<location path="Admin">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
for the location of Admin.
Also, there is no difference in the code between the web.config, Login.aspx, or the default.aspx files on the current server and the one on the test server, so I am confused as to why the redirect will not work on both. It even works in the Visual Studio server environment, for which the code is also identical.
Any suggestions and help is appreciated.
Directory Listing Denied is an IIS error, stating that directory browsing on the server isn't allowed. If you see this, it means when browsing to Website/Admin, the server isn't finding any expected default documents and is then trying to show you the file directory through the browser (expected behavior). IIS is set to not allow this in your case (which is a good thing).
Can you contact the server admins and ask them to verify the default documents for the website, and add Default.aspx to the list? If not, at least find out what the default file names are in the site setup, and name your root page based on that.
I think by default IIS uses Default.htm and maybe one other. Even when registering asp.net with IIS, I don't believe Default.aspx is added. It has to be done manually.

Categories