Urgent - need help with logging anonymous and Active Dir users without login form

P

pv

Hi everyone,

I need help with following scenario, please:

Users are accessing same web server from intranet (users previously
authenticated in Active Dir) and from extranet (common public users). If
user is from intranet, web server should recognize it and application should
create additional options in controls regarding groups the user belongs to.
If user is from extranet it should be logged in as anonymous and a link to
login page should be created. The goal is to have login page only when user
request it.

I have tried to achieve this by using both windows and forms authentication
but I still did not find the way to avoid IIS login form.

Thanks in advance.

PV

P.S. I already posted this to microsoft.public.dotnet.framework.security but
no answers so far
 
B

Brad

I'll layout what we did to resolve nearly identical situation...the only
difference being we're a government agency with several other agencies
networks behind the same firewall. Users on our agency network are
automatically logged in to our intranet in. Users from the other agencies
access our intranet as anonymous...or they can opptionally set up a portal
account on our intranet and log in using that (we can then use that account
to assign additional intranet access for them). To accomplish this we use
forms authentication for everything. We determine if a user is in our
domain and if they are we use that information to automatically create the
forms authenticaitonticket. If the user is not on in our domain they can
still access our intranet as anonymous and have the option to login (using a
web page or web user control) which will then fill in the forms
authentication ticket.

Here are the steps to accomplish this:
***************
Disclaimer: Examples are not the exact code from our system: in our system
it's all classed out and compartmentlized...so I've typed in code which
should aproximate what we do...enough so to give you the concepts. I guess
I could probably write an article on the concept with the exact
code....maybe someday.
***************

(1) Use Forms Authentication for everything.
If you want this authenticaiton to apply to all web apps on your intranet
(single sign-on) you should set the forms authenticaiton and machine key
once in a root web.config file and the leave them out of all web.configs for
apps under the intranet.
<machineKey validationKey="AutoGenerate"
decryptionKey="AutoGenerate" validation="3DES"/>
<authentication mode="Forms">
<forms name=".ASPXAUTH" loginUrl="/login.aspx" protection="All"
timeout="60" slidingExpiration="true" />
</authentication>

Note: the /login.aspx in the forms element above is the login page
used by the users outside your domain.

(2) Create a sub folder on the web which will use NT authentication.
In IIS turn off anonymous access to this folder.

(3) In this subfolder create a asp.net page (if you have a root web project
this page can be part of the root web project...otherwise you will need to
create a new web project in this subfolder)
This asp.net page (lets call it NTLogin.aspx) will have no html content,
just code behind. In the page_load event you will get the windows account
information and write it into the forms authentication ticket, then redirect
the user back to the page the access which initiated the login request.

example:
Private Sub Page_Load(......)
Dim userName As String = WindowsIdentity.GetCurrent.Name
userName = userName.Substring(userName.IndexOf("\") + 1)
Dim accountSystem As New DataAccess.Users
FormsAuthentication.SetAuthCookie(userName, False)

Dim url As String
If (Request.Params("ReturnURL") Is Nothing) = False Then
url = Request.Params("ReturnURL")
Else
url = Request.Url.AbsoluteUri
End If
Response.Redirect(url)
End Sub

(4) For the above NTLogin.aspx page set the web config to use impersonation
and allow all users
example:
<location path="/NTSecurity/NTLogon.aspx">
<system.web>
<identity impersonate="true" />
<authorization>
<allow users ="*" />
</authorization>
</system.web>
</location>

(5) In the global.asax code of your app, were going to add code to
a) Check if client is authenticated. If not then contin ue on with
the steps below.
b) Do a dns lookup on the client computer accessing the app and see
if that dns is in our domain
i.e. if client computer is named Accounting1 and your domain is
Acme100
the computers dns is going to be Accounting1.Acme100.
We'll look to see if Acme100 is part of the computer's dns name.
c) If client is in our domain we redirect them to the above
NTLogin.aspx page
passing the current requested url so we can return to it.
This is using what we did in steps 2 - 4
d) If client is not authenticated let then through, they will be
anonymous

Example of code to do all of this.
Dim isDomainUser as boolean = false
' Check if client computer is on coming from our network
Try
Dim clientIPAddress As System.Net.IPAddress =
System.Net.IPAddress.Parse(request.UserHostAddress)

Dim dnsName As String =
System.Net.Dns.GetHostByAddress(clientIPAddress).HostName
' create a list of domain user could come from.
' if network has only one domain then just do the IndexOf
without a For/Each
Dim mask as String() = {"mydomain1","mydomain2"....}
For Each mask As String In dnsMask
If dnsName.IndexOf(mask) >= 0 Then
isDomainUser = True
End If
Next
Catch ex As Exception
End Try

' Client is coming from our network, redirect them to the
autologin page
If isDomainUser then
Dim url As String = "/NTSecurity/NTLogon.aspx"
If Request.Url.ToString.IndexOf(url) < 0 Then
If Not(IsNothing(Request.Params("ReturnURL"))
Then
url &= "?ReturnURL=" &
Request.Params("ReturnURL")
End If
End If
Response.Redirect(url)
' If you **always** want to force anonymous users to a login
page add an Else statement
' with code to direct them to the login page.
End If


Hope this helps some. I'm sure it's not the only solution but it has worked
well for us for several years now.
 
P

pv

Hi Brad



Thanks for the tip!



I have tried you solution and I could not make it work. But combining my old
solution and yours actually worked. My solution is based on windows
authentication with anonymous user. Only thing I missed was how to be sure
that user is coming from intranet or from extranet. So, the part of your
code regarding dns was missing link ;-)



If you are interested in complete solution (or anyone else) I can post it
here or send you on email. Here is only brief description.



Best regards,

PV



Solution in brief, not completed, optimized and commented yet.

----------------------------------------------



IIS settings:



Anonymous access: turned ON

Account used for anonymous access: DOMAIN\iisauth (new domain
whose only purpose is to access as anonymous)

Password: of course password of the 'iisauth' user

Allow IIS to control password: turned OFF

Integrated Windows authentication: ON





WEB Config:



<configuration>



<appSettings>

<add key="DOMAIN_NAME" value="DOMAIN" />

<add key="ANONYMOUS_IISAuth" value="iisauth"/>

</appSettings>

....

<system.web>

..

<identity impersonate="true" />

<authentication mode="Windows"/>



<authorization>

<deny users ="?" />

<allow users ="*" />

</authorization>

..



Globalasax.cs:



private string DOMAIN_NAME =
System.Configuration.ConfigurationSettings.AppSettings["DOMAIN_NAME"];

private string ANONYMOUS_IISSpirelloAuth =
System.Configuration.ConfigurationSettings.AppSettings["ANONYMOUS_IISAuth"];

private FormsAuthenticationTicket _authTicket;.

..

protected void Application_AuthenticateRequest(Object sender, EventArgs e)

{

SetCurrentAuthUser();

}

..

..



private void SetCurrentAuthUser() // set user from cookie

{

if (!User.Identity.IsAuthenticated)

{

string cookieName =
FormsAuthentication.FormsCookieName;

HttpCookie authCookie =
Context.Request.Cookies[cookieName];



if (authCookie != null)

{

FormsAuthenticationTicket authTicket =
null;



try

{

authTicket =
FormsAuthentication.Decrypt(authCookie.Value);

}

catch (Exception exp)

{

return;

}



if (authTicket == null)

{

return;

}



SetContextUser(authTicket);

}

else

{

if (WindowsIdentity.GetCurrent().Name ==
DOMAIN_NAME + "\\" + ANONYMOUS_IISSpirelloAuth)

{

SetAuthCookie(DOMAIN_NAME +
"\\" + ANONYMOUS_IISSpirelloAuth);

bool isDomainUser = false;

// Check if client computer
is on coming from our network

try

{

System.Net.IPAddress
clientIPAddress = System.Net.IPAddress.Parse(Request.UserHostAddress);



string dnsName =
System.Net.Dns.GetHostByAddress(clientIPAddress).HostName;

// create a list
of domain user could come from.

// if network
has only one domain then just do the IndexOf without a For/Each

string[] mask =
new string[] {"localhost", "DOMAIN", "domain"};



foreach (string
dnsMask in mask)

{

if
(dnsName.IndexOf(dnsMask) >= 0)


isDomainUser = true;

}

}

catch (Exception ex)

{

}

if (!isDomainUser)

SetContextUser(_authTicket);

}

}

}

}







private void SetContextUser(FormsAuthenticationTicket authTicket)

{

GenericIdentity id = new GenericIdentity (authTicket.Name,
"LdapAuthentication");

string[] groups = new String[] {"everyone"};





GenericPrincipal principal = new GenericPrincipal(id, groups);

Context.User = principal;

}







private void SetAuthCookie(string userName) // bind auth cookie

{

FormsAuthenticationTicket authTicket =

new FormsAuthenticationTicket

(

1, // version

userName,

DateTime.Now,

DateTime.Now.AddMinutes(60),

false,

userName // group actually

);



_authTicket = authTicket;



string encryptedTicket = FormsAuthentication.Encrypt
(authTicket);



HttpCookie authCookie =

new HttpCookie

(

FormsAuthentication.FormsCookieName, encryptedTicket

);



Response.Cookies.Add(authCookie);

}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top