I have a C# .NET framework backend API. I am implementing AD login, but have a problem, where the PrincipalContext constructor does not work without the username and password, which should not be the case.
The line in question is:
var principalContext = new PrincipalContext(
ContextType.Domain,
System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName
);
It works fine on a different computer with the current web.config file, so I am guessing my IIS is not set up correctly or the permissions are incorrect.
I am running the API in VS2022 in debug mode, local IIS, and the website is inside Default Web Site in IIS.
My application pool identity is set to ApplicationPoolIdentity, in authentication I have only anonymous authentication enabled (I have also tried only Windows authentication and both).
I have also noticed, that the line
System.Security.Principal.WindowsIdentity.GetCurrent().Name;
returns domain\\username on the computer where it works, and returns iis apppool\\app pool name on my computer.
Also, this is my web.config file for reference:
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
<!-- so only the Tokens controller uses Windows authentication and all others can use JWT tokens -->
<location path="Tokens">
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true" />
<anonymousAuthentication enabled="false" />
</authentication>
</security>
</system.webServer>
</location>
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="false" />
<anonymousAuthentication enabled="true" />
</authentication>
</security>
...
</system.webServer>
the problem on your localhost should be caused because your application pool uses a local system identity, you can change it with a domain user that has the permission to retrieve the information to the domain controller
Let me now if you need more information how to change the app pool identity.
Regards
Jerry
If you don't pass in a username and password, the PrincipalContext constructor will use the credentials of the account running the application pool to host the asp.net application in IIS to connect to Active Directory. ApplicationPoolIdentity is a dedicated pseudo-user account for the application pool worker process, it is recommended that you change the application pool identity.
LocalSystem - The Local System account has all user rights and is part
of the Administrators group on the Web server. Avoid using the Local
System account if possible, as it can pose a serious security risk to
your web server.
NetworkService - By default, the Network Service account is selected.
It is a member of the Users group and has the user rights required to
run the application. It can interact in Active Directory-based
networks by using computer account credentials. This account provides
maximum security against attacks that might attempt to take over the
web server.
LocalService - The Local Service account is a member of the Users
group and has the same user rights as the Network Service account, but
only on the local computer. Use this account when the worker processes
in your application pool do not need access outside the web server
they are running on.
It is recommended that you set up a domain service account dedicated to the IIS application pool.
You need to create a domain service account firstly.
Under Administrative Tools, open the Active Directory Users and
Computers.
Right-click the directory where you want to assign
this account (ie testlab.com > Service Accounts) and select New >
User.
Add a name and login for the service account.
Click Next and enter a password. Clear User must change password at next
logon.
Choose between a password that never expires or an account that locks
you out of the secret server.
Click Next, then Finish.
Assign the identity of the application pool in IIS.
Select the corresponding application pool, right-click and select Advanced
Settings.
In the Process Model section, select Identity and click the
ellipsis.
Select Custom Account, click Set, enter your service account name and
password, and click OK.
Grant folder permissions
Give the service account Modify and Access to the folder where the application files reside.
Related
I am wondering if it's possible, and if so, how to have an ASP.net website on IIS use the windows credentials of the currently logged in user for Directory.CreateDirectory and File.Copy commands.
Currently my application works when running locally, however it doesn't work when hosted on the server using IIS.
It is set to only allow Windows Authentication and ASP.Net Impersonation on the server.
Directory.Exists() always returns false, I'm assuming because it is using the IIS user instead of the windows user which doesn't have permissions to access the server I am checking files on (other calls above fail too). I don't want to supply user credentials as I would like each logged in user to only have permissions to preform what their credentials give and not what an admin credentials have permissions to.
Web.config authentication setup
<authentication mode="Windows" />
<authorization>
<deny users="?" />
</authorization>
<identity impersonate ="true"/>
EDIT:
Ended up creating a service account with access to the folder and using that for the Application Pool. When I get some more free time I might come back and try to figure out the issue (have a feeling it might have to do with a double-hop as I am going from IIS to another server not the IIS server itself. But don't currently have permission to setup IIS Server as a delegate and test if that does anything).
I'm developing an ASP.NET MVC 5 app with .NET Framework 4.5.1 and C#.
On web.config I have added this:
<authentication mode="Windows" />
<authorization>
<deny users="?" />
</authorization>
And set on ASP:NET MVC Visual Studio project Windows authentication enabled and disabled Anonymous authentication.
This app will be use inside an Intranet, and I am confuse because I have found this article, How To: Secure your ASP.NET MVC application and use Active Directory as the Membership Provider, and it tells that I have to use a connection string to LDAP.
Is that necessary?
Now, when I try to enter the app I have to put my domain credentials and it works fine.
I ask this because I want to secure my controllers with Active Directory Groups and, on the same blog, here: How to use Active Directory groups to restrict access to controller actions in ASP.NET MVC and make your application even more secure!, tells how to do it but I'm not sure if I need to add an LDAP connection to my app.
You are confusing Windows authentication with Active Directory - the two do not necessarily go together. The article you have linked to describes how to connect Forms Authentication to Active Directory. For this option, you would re-enable anonymous authentication, and disable windows authentication. Your MVC code would take the username and password and authenticate these against Active Directory. The advantage of this approach is that it will work on any browser, and from a computer not on Active Directory. It is simply using AD credentials, rather than Windows Authentication.
In Windows Authentication, the browser takes care of authenticating you with the current domain. Your MVC app will never see a password, and does not need to handle this information. With this approach, you may be limited by browser choice, and it definitely won't work from a computer not connected to your Active Directory. This answer describes an approach to using AD Groups with Windows Auth.
The main bit you still need to do is to enable the Windows role manager component, using the following in web.config:
<roleManager enabled="true" defaultProvider="WindowsProvider">
<providers>
<clear />
<add name="WindowsProvider" type="System.Web.Security.WindowsTokenRoleProvider" />
</providers>
</roleManager>
You should then be able to use the normal group membership checks, such as:
[Authorize(Roles = #"AD\GroupName")]
Or
if (User.IsInRole(#"AD\GroupName")) { ... }
I have an ASP.NET application, which runs on machine 1.
When a user access that page from machine 2, I want to find out the user name, under which he or she is logged in on machine 2.
I tried to use
Request.LogonUserIdentity.Name
Page.User.Identity.Name
((WindowsIdentity)HttpContext.Current.User.Identity).Name
((WindowsIdentity)HttpContext.Current.User.Identity).User
Request.LogonUserIdentity.User
but it doesn't work.
Request.LogonUserIdentity.Name returns NT AUTHORITY\IUSR, Request.LogonUserIdentity.User - S-1-5-17, all others - empty strings. NT AUTHORITY\IUSR is the user on the machine, on which the web application runs, not the user on the client machine.
In web.config I disabled impersonation using
<authentication mode="Windows"/>
<identity impersonate="false"/>
What can I do in order to get the user name of the user, who accesses the web page?
You have to set the authentication in IIS to Windows Authentication (and probably disable all others):
Go to:
Website
IIS - Authentication
Edit according your wishes
I am working on an ASP.Net MVC 3 application and I am having a User table that stores usernames and their passwords. I have created an additional ADUsername (stores Active Directory's Domain/Username).
I am trying to do the following:
Users running the application from Intranet should not see login page. Their Domain/Username should be received automatically and compared against ADUsername field.
Users running the application from internet (out of the local network) or users with no ADUsername value: should see the login screen and they should use my custom Username and Password fields to login.
This was very easy using Visual Studio Development Server and very difficult using IIS :)
As I set my Web.Config to use forms, I am using WindowsIdentity.GetCurrent().Name to get the current ADUsername and then, I lookup my User table to find the user and FormsAuthentication.SetAuthCookie him.
Using IIS is always returning APPPOOL\ASP.NET v4.0 user which is not reflecting the domain/user I needed.
Any Help?
This is not an easy task to accomplish. The Windows identity of your intranet user will only be available to you when Windows Authentication in IIS is enabled, an anonymous authentication disabled. When the user's browser hits the server, IIS will perform the NTLM challenge/response process to validate the user. Note that this challenge/response actually occurs on every individual HTTP request, not just once.
The problem with this mechanism is that your Forms authentication will no longer be used, as it kicks in after Windows authentication runs, and failing to authenticate just triggers an IIS access-denied - not fallback to Forms authentication.
To build a hybrid, you will need to:
Set up your main web application to authenticate users with Forms authentication. Set web.config like this. Generate your own machine key - this is key to ensure cookie sharing works
<authentication mode="Forms"><forms loginUrl="~/Account/LogOn" timeout="2880" path="/" enableCrossAppRedirects="true" name=".ASPXFORMSAUTH" protection="All" />
</authentication>
<machineKey validationKey="C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE" decryptionKey="8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F" validation="SHA1" /> <system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true"/>
<windowsAuthentication enabled="false"/>
</authentication>
</security></system.webServer>
Create a new, separate web app to use purely for the NTLM authentication. It will authorize then redirect to the main application. Sorry, the two apps can't be combined.
In NTLM web app, change web.config Authentication mode like below:
<authentication mode="Windows">
</authentication>
<machineKey validationKey="C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
decryptionKey="8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F" validation="SHA1" />
<system.webServer>
....
<security>
<authentication>
<windowsAuthentication enabled="true"/>
<anonymousAuthentication enabled="false"/>
</authentication>
<ipSecurity>
<!-- put whatever here to restrict to your LAN
<add ..../>
-->
</ipSecurity>
</security>
</system.webServer>
In NTLM webapp, the controller does one thing - extract username from (WindowsPrincipal)Thread.CurrentPrincipal(); and calls FormsAuthentication.SetAuthCookie(..). Then redirect to the main web app. Do not use WindowsIdentity.GetCurrent() as it will not be accurate without impersonation enabled [see msdn.microsoft.com/en-us/library/ff647076.aspx] which you don't want to be using
You cannot test any of this under Cassini or IIS Express; you must use IIS 7.5.
Goto IIS 7.5 and turn on Feature Delegation for "Authentication - Anonymous" and "Authentication - Windows".
Create IIS application for your Forms based app
Right click on your newly created Forms app and 'Add Application'. Set path to your NTLM authentication application, and the name to something like "IntranetAuthentication"
In browser access http://localhost/YourSite for forms authentication, and http://localhost/YourSite/IntranetAuthentication to see NTLM auth then passthru auth working back to main site
At your company, direct intranet users to use the intranet logon. Externally everyone uses regular forms authentication page.
if you're using a mixed authentication why don't you get AD User via context?
context.Request.ServerVariables["LOGON_USER"]
What is the difference between these two lines of web.config code
1.
<identity impersonate="true" />
2.
<identity impersonate="true" userName="MyUserName" password="MyPassword"/>
Where MyuserName and MyPassword are my windows credentials. If you have IIS setup to use windows credentials shouldn't "1." pass in my windows credentials and hence be the same as "2."?
My app is dying when I use "1" with an authentication error when trying to connect to my WCF service. There is obviously nothing wrong with the code in my service and the code that calls my service as "2" works just fine and passes the client credentials to my WCF service.
the IIS config for the website is setup for windows authentication and the user it runs under is trusted for delegation.
So how can I get my windows credentials passed through without hard coding them?
What you're seeing is a problem with delegation. If you use
<identity impersonate="true" />
then what happens is your ASP.NET pages will run under the credentials of the user logged in (assuming Windows authentication). However these credentials are not passed onto any calls made outside of your application such as a connection to SQL or a connection to a WCF service. You need to use the credentials passed to ASP.NET and then use impersonation before calling your web service;
using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
{
WCFTestService.ServiceClient myService = new WCFTestService.ServiceClient();
Response.Write(myService.GetData(123) + "<br/>");
myService.Close();
}
There's more details on the WCF Security Patterns and Practices site.
If you read the MSDN page about the ASP.NET identity impersonation, you will notice that if the <identity> element does not include credentials, ASP.NET will impersonate the token passed to it by IIS, which can be either the identity of the request authenticated user or the anonymous Internet user account (IUSR_machinename). Seems to me that in the scenario 1. above ASP.NET is getting the anonymous user token, which would explain the failure. You can try disabling anonymous access to your web service to force the WIndows authentication to kick in.