I created domain user 'jsmith' in Active Directory and i've added that domain account as a user in Dynamics CRM. My goal here is to execute code with a service account that is in the PrivUserGroup for the organization while impersonating 'jsmith'. I instantiate the CrmDataContext by passing it an instance of CrmConnection. When calling the constructor of the CrmConnection I pass it the name of my connection string in the application config file then I set the ImpersonatedUser property to the system user id of 'jsmith'. One thing to note is that I'm using a console application to run this. View my code below:
Connection String in app.config:
CrmDataContext and GetEntities code:
var connection = new CrmConnection("Crm");
connection.ImpersonatedUser = Guid.Parse("1937F45C-8EB4-E011-8FE4-005056887B79");
var crm = new CrmDataContext(connection);
var contacts = crm.GetEntities("contacts")
if(contacts.Count() > 0) //the call to Count() is where the error gets thrown. Invalid user auth.
//do something
I have no issues when trying to impersonate with my own system user id which is tied to my AD domain account that I'm logged in as while running the tests. I get results back just fine so I know there is no issue with the service account that is being used to execute the code. I've even assigned 'jsmith' to the same business unit and put him in the same roles that I'm in (which is System Administrator) and I still get the Invalid user auth. What could I possibly be missing. Below is error information in the trace file on the server. In the trace information below the one thing that does stick out is the first line: "[2011-07-22 18:14:08.0] Process: w3wp |Organization:f827deb3-c6cc-df11-bc07-005056887b79 |Thread: 6 |Category: Exception |User: 822138f1-c574-e011-9dca-005056887b79 |Level: Error | CrmException..ctor*". The User id that is being display is my system user id. It seems like it would show the id of the service account from the connection string or the id 'jblow' who is being impersonated. Any ideas would be greatly appreciated.
[2011-07-22 18:14:08.0] Process: w3wp |Organization:f827deb3-c6cc-df11-bc07-005056887b79 |Thread: 6 |Category: Exception |User: 822138f1-c574-e011-9dca-005056887b79 |Level: Error | CrmException..ctor
at CrmException..ctor(Int32 errorCode, Object[] arguments)
at SecurityHelper.VerifyAndReturnCurrentCallerId(Guid userId, Guid callerId, Guid orgId)
at CrmWebService.get_CurrentCallerId()
at CrmService.Execute(Request request)
at RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at LogicalMethodInfo.Invoke(Object target, Object[] values)
at WebServiceHandler.Invoke()
at WebServiceHandler.CoreProcessRequest()
at SyncSessionlessHandler.ProcessRequest(HttpContext context)
at CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
at ApplicationStepManager.ResumeSteps(Exception error)
at HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
at HttpRuntime.ProcessRequestNoDemand(HttpWorkerRequest wr)
at ISAPIRuntime.ProcessRequest(IntPtr ecb, Int32 iWRType)
>Crm Exception: Message: Invalid user auth., ErrorCode: -2147220988
[2011-07-22 18:14:08.0] Process: w3wp |Organization:f827deb3-c6cc-df11-bc07-005056887b79 |Thread: 6 |Category: Platform.Sdk |User: 822138f1-c574-e011-9dca-005056887b79 |Level: Error | CompositeSoapExtensionExceptionHandler.Handle
at CompositeSoapExtensionExceptionHandler.Handle(Stream to, Stream from, Exception exception)
at CrmAuthenticationSoapExtensionBase.ProcessMessage(SoapMessage message)
at SoapMessage.RunExtensions(SoapExtension[] extensions, Boolean throwOnException)
at SoapServerProtocol.WriteException(Exception e, Stream outputStream)
at WebServiceHandler.WriteException(Exception e)
at WebServiceHandler.Invoke()
at WebServiceHandler.CoreProcessRequest()
at SyncSessionlessHandler.ProcessRequest(HttpContext context)
at CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
at ApplicationStepManager.ResumeSteps(Exception error)
at HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
at HttpRuntime.ProcessRequestNoDemand(HttpWorkerRequest wr)
at ISAPIRuntime.ProcessRequest(IntPtr ecb, Int32 iWRType)
>CrmSoapExtension detected CrmException:
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> Microsoft.Crm.CrmException: Invalid user auth.
at Microsoft.Crm.Sdk.SecurityHelper.VerifyAndReturnCurrentCallerId(Guid userId, Guid callerId, Guid orgId)
at Microsoft.Crm.WebServices.Crm2007.CrmWebService.get_CurrentCallerId()
at Microsoft.Crm.Sdk.Crm2007.CrmService.Execute(Request request)
--- End of inner exception stack trace ---
UPDATE 7/25:
I decided to perform a test by making a call like I've been doing using the CrmDataContext where the CrmConnection.ImpersonatedUser is set to the jsmith id. Then I made another call (exact same query) using the old school approach where you build the QueryExpression and pass it into the CrmService where the CallerId property of the CrmAuthenticationToken is set to the id for jsmith. The using CrmDataContext failed with the "Invalid user auth" error but the other call using the CrmService and QueryExpression ran fine. I used fiddler to look at the raw http request for each of those calls. The raw request was the exact same for both calls except for one thing.... The Negotiate token in the Authorization header of the request. I made both calls, one right after the other, in my console app and they produce different Negotiate tokens. That's got to be the problem although I don't know how to fix. Seems like this is a bug in the Advanced Developer Extensions. Below are the raw http for both.
--using CrmDataContext
POST http://myserver/MSCRMServices/2007/CrmService.asmx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0.30319.235)
VsDebuggerCausalityData: uIDPo6mcKDyuc+pPqk3LRv81TrIAAAAA/j8K/SLE5EivZ+mzg1+doYkmNLjkHbFHmbD9UyYmHFEACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://schemas.microsoft.com/crm/2007/WebServices/Execute"
Accept-Encoding: gzip,gzip
Authorization: Negotiate YIIIrgYGKwYBBQUCoIIIojCCCJ6g.....
Host: myserver
Content-Length: 1281
Expect: 100-continue
0
myorg
1937f45c-8eb4-e011-8fe4-005056887b79
contact
false
1
100
And
--call using CrmService with QueryExpression
POST http://myserver/MSCrmServices/2007/CrmService.asmx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0.30319.235)
VsDebuggerCausalityData: uIDPo8cVsRu/YZBCl+8cnC9j5fwAAAAAGni8rU7A/Uy4JYm/bi/S6d/soXPiw+xBoKSYCD/1KRIACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://schemas.microsoft.com/crm/2007/WebServices/Execute"
Authorization: Negotiate YIIG5wYGKwYBBQUCoIIG2zCCBtegMDAuBgkqhk.....
Host: myserver
Content-Length: 1219
Expect: 100-continue
0
myorg
1937f45c-8eb4-e011-8fe4-005056887b79
contact
false
1
100
And
解决方案
I never figured out the problem. But, my work-around is to just build a connection string at runtime that contains the username and password of the person i would want to impersonate via the CallerId property. So I want really be impersonated and I guess for my situation it really does not matter.