How can I set different Authentication Mode in Web.config in different host/domain name?
For example, I have 3 different environments:
Host 1. localhost (For local dev use)
Host 2. abc-test.com (For Stage)
Host 3. abc.com (For Production)
I would like to set the Host 1 and Host 2 with <authentication mode="Windows" />, but "none" for Host 3, as it will be run with Azure SignIn method.
Note:
I figured out when I set <authentication mode="Windows" /> in web.config and specify the if-else clause in controller to distinguish which domain name to retrieve the userIdentity, the "Non-Windows Auth" and Request.IsAuthenticated (For Azure SignIn) will not be working properly.
Hope one of you has experienced the same before and may provide me with the best solution.
Thanks in advance! :)
Related
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
}
I'm trying to programmatically read (and only read) various IIS settings from remote servers (Win 2k8/IIS7 , or Win2k12/IIS8).
Have tried but eventually gave up on Microsoft.Web.Administration and WebConfigurationManager methods, because they require certain security "flexibility", which isn't feasible for me.
I found WMI impersonation capabilities the most adequate, and I am able to get the settings which reside within ApplicationHost.config file.
So far I've not been able to find a way to use WMI to read from the web.config file at the virtual directory level.
Currently I'm looking to read Authentication settings - "mode", and the various attributes of that mode.
To illustrate, this is the portion of the web.config file I'm interested in (example for Forms Authentication):
<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Login.aspx" name=".ASPXAUTH" timeout="360" />
</authentication>
<system.webServer>
</configuration>
Is there a way to reach this data using WMI?
Or can you think of another (secure) method to achieve this goal?
Appreciate the help!
EDIT found the right namespace and posted it in an answer
The WMI doesn't provide any class to read the content of a file.... but for your particular case you can check the IIS WMI Provider reference and try something like the IIsWebFileSetting class.
Turns out I was using the wrong WMI Namespace (MicrosoftIISv2).
The namespace I should've been using is WebAdministration. It has access to the properties I'm looking for (specifically those related to Forms Authentication). More info here - http://wutils.com/wmi/root/webadministration
I'm now facing another problem, where I'm able to connect to this namespace on one machine and query for data, but not on another (seemingly identical) machine.
Guess that's a subject for a different question, though.
I have two websites hosted on the same server (IIS6 on Windows Server 2003 R2).
URL for the first website is www.domainname.com URL for the second website is my.domainname.com/website2 where "website2" is a virtual directory under "my" website on the same server.
I have configured Single Sign On using forms authentication on both sites and it was working very well. After I moved the first website to another server (IIS7 - Windows Server 2008 R2) SSO stopped working (both ways).
"machineKey" and "forms" values are identical on both sites (see below).
I can see that the ticket is passed from the server logs.
I get the "Forms authentication failed for the request. Reason: The ticket supplied was invalid." error on the Event Viewer.
both sites use .net 4
------- Configuration start
<machineKey validationKey="key1" decryptionKey="key2" decryption="3DES" validation="SHA1" />
<authentication mode="Forms">
<forms requireSSL="true" name="domainnameAuth" domain=".domainname.com" loginUrl="login.aspx" timeout="20" protection="All" path="/" />
</authentication>
What am I missing here?
Any help on how to debug this situation is greatly appreciated.
The issue disappeared after installing update http://support.microsoft.com/kb/2656351
I beleive there was an issue with FormsAuthentication.Decrypt/Encrypt and that was fixed after this update.
Thank you for your help Henk!
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" />
How can I configure IIS to prompt for passwords on a web application running on ASP.NET MVC in IIS?
I want to password protect the Views\ApplicationLog\ folder, so that browsers ask for username and password when users try to access this folder.
How could I accomplish this? Can this be done directly from IIS, or do I need to set something in web.config?
Please try to be thorough, I don't know IIS all that well.
If you're using MVC, you shouldn't have anyone directly accessing anything under your Views folder at all. Instead, your Controllers (or their actions) will assert whatever authentication is required.
In this specific case, it looks like your controller is named ApplicationLogController. So you'd add an [Authorize] attribute on the controller as follows, and it will automatically ensure that anyone accessing the controller methods is authorized.
[Authorize] // You can also do [Authorize(Roles="MyRole,YourRole")], etc...
public class ApplicationLogController : Controller
{
...
}
In the IIS 6 manager, go to the "Directory Security" tab, click on "Edit" then check "Integrated Windows Authentication" and / or "Basic Authentication" depending on the modes you want to support.
In system.web within your app's web.config:
<authentication mode="Windows">
<authorization>
<deny users="?" />
</authorization>