ASP.NET Impersonation Problem

R

Ram P. Dash

Now this is a classic. The impersonation fails for CASE I but doesn't fail
for CASE II or III.

Case I:

Client Side Code
-----------------
System.Net.NetworkCredential credential = new
System.Net.NetworkCredential("myUserName", "myPassword", "myDomain");
ServiceA a = new ServiceA();
a.Credentials = credential;
a.SomeMethod();

Server Side Code
------------------
Web.config
-----------
<authentication mode="Windows" />
<identity impersonate="true" />

ServiceA
---------
[WebMethod]
public void SomeMethod() {

// Write to share drive code (the share drive has myUserName in ACL
list, myUserName should be able to write to it)
// But it fails
}

Case II:
Everything being same if I change only the Web.config as follows, it works:

<authentication mode="Windows" />
<identity impersonate="true" userName="myDomain\myUserName"
password="myPassword" />

Case III:

Web.config
------------
<authentication mode="Windows" />
<!-- No impersonation -->

ServiceA
---------
[WebMethod]
public void SomeMethod() {

Impersonate i = new Impersonate();
i.StartImpersonate();
// Write to share drive code (the share drive has myUserName in ACL
list, myUserName should be able to write to it)
// This time it works
i.UndoImpersonate();
}

public class Impersonate {

// Usual code using the following
[DllImport("advapi32.dll")]
public static extern int LogonUserA(...);
}

I've tried the following for CASE I as suggested in
http://support.microsoft.com/default.aspx?scid=KB;en-us;q306158. But nothing
works.

a) Changing the "userName" attribute from "machine" to "system" in
"processModel" node in machine.config
b) Including ASPNET user in following Group Policy:
\Local Computer Policy\Computer Configuration\Windows Settings\Local
Policies\User Rights Assignment\"Act as part of the operating system"

Infrastructure: Windows XP Pro (Service Pack 1); .NET Frmaework 1.0 (No
service pack)

Our corporate policy strongly favors doing things as in CASE I. How can I
make it work?

Thanks,
Ram
 
R

Ram P. Dash

I create an instance of NetworkCredential and feed that to the WebService
proxy class object. The credential do get carried to the WebService. However
the token's ACL is lost somewhere in the middle. In CASE I on server side,
if I do System.Security.Principal.WindowsIdentity id =
System.Security.Principal.WindowsIdentity.GetCurrent(); I can see my
identity.

Ram
 
W

Willy Denoyette [MVP]

Ram P. Dash said:
Now this is a classic. The impersonation fails for CASE I but doesn't fail
for CASE II or III.

Case I:

Client Side Code
-----------------
System.Net.NetworkCredential credential = new
System.Net.NetworkCredential("myUserName", "myPassword", "myDomain");
ServiceA a = new ServiceA();
a.Credentials = credential;
a.SomeMethod();

Server Side Code
------------------
Web.config
-----------
<authentication mode="Windows" />
<identity impersonate="true" />

ServiceA
---------
[WebMethod]
public void SomeMethod() {

// Write to share drive code (the share drive has myUserName in ACL
list, myUserName should be able to write to it)
// But it fails
}

Case II:
Everything being same if I change only the Web.config as follows, it
works:

<authentication mode="Windows" />
<identity impersonate="true" userName="myDomain\myUserName"
password="myPassword" />

Case III:

Web.config
------------
<authentication mode="Windows" />
<!-- No impersonation -->

ServiceA
---------
[WebMethod]
public void SomeMethod() {

Impersonate i = new Impersonate();
i.StartImpersonate();
// Write to share drive code (the share drive has myUserName in ACL
list, myUserName should be able to write to it)
// This time it works
i.UndoImpersonate();
}

public class Impersonate {

// Usual code using the following
[DllImport("advapi32.dll")]
public static extern int LogonUserA(...);
}

I've tried the following for CASE I as suggested in
http://support.microsoft.com/default.aspx?scid=KB;en-us;q306158. But
nothing
works.

a) Changing the "userName" attribute from "machine" to "system" in
"processModel" node in machine.config
b) Including ASPNET user in following Group Policy:
\Local Computer Policy\Computer Configuration\Windows Settings\Local
Policies\User Rights Assignment\"Act as part of the operating system"

Infrastructure: Windows XP Pro (Service Pack 1); .NET Frmaework 1.0 (No
service pack)

Our corporate policy strongly favors doing things as in CASE I. How can I
make it work?

Thanks,
Ram

I told you, that this can only work in a Kerberos Realm (W2K AD domain), and
this only when Delegation is enabled at the server and all clients are
delegatable. This is not something I would ever recommend.
A better solution is to authenticate the client , and access the remote
share using fixed credentials, access control can be implemented using
roles.

Willy.
 
B

Bruce Barker

its all to due with creditial forwarding (1 hop rule). to access the
network, you creditial need to be a primary token with network access.

case I: will fail becuase the server does not have a primary token only one
passed from the client, unless the browser in on the server - localhost. (as
many develop apps on their local box and use localhost, the problem is not
seen until prod. you can dup on your own box, by hitting from another box.)

case II: works because the server has a primary token created by asp.net

case III: works becuase the thread creates a primary token

as pointed at, you can use kerberos, and enable creditial forwarding.

-- bruce (sqlwork.com)
 
R

Ram P. Dash

Thanks a lot Bruce,

As rightly pointed out by you, it's a double hop issue which can be resolved
via kerberos delegation. However, our corporate security group will never
allow it.

I know this question is stupid but is there any way that on the server side
I can create a primary token based on the credentials supplied from client?

Ram

Bruce Barker said:
its all to due with creditial forwarding (1 hop rule). to access the
network, you creditial need to be a primary token with network access.

case I: will fail becuase the server does not have a primary token only one
passed from the client, unless the browser in on the server - localhost. (as
many develop apps on their local box and use localhost, the problem is not
seen until prod. you can dup on your own box, by hitting from another box.)

case II: works because the server has a primary token created by asp.net

case III: works becuase the thread creates a primary token

as pointed at, you can use kerberos, and enable creditial forwarding.

-- bruce (sqlwork.com)



Ram P. Dash said:
Now this is a classic. The impersonation fails for CASE I but doesn't fail
for CASE II or III.

Case I:

Client Side Code
-----------------
System.Net.NetworkCredential credential = new
System.Net.NetworkCredential("myUserName", "myPassword", "myDomain");
ServiceA a = new ServiceA();
a.Credentials = credential;
a.SomeMethod();

Server Side Code
------------------
Web.config
-----------
<authentication mode="Windows" />
<identity impersonate="true" />

ServiceA
---------
[WebMethod]
public void SomeMethod() {

// Write to share drive code (the share drive has myUserName in ACL
list, myUserName should be able to write to it)
// But it fails
}

Case II:
Everything being same if I change only the Web.config as follows, it
works:

<authentication mode="Windows" />
<identity impersonate="true" userName="myDomain\myUserName"
password="myPassword" />

Case III:

Web.config
------------
<authentication mode="Windows" />
<!-- No impersonation -->

ServiceA
---------
[WebMethod]
public void SomeMethod() {

Impersonate i = new Impersonate();
i.StartImpersonate();
// Write to share drive code (the share drive has myUserName in ACL
list, myUserName should be able to write to it)
// This time it works
i.UndoImpersonate();
}

public class Impersonate {

// Usual code using the following
[DllImport("advapi32.dll")]
public static extern int LogonUserA(...);
}

I've tried the following for CASE I as suggested in
http://support.microsoft.com/default.aspx?scid=KB;en-us;q306158. But
nothing
works.

a) Changing the "userName" attribute from "machine" to "system" in
"processModel" node in machine.config
b) Including ASPNET user in following Group Policy:
\Local Computer Policy\Computer Configuration\Windows Settings\Local
Policies\User Rights Assignment\"Act as part of the operating system"

Infrastructure: Windows XP Pro (Service Pack 1); .NET Frmaework 1.0 (No
service pack)

Our corporate policy strongly favors doing things as in CASE I. How can I
make it work?

Thanks,
Ram
 
W

Willy Denoyette [MVP]

Ram P. Dash said:
Thanks a lot Bruce,

As rightly pointed out by you, it's a double hop issue which can be
resolved
via kerberos delegation. However, our corporate security group will never
allow it.

I know this question is stupid but is there any way that on the server
side
I can create a primary token based on the credentials supplied from
client?

Ram

If You mean passing the credentials from the client to the server, yes there
is call "LogonUser"at the server using the credentials supplied. But again
this is a real bad idea, calling LogonUser for each service request can kill
the performance of the server application when handling multiple
simultaneous requests, and I wonder if the security group will allow this.
Do as I said, authenticate as close to the client as possible, once
authenticated use roles for authorization handling.

Willy.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top