When working with web services and ADO.NET services (O-data) you will sometimes have requirement to invoke ADO.NET Data Service from one service.
For example, imagine there is a Silverlight application which invokes some operation DoSomething on Service1. Now imagine the Silverlight application has line of code which invokes the ADO.NET Data Service:
JdMasterEntities ctx = new JdMasterEntities(this.m_JdMasterUri);
var query = from user in ctx.Entity select user;
IEnumerable<Entity> list = dataQuery.Execute();
return ctx;
If your service operation DoSomething uses impersonation (Link I, Link II) all will work fine, because the browser network stack in Silverlight does this for you.
This is example of using of impersonation:
// Here you need to impersonate imperatively later in code.
[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
public QueryTransportResponse DoSomething(QueryTransportRequest query)
or
// WCF impersonates for you declaratively.
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public QueryTransportResponse DoSomething(QueryTransportRequest query) The browser do it for you means the browser prepares the token of interactive user for impersonation before request is sent to service. If you didn;t understand what this means take a look on next example. Imagine you write the application which needs to invoke DoSomething. Because you know that DoSomething will perform impersonation you have to send the toke which can be impersonated.
To make this working do following:
MyProxyClient proxy = new MyProxyClient()
// If the service needs to access resources at its local machine. For example to invoke the ADO.NET data service
// which is hosted at the same machine as Service1 (implements operation DoSomething).
proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
or
// If the service needs to access resources at some other machine. For example if the ADO.NET data service is hosted at other machine
// than Service1.
proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
proxy.DoSomething();
If you want to invoke the ADO.NET data service from some service operation you will do it as follows:
JdMasterEntities ctx = new JdMasterEntities(this.m_JdMasterUri);
var query = from user in ctx.Entity select user;
DataServiceQuery<Entity> dataQuery = (DataServiceQuery<Entity>)query;
IEnumerable<Entity> list = dataQuery.Execute();
return ctx;
But if the ADO.NET data service requires windows authentication you need to append credentials to web request.
ctx.Credentials = System.Net.CredentialCache.DefaultCredentials;
The question is now what credentials will be used when you setup DefaultCredentials? The typical architect answer is “It depends” :)
The value of default is following call:
System.Security.Principal.WindowsIdentity.GetCurrent()
Whatever this is it will be passed as credentials to the next hop (in this case ADO.NET data service). By default (if no impersonation is used) this is the pool identity like "IIS APPPOOL\\DefaultAppPool".
If the operation DoSomething allows impersonation, but not requires (see example above) you need to do imperative impersonation:
if (Thread.CurrentPrincipal.Identity is WindowsIdentity)
{
using (((WindowsIdentity)Thread.CurrentPrincipal.Identity).Impersonate())
{
. . . call to ado.net data service . . .
// System.Security.Principal.WindowsIdentity.GetCurrent()
// gives: DOMAIN\user_who_open_the_browser_which_invoked_DoSomething_within_Silverlight_application.
}
}
If the ADO.NET data service is permitted for anonymous users of for the application pool user, you do not have to do anything.
If the ADO.NET data service is permitted for specific windows users who started the Silverlight application you need to impersonate.
this is why the answer was “It depends”.
Posted
Dec 23 2009, 01:00 AM
by
Damir Dobric