Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • James Woodmancy 6 posts 26 karma points
    Sep 21, 2011 @ 14:51
    James Woodmancy
    0

    Using Active Directory with mixed authentication

    Hi,

    One of our clients wishes to have a Intranet site. We want to be able to allow single sign on, so if they access the intranet when they are logged on in the office or via VPN they will automatically see the intranet.  However, if the user goes the intranet from home or in a intranet cafe, the authentication will fall back to forms authentication and they will have to input their AD username and password into the login form and this will validate them with LDAP. We are using IIS7 windows 2008.

    I have a few ideas where to start but I would be interested in hearing any ideas or hearing from someone who has done this before who could help

     

    Thanks

  • Pete 213 posts 285 karma points
    Oct 28, 2011 @ 15:18
    Pete
    0

    James

    I have a customer with exactly the same requirements. Did you find a solution? I would be interested in how you went about this and any code snippets you could mention.

    Thanks, Peter

  • James Woodmancy 6 posts 26 karma points
    Oct 28, 2011 @ 16:01
    James Woodmancy
    0

    Hi Peter,

    Our clients "intranet" site was actually been hosted on the same umbraco installtion as the main site..so we had

    Website (www.oursite.com)

    Intranet (intranet.oursite.com)

    We then used forms authentication based on the umbraco members to lock down the intranet nodes.  So if people would access intranet.oursite.com, they would be redirected to the login page and would have to enter a username and password which would connect to LDAP via LDAPS.

    if valid in LDAP then we would add them to the umbraco members

     Member m = Member.GetMemberFromLoginName(username);

                // check to see if the member exists in umbraco
                if (m == null)
                {

                    // new member, Create and map to AD with email
                    MemberType mt = MemberType.GetByAlias("Intranet");

                    Member newMember = Member.MakeNew(username, mt, new umbraco.BusinessLogic.User(0));

                    newMember.LoginName = username;

                    //Add the member to a Group
                    MemberGroup mg = MemberGroup.GetByName("Staff");
                    newMember.AddGroup(mg.Id);

                    newMember.Save();
                }

     

    In order to get SSO working we had to host a simple webpage on the clients internal IIS server within their domain that LDAP is running on.  This simple website would run under windows authentication mode, grab their username and then create a forms authentication ticket

    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal user = UserPrincipal.FindByIdentity(context,User.Identity.Name))
                        {
                            if (user != null)
                            {
                                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,user.SamAccountName,DateTime.Now,DateTime.Now.AddSeconds(10),false, user.DistinguishedName, "/");
                                encTicket = FormsAuthentication.Encrypt(ticket);
                            }
                        }
                    }

     

    then redirect to intranet.centrepoint.org.uk with the encrypted ticket in the querystring

     Response.Redirect("http://intranet.centrepoint.org.uk/?auth=" + encTicket);

    the login page mentioned before would then check to see if anything was in the auth querystring, and if so, grab it and decrypt it - if the ticket was still valid (i.e within 10 seconds of been created) then we could get the AD login name that was encrypted in the ticket and validate this username against LDAP.  if successful, then they would be redirected to the intranet home page and forms authentication cookie would be set

     

     dn = ticket.UserData;
      Authenticated = ValidateActiveDirectoryLoginByDn(dn);

                        if (Authenticated)
                        {
                            ValidateMembership(ticket.Name);

                            Member m = Member.GetMemberFromLoginName(ticket.Name);
                            if (m != null)
                            {
                                Member.AddMemberToCache(m);
                            }

                        }

     

    In order to get the forms authentication ticket to enrypt and decrypt correctly you will have to have the same machine key in the external sites web config and the internal sites web.config.

    The local intranet site had a dns entry called auth.intranet.oursite.com which people would have to type in to access the intranet via SSO and if they were at an internet cafe or home they would have to type in intranet.oursite.com to get the login page - and then enter their AD network username and password to enter.  not quiet the ideal solution but the only one that works after days of research.

     

    Cheers

    James

     

     

     

  • Pete 213 posts 285 karma points
    Oct 28, 2011 @ 16:12
    Pete
    0

    That's great, thanks for the info james.

    We've actually got the machine key problem at the moment and I was wondering how to fix it. My customer has a server with the AD on it, which does'nt have IIS, and then a server which hosts the IIS / umbraco site, I was looking down the route of the SID key setting within the registry on both machines.

    Peter

  • Tom 713 posts 954 karma points
    Nov 07, 2011 @ 05:13
    Tom
    0

    Hi James,

    just wondering what is in your ValidateMembership method and the ValidateActiveDirectoryLoginByDn Method?

     

    I have been looking for a solution for this for days too! :)

    We've implemented an AD membership provider succcessfully.. the difference is we haven't "made" umbraco members.. is that a gotcha relevant to the win login part?

    just wondering why you couldn't get the SSO working with umbraco without the redirect out of interest?

    Cheers,

    Tom

  • Tom 713 posts 954 karma points
    Nov 07, 2011 @ 08:30
    Tom
    0

    I was also wondering with the small web app with SSO what kind of configuration did you need to do for the 

    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal user = UserPrincipal.FindByIdentity(context,User.Identity.Name))
                        {

     

    im having issues with our implementation where it doesn't seemlessly log the user in using windows auth.. it displays the standard popup.. 

     

     

    public partial class _default : System.Web.UI.Page

    {

    protected void Page_Load(object sender, EventArgs e)

    {

    //WindowsIdentity ident = WindowsIdentity.GetCurrent();

    //WindowsPrincipal wind_princ = new WindowsPrincipal(ident);

     

    //PrincipalContext context = new PrincipalContext(ContextType.Domain);

    //UserPrincipal user = UserPrincipal.FindByIdentity(context, User.Identity.Name);

     

     

    var ticket = new FormsAuthenticationTicket(1, Request.ServerVariables["LOGON_USER"], DateTime.Now, DateTime.Now.AddSeconds(10), false, "ROLES", "/");

    var encTicket = FormsAuthentication.Encrypt(ticket);

    Response.Redirect("http://test/WindowsLoginRedirector.aspx?ticket=" + encTicket);

    }

    }

  • James Woodmancy 6 posts 26 karma points
    Nov 07, 2011 @ 10:40
    James Woodmancy
    0

    Hi Tom,

    We couldn't get the SSO to work without the redirect because the web server which runs umbraco is running on a completely different domain to AD.  Therefore I couldn't get the umbraco webserver to run under windows authentication - because when I did I would always be prompted for the windows username and password - as the username i was connecting as wouldn't exist on the domain. 

    The reason why I had to use the umbraco members was because I wanted to run forms authentication aswell - if you've implemented the  AD membership provider then maybe you don't need this part actually...

    One note on why the windows authentication always prompts for the username and password in the standard prompt - maybe its a browser security setting

     

    In firefox:

     

    Type in about:config in the address bar

    In the filter bar type in network.automatic-ntlm-auth.trusted-uris

    Double click on it and enter the url name of the page

     

    In IE:

     

    Tools/Internet Options

    Security Tab

    Select Local intranet

    Click Sites

    Click Advanced button

    Add the url name of the page

     

    Hope that helps

    cheers

    james

  • Tom 713 posts 954 karma points
    Nov 07, 2011 @ 23:07
    Tom
    0

    Hi James,

    thanks so much for your reply! most appreciated!

    with this chunk of code:

    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal user = UserPrincipal.FindByIdentity(context,User.Identity.Name))
                        {
                            if (user != null)
                            {
                                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,user.SamAccountName,DateTime.Now,DateTime.Now.AddSeconds(10),false, user.DistinguishedName, "/");
                                encTicket = FormsAuthentication.Encrypt(ticket);
                            }
                        }
                    }

     

    did you need to authenticate the app on the domain using an ldap login? I can't seem to run this locally even though we're on a windows domain..

     

    I ended up doing something similar using windows auth but getting the name of the windows user to pass through correctly hasn't worked out as well as I'd like..

    using windows auth without anonymous login enabled under iis7 i did the following:

    var ticket = new FormsAuthenticationTicket(1, Request.ServerVariables["LOGON_USER"], DateTime.Now, DateTime.Now.AddSeconds(10), false, "ROLES", "/");

    var encTicket = FormsAuthentication.Encrypt(ticket);

    Response.Redirect("http://testdomain.test/WindowsLoginRedirector.aspx?ticket=" + encTicket);

     

    and then in my umbraco app I created a page called WindowsLoginRedirector.aspx which has javascript redirect to '/' but in the codebehind I have. I found I had to have the javascript redirect or the cookie wasn't being written to the browser:

     

    public partial class WindowsLoginRedirector : System.Web.UI.Page

    {

    protected override void OnInit(EventArgs e)

    {

    base.OnInit(e);

     

    string ticket = Context.Request.QueryString["ticket"];

    string name = FormsAuthentication.Decrypt(ticket).Name;

    int domainPathSeparatorIndex = name.LastIndexOf('\\');

    if (domainPathSeparatorIndex != -1)

    {

    name = name.Substring(domainPathSeparatorIndex + 1);

    }

     

    var member = Membership.GetUser(name);

    if (member != null)

    {

    string roles = string.Join(";", Roles.GetRolesForUser(name));

    var cookie = Response.Cookies[FormsAuthentication.FormsCookieName];

    //var newTicket = FormsAuthentication.Decrypt(cookie.Value);

    var newTicket = new FormsAuthenticationTicket(name, false, (int)FormsAuthentication.Timeout.TotalMinutes);

    newTicket = new FormsAuthenticationTicket(newTicket.Version, newTicket.Name, newTicket.IssueDate, newTicket.Expiration, newTicket.IsPersistent, roles, newTicket.CookiePath);

    cookie.Value = FormsAuthentication.Encrypt(newTicket);

    }

     

    }

    }

     

     

     

     

    I was just wondering

    Authenticated = ValidateActiveDirectoryLoginByDn(dn);

                        if (Authenticated)
                        {
                            ValidateMembership(ticket.Name);

                            Member m = Member.GetMemberFromLoginName(ticket.Name);
                            if (m != null)
                            {
                                Member.AddMemberToCache(m);
                            }

                        }

     

    could you post the method in bold above? I was just wondering what that did?

    Cheers,

    Tom

  • James Woodmancy 6 posts 26 karma points
    Nov 21, 2011 @ 15:00
    James Woodmancy
    0

    Hi,

     

    I think you may have to give read access permissions to a group that all LDAP users are a member of e.g Users...

     

    Cheers

    James

Please Sign in or register to post replies

Write your reply to:

Draft