Thread.CurrentPrincipal problem when client calls an IIS process hosting a remoting service

A

Anthony Paul

Hello everyone!

I have the following problem :

I have a remoting service hosted through IIS called "MyService".
MyService has the standard login method (username, password) that
encapsulates an authentication mechanism that results in the
Thread.CurrentPrincipal being set to a newly created principal.

I also have a winforms client that accesses MyService through a proxy.
I have a test button set up where it creates a MyService proxy, calls
the login method, calls a test method that returns some info, and
posts that info for my viewing pleasure. My windows account is MyDomain
\Me and I am currently logged in using this account, but I want to log
in to MyService via my winforms client app as a different account
called SuperFreak so I have my test button call the Login method
passing in SuperFreak as a username. I click my test button, the info
pops up as expected, and I'm a happy camper.

I now create an asp.net web client that has the exact same interface,
test button and all. I click my test button, log in goes through fine,
but no results. I proceed to attach my VS debugger to the aspnet
process to debug MyService. Upon inspection I realize that I'm not
getting anything back because it seems I don't have permissions even
though I'm using the same username and password. Upon further
inspection I realize that although Thread.CurrentPrincipal is being
set correctly during login (it gets set to SuperFreak as it should),
any subsequent calls made through the proxy uses my windows
authentication principal instead (MyDomain\Me). This doesn't happen
when I make the calls through my winforms client; once the login sets
the Thread.CurrentPrincipal to SuperFreak, it remains that way through
subsequent calls.

This seems to be a context problem and I'm currently trying to wrap my
head around it, but in the meantime I thought I'd stop by and see if
anyone would give me some pointers.

Regards!

Anthony
 
D

Dominick Baier

Thread.CurrentPrincipal is tied to a thread. Each request in asp.net gets
executed on a different thread and T.CP is regenerated every time - you have
to set T.CP on every request manually again - thats because of the stateless
nature of a web application.

You can automate that by handling the AuthenticateRequest event in the ASP.NET
application (e.g. in global.asax).
 
A

Anthony Paul

Hello Dominick!

Thanks for replying. I understand the nature of threads, but if my
asp.net method block as follows :

public void TestButton_Click(...)
{
MyServiceProxy proxy = new MyServiceProxy();
Proxy.Login("SuperFreak", "password");
string info = Proxy.GetInfo();
MyLabel.Text = info;
}

then I would expect the block of code to be executed within the same
thread, no? But what's happening is that on the service side, Login
changes the Thread.CurrentPrincipal to SuperFreak but on the next call
to GetInfo it's set to "MyDomain\Me" instead.

I have to run to the gym right now so I'll look up AuthenticateRequest
when I get back, but I still don't see why it's running on seperate
threads when the calls are made within the same asp.net request; or
maybe I'm just tired and am failing to see the obvious.

Regards,

Anthony
 
D

Dominick Baier

ah i see - you are talking about T.CP in the remoting server not the asp.net
app ?!

then your remoting server uses a single call pattern....

Which makes it stateless too...

I guess you have to switch remoting to CAO (client activated objects).
 
A

Anthony Paul

Hello Dominick!

That's correct, the Thread.CurrentPrincipal is being modified within
the Login method on the MyService side. Both my winform and asp.net
clients are calling the Login method and immediately after calls other
methods. The Thread.CurrentPrincipal remains the same through
subsequent calls made by my winform client but loses it with my
asp.net client.

So for a recap :

[client] client calls MyService.Login("SuperFreak", "password")
[service] MyService's Login method authenticates and changes the
Thread.CurrentPrincipal (on the MyService side)
[client] client calls MyService.GetInfo()

[service] At this point if I trace through MyService.GetInfo() (again,
all on the MyService side), the Thread.CurrentPrincipal will still be
set correctly to SuperFreak if called by my winform client, but set to
my windows account MyDomain\Me when called by my asp.net client.

What I'm trying to figure out here is why the service-side thread is
losing it's identity when servicing calls from within a single asp.net
request.

Regards,

Anthony
 
D

Dominick Baier

so the problem is that in asp.net you are creating a new client proxy to
the remoting object on every request - that means new proxy - new client
- new thread.currentprincipal - but you want to keep state in the remoting
server. You have to find a way to reuse the proxy.

maybe you should re-think that desígn - keeping state in a stateless client
is hard to get right.

There are several solutions to that:

- don't keep state in the remoting object
- login every time before you use the rem obj
- send the authentication information out of band with every call (using
the call context)


-----
Dominick Baier (http://www.leastprivilege.com)

Developing More Secure Microsoft ASP.NET 2.0 Applications (http://www.microsoft.com/mspress/books/9989.asp)
Hello Dominick!

That's correct, the Thread.CurrentPrincipal is being modified within
the Login method on the MyService side. Both my winform and asp.net
clients are calling the Login method and immediately after calls other
methods. The Thread.CurrentPrincipal remains the same through
subsequent calls made by my winform client but loses it with my
asp.net client.

So for a recap :

[client] client calls MyService.Login("SuperFreak", "password")
[service] MyService's Login method authenticates and changes the
Thread.CurrentPrincipal (on the MyService side)
[client] client calls MyService.GetInfo()
[service] At this point if I trace through MyService.GetInfo() (again,
all on the MyService side), the Thread.CurrentPrincipal will still be
set correctly to SuperFreak if called by my winform client, but set to
my windows account MyDomain\Me when called by my asp.net client.

What I'm trying to figure out here is why the service-side thread is
losing it's identity when servicing calls from within a single asp.net
request.

Regards,

Anthony

ah i see - you are talking about T.CP in the remoting server not the
asp.net app ?!

then your remoting server uses a single call pattern....

Which makes it stateless too...

I guess you have to switch remoting to CAO (client activated
objects).
 
A

Anthony Paul

Hello Dominick,

Okay, I think there's a misunderstanding either on my part or yours,
and I think I've narrowed it down to our concept of a request. I
envision the following happening :

User clicks test button on browser
http request is sent to client asp.net server
client asp.net server passes request to appdomain containing my client
app and starts processing TestButton_Click

// the following code is common/identical to BOTH my asp.net client
AND my winforms client
client app creates proxy to MyService
client app executes the proxy's Login method (synchronously?), which
sends an http request containing (soap?) request/parameters to
MyService's asp.net server
MyService's asp.net server passes the request to appdomain containing
MyService
MyService.Login is executed, setting Thread.CurrentPrincipal to
"SuperFreak"
MyService returns response to client's asp.net server
client asp.net server receives request and proceeds to the next line
of code in the TestButton_Click
// the following shortened for brevity
client app executes the proxy's GetInfo method
MyService.GetInfo is executed, but Thread.CurrentPrincipal is NOT set
to "SuperFreak"
MyService returns empty response to client asp.net server (empty
because no permissions = no result set)
client asp.net server receives request and has nothing to display
client app executes the rest of TestButton_Click code
// end of common code

client asp.net server sends response back to user's browser
user doesn't see the expected info in browser

The exact same common code executes perfectly fine when called via a
winform client; the Login method is called, Thread.CurrentPrincipal is
set to SuperFreak, the GetInfo method is called,
Thread.CurrentPrincipal is *still* set to SuperFreak as it should, and
returns a result set.

As you can see, all of this occurs within the user's click of the
TestButton, which is in and of itself just one http request. The proxy
calls, of course, are multiple requests, but that was always the case
even via my winform client.

I'm trying to find out why this common code works differently when
called from an asp.net client vs a winform client; there should be no
difference from my limited understanding of the overall process.

Regards,

Anthony

so the problem is that in asp.net you are creating a new client proxy to
the remoting object on every request - that means new proxy - new client
- new thread.currentprincipal - but you want to keep state in the remoting
server. You have to find a way to reuse the proxy.

maybe you should re-think that desígn - keeping state in a stateless client
is hard to get right.

There are several solutions to that:

- don't keep state in the remoting object
- login every time before you use the rem obj
- send the authentication information out of band with every call (using
the call context)

-----
Dominick Baier (http://www.leastprivilege.com)

Developing More Secure Microsoft ASP.NET 2.0 Applications (http://www.microsoft.com/mspress/books/9989.asp)


Hello Dominick!
That's correct, the Thread.CurrentPrincipal is being modified within
the Login method on the MyService side. Both my winform and asp.net
clients are calling the Login method and immediately after calls other
methods. The Thread.CurrentPrincipal remains the same through
subsequent calls made by my winform client but loses it with my
asp.net client.
So for a recap :
[client] client calls MyService.Login("SuperFreak", "password")
[service] MyService's Login method authenticates and changes the
Thread.CurrentPrincipal (on the MyService side)
[client] client calls MyService.GetInfo()
[service] At this point if I trace through MyService.GetInfo() (again,
all on the MyService side), the Thread.CurrentPrincipal will still be
set correctly to SuperFreak if called by my winform client, but set to
my windows account MyDomain\Me when called by my asp.net client.
What I'm trying to figure out here is why the service-side thread is
losing it's identity when servicing calls from within a single asp.net
request.

- Show quoted text -
 
D

Dominick Baier

in the remoting server object

call GetHashCode in Login and GetInfo - just to make sure both calls are
processed by the same instance.

-----
Dominick Baier (http://www.leastprivilege.com)

Developing More Secure Microsoft ASP.NET 2.0 Applications (http://www.microsoft.com/mspress/books/9989.asp)
Hello Dominick,

Okay, I think there's a misunderstanding either on my part or yours,
and I think I've narrowed it down to our concept of a request. I
envision the following happening :

User clicks test button on browser
http request is sent to client asp.net server
client asp.net server passes request to appdomain containing my client
app and starts processing TestButton_Click
// the following code is common/identical to BOTH my asp.net client
AND my winforms client
client app creates proxy to MyService
client app executes the proxy's Login method (synchronously?), which
sends an http request containing (soap?) request/parameters to
MyService's asp.net server
MyService's asp.net server passes the request to appdomain containing
MyService
MyService.Login is executed, setting Thread.CurrentPrincipal to
"SuperFreak"
MyService returns response to client's asp.net server
client asp.net server receives request and proceeds to the next line
of code in the TestButton_Click
// the following shortened for brevity
client app executes the proxy's GetInfo method
MyService.GetInfo is executed, but Thread.CurrentPrincipal is NOT set
to "SuperFreak"
MyService returns empty response to client asp.net server (empty
because no permissions = no result set)
client asp.net server receives request and has nothing to display
client app executes the rest of TestButton_Click code
// end of common code
client asp.net server sends response back to user's browser user
doesn't see the expected info in browser

The exact same common code executes perfectly fine when called via a
winform client; the Login method is called, Thread.CurrentPrincipal is
set to SuperFreak, the GetInfo method is called,
Thread.CurrentPrincipal is *still* set to SuperFreak as it should, and
returns a result set.

As you can see, all of this occurs within the user's click of the
TestButton, which is in and of itself just one http request. The proxy
calls, of course, are multiple requests, but that was always the case
even via my winform client.

I'm trying to find out why this common code works differently when
called from an asp.net client vs a winform client; there should be no
difference from my limited understanding of the overall process.

Regards,

Anthony

so the problem is that in asp.net you are creating a new client proxy
to
the remoting object on every request - that means new proxy - new
client
- new thread.currentprincipal - but you want to keep state in the
remoting
server. You have to find a way to reuse the proxy.
maybe you should re-think that desígn - keeping state in a stateless
client is hard to get right.

There are several solutions to that:

- don't keep state in the remoting object
- login every time before you use the rem obj
- send the authentication information out of band with every call
(using
the call context)
-----
Dominick Baier (http://www.leastprivilege.com)
Developing More Secure Microsoft ASP.NET 2.0 Applications
(http://www.microsoft.com/mspress/books/9989.asp)
Hello Dominick!

That's correct, the Thread.CurrentPrincipal is being modified within
the Login method on the MyService side. Both my winform and asp.net
clients are calling the Login method and immediately after calls
other methods. The Thread.CurrentPrincipal remains the same through
subsequent calls made by my winform client but loses it with my
asp.net client.

So for a recap :

[client] client calls MyService.Login("SuperFreak", "password")
[service] MyService's Login method authenticates and changes the
Thread.CurrentPrincipal (on the MyService side)
[client] client calls MyService.GetInfo()
[service] At this point if I trace through MyService.GetInfo()
(again,
all on the MyService side), the Thread.CurrentPrincipal will still
be
set correctly to SuperFreak if called by my winform client, but set
to
my windows account MyDomain\Me when called by my asp.net client.
What I'm trying to figure out here is why the service-side thread is
losing it's identity when servicing calls from within a single
asp.net request.

Regards,

Anthony

On May 18, 2:58 am, Dominick Baier
ah i see - you are talking about T.CP in the remoting server not
the asp.net app ?!

then your remoting server uses a single call pattern....

Which makes it stateless too...

I guess you have to switch remoting to CAO (client activated
objects).

-----
Dominick Baier (http://www.leastprivilege.com)
Developing More Secure Microsoft ASP.NET 2.0 Applications
(http://www.microsoft.com/mspress/books/9989.asp)- Hide quoted text
-
- Show quoted text -
 
A

Anthony Paul

yup yup yup, HashCode is identical. :/

in the remoting server object

call GetHashCode in Login and GetInfo - just to make sure both calls are
processed by the same instance.

-----
Dominick Baier (http://www.leastprivilege.com)

Developing More Secure Microsoft ASP.NET 2.0 Applications (http://www.microsoft.com/mspress/books/9989.asp)


Hello Dominick,
Okay, I think there's a misunderstanding either on my part or yours,
and I think I've narrowed it down to our concept of a request. I
envision the following happening :
User clicks test button on browser
http request is sent to client asp.net server
client asp.net server passes request to appdomain containing my client
app and starts processing TestButton_Click
// the following code is common/identical to BOTH my asp.net client
AND my winforms client
client app creates proxy to MyService
client app executes the proxy's Login method (synchronously?), which
sends an http request containing (soap?) request/parameters to
MyService's asp.net server
MyService's asp.net server passes the request to appdomain containing
MyService
MyService.Login is executed, setting Thread.CurrentPrincipal to
"SuperFreak"
MyService returns response to client's asp.net server
client asp.net server receives request and proceeds to the next line
of code in the TestButton_Click
// the following shortened for brevity
client app executes the proxy's GetInfo method
MyService.GetInfo is executed, but Thread.CurrentPrincipal is NOT set
to "SuperFreak"
MyService returns empty response to client asp.net server (empty
because no permissions = no result set)
client asp.net server receives request and has nothing to display
client app executes the rest of TestButton_Click code
// end of common code
client asp.net server sends response back to user's browser user
doesn't see the expected info in browser
The exact same common code executes perfectly fine when called via a
winform client; the Login method is called, Thread.CurrentPrincipal is
set to SuperFreak, the GetInfo method is called,
Thread.CurrentPrincipal is *still* set to SuperFreak as it should, and
returns a result set.
As you can see, all of this occurs within the user's click of the
TestButton, which is in and of itself just one http request. The proxy
calls, of course, are multiple requests, but that was always the case
even via my winform client.
I'm trying to find out why this common code works differently when
called from an asp.net client vs a winform client; there should be no
difference from my limited understanding of the overall process.
so the problem is that in asp.net you are creating a new client proxy
to
the remoting object on every request - that means new proxy - new
client
- new thread.currentprincipal - but you want to keep state in the
remoting
server. You have to find a way to reuse the proxy.
maybe you should re-think that desígn - keeping state in a stateless
client is hard to get right.
There are several solutions to that:
- don't keep state in the remoting object
- login every time before you use the rem obj
- send the authentication information out of band with every call
(using
the call context)
-----
Dominick Baier (http://www.leastprivilege.com)
Developing More Secure Microsoft ASP.NET 2.0 Applications
(http://www.microsoft.com/mspress/books/9989.asp)
Hello Dominick!
That's correct, the Thread.CurrentPrincipal is being modified within
the Login method on the MyService side. Both my winform and asp.net
clients are calling the Login method and immediately after calls
other methods. The Thread.CurrentPrincipal remains the same through
subsequent calls made by my winform client but loses it with my
asp.net client.
So for a recap :
[client] client calls MyService.Login("SuperFreak", "password")
[service] MyService's Login method authenticates and changes the
Thread.CurrentPrincipal (on the MyService side)
[client] client calls MyService.GetInfo()
[service] At this point if I trace through MyService.GetInfo()
(again,
all on the MyService side), the Thread.CurrentPrincipal will still
be
set correctly to SuperFreak if called by my winform client, but set
to
my windows account MyDomain\Me when called by my asp.net client.
What I'm trying to figure out here is why the service-side thread is
losing it's identity when servicing calls from within a single
asp.net request.
Regards,
Anthony
On May 18, 2:58 am, Dominick Baier
ah i see - you are talking about T.CP in the remoting server not
the asp.net app ?!
then your remoting server uses a single call pattern....
Which makes it stateless too...
I guess you have to switch remoting to CAO (client activated
objects).
-----
Dominick Baier (http://www.leastprivilege.com)
Developing More Secure Microsoft ASP.NET 2.0 Applications
(http://www.microsoft.com/mspress/books/9989.asp)-Hide quoted text
-
- Show quoted text -- Hide quoted text -

- Show quoted text -
 
A

Anthony Paul

Ahhhh....

I see what you're saying now about it being serviced in a different
thread. Let's recap and correct me if I'm wrong...

When my WinForm client calls the remoting service hosted in IIS, the
login method sets the Thread.CurrentPrincipal, which is serialized/
persisted back to the WinForm client (am I right?) Since the WinForm
client is making all of its calls on the same thread, the same
Thread.CurrentPrincipal is being used every time since it's persisted
between the client and the service.

When my asp.net client calls the remoting service hosted in IIS, the
login method sets the Thread.CurrentPrincipal, which is also
serialized/persisted back to the asp.net client (?). But since each
request is serviced by a different thread (due to the nature of http)
it loses the Thread.CurrentPrincipal on all subsequent requests to the
remoting service hosted in IIS.

Presuming all of what I said is correct, what is the proper mechanism
through which I would be able to persist the CurrentPrincipal between
the asp.net client and the remoting service throughout an individual's
session? Keep in mind that the CurrentPrincipal is originally being
set on the iis hosted remoting-service side, *NOT* on the asp.net
client side. I saw an article or two on the web detailing how to go
about this if the asp.net client was the one that needed to set the
CurrentPrincipal, which is not what's happening in my case.

Regards,

Anthony
 

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,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top