简体   繁体   中英

Using Windows Authentication, define AD-Server

We are developing a web-app which allows us to edit data from databases. Because this app should be reachable from outside, we decided to put it on one of our DMZ-servers. To have a centralized control over all user accessing this service, we decided to use Windows Authentication. But since the DMZ-servers are not members of the Active Directory in our local LAN, this does not work yet (getting "401 - Unauthorized: Access is denied due to invalid credentials.").

I tried to specify the LDAP-ConnectionString like described here ASP.NET MVC: How to setup web.config for LDAP authentication? . But it does not work. I guess, this config was not designed to work with Windows Authentication ( <authentication mode="Windows"/> ). Even if I test it on the local machine and put in wrong credentials, it authenticates me. So my guess is, that this config is getting entirely ignored.

<connectionStrings>
    <add name="ADConnectionString" connectionString="LDAP://<IP of AD-Server>/DC=<DomainName>"/>
</connectionStrings>
<system.web>
[...]
<authentication mode="Windows"/>
<authorization>
  <deny users="?" />
</authorization>
<membership defaultProvider="ADMembershipProvider" >
  <providers>
    <clear/>
    <add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" 
         connectionStringName="ADConnectionString"
         connectionUsername="<Domain>\<LDAP-Reader-User>"
         connectionPassword="<LDAP-Reader-Password>"/>
  </providers>
</membership>

To be sure that the problem doesn't lie on the LDAP-Communication I made a LDAP-Query-Test. The DMZ-server is actually able to send LDAP-queries. I tested following and got positive results (and negative results by providing a wrong password)

public bool TestPrincipalContext()
{
    PrincipalContext c = new PrincipalContext(ContextType.Domain, "<IP of AD-Server>", "<LDAP-Reader-User>", "<LDAP-Reader-Password>");
    return c.ValidateCredentials(Request.Form["username"], Request.Form["password"]);
}

Question:

What I am looking for is like a config or a "custom-security-provider" where I can specify the LDAP-Server and use all inbuilt features of Windows Authentication. Is this possible? How would I do this?

Disclaimer

This may not help everyone and is probably not the cleanest method, but it helped me.

To explain why I choose this method, here are the circumstances:

  • Basically we just want to check if a given user has the right to access certain elements, by checking his group-membership (by using [Authorize] and User.IsInRole ). And we want to manage all users on one place (AD)

  • We have a limited timeframe, which does not allow us to invest too much time to find the best way.

  • We already know what AD-Server we will be using and how we treat the users that will have access to the said service. Also, users can't register by them selfs, so overall we have the control over, who has access to our ressources.

  • We want to keep the amount of running services as low as possible and since ADFS would be an additional service for us, we searched for alternatives.

  • Since the "Security-Management" is leaned on the FormsAuthentication (Cookie encryption) we believe it to be secure. Also we created a service-user with limited permissions to just read the LDAP.

If you have security concerns, better solutions or just suggestions, feel free to add comments/answers.

Quick Overview

I ended up, creating a custom "SecurityProvider". I got inspired by https://support.microsoft.com/en-us/help/316748/how-to-authenticate-against-the-active-directory-by-using-forms-authen which describes the Authentication using FormsAuthentication and .aspx.

Basically it sets the User ( HttpContext.User ) in the Application_AuthenticateRequest -Method in Global.asax. This is done by using a decrypted Cookie, which is set in the login with the help of PrincipalContext and FormsAuthentication .

CustomPrincipal

Since UserPrincipal does not implement IPrincipal , I made a wrapper called CustomPrincipal which implements IPrincipal and has a UserPrincipal as Property. This way I can retrieve a UserPrincipal -object from PrincipalContext and use it as User ( HttpContext.User ).

Application_AuthenticateRequest

Here I checked if the user is logged in by checking the cookie, and if he is, decrypt the cookie to get the username, create the needed CustomPrincipal -object and setting it as the User.

Login

On Login it takes the given username and password and uses the PrincipalContext to check if the given credentials are valid ( PrincipalContext.ValidateCredentials(username, password) ). If they are, a encrypted cookie containing the username gets generated.

Logout

Logout just lets the "Auth"-Cookie expire. Simple as that...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM