如何使用ADAL / OAuth通过CRM Online进行身份验证并通过令牌请求数据?

时间:2016-07-26 16:18:33

标签: c# oauth azure-active-directory dynamics-crm-online

我有多个CRM Online实例,由Microsoft托管在云端 它们都使用相同的Azure Active Directory进行保护,该Active Directory本身由ADFS管理 我的应用程序在Azure AD中注册,因此具有客户端ID /密钥等以及CRM的权限。

我想通过Web API连接到特定的CRM实例来请求数据 我可以通过使用包含用户名/密码的连接字符串CrmServiceClient来实现此功能 这似乎是常见的示例,但我不想这样做。以下MSDN文章使我看起来可以通过令牌代替:https://msdn.microsoft.com/en-us/library/gg327838.aspx

我可以成功获得这样的令牌(我已经隐藏了一些安全细节):

var tenantName = @"myorg.onmicrosoft.com";
var authString = string.Format(@"https://login.microsoftonline.com/{0}", tenantName);

var authContext = new AuthenticationContext(authString, false);

// I am in the UK so use crm4
var resource = @"https://myorg.crm4.dynamics.com";
var clientId = @"899ac540-2134-1234-abcd-2d6440046630";
var key = @"nStbgtfe0oybU1P5+/FQ4wFn1oLTEDr5M7Kjrghf5yh=";
var clientCred = new ClientCredential(clientId, key);

var authResult = await authContext.AcquireTokenAsync(resource, clientCred);

通常我会将此令牌作为身份验证标头传递给HttpRequest,但此博客上的选项3表明可以使用SDK提供的OrganizationWebProxyClient类:http://crmtipoftheday.com/2015/06/24/you-have-oauth-token-now-what/

var orgService = new OrganizationWebProxyClient(
    new Uri("https://myorg.api.crm4.dynamics.com/XRMServices/2011/Organization.svc"), false)
{
    HeaderToken = authResult.AccessToken,
    SdkClientVersion = "8"
};

最后,我需要为Microsoft提供的组织服务添加服务引用:

https://myorg.api.crm4.dynamics.com/XRMServices/2011/Organization.svc?singleWSDL&sdkversion=8

这会在我的app.config中创建一个绑定:

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="CustomBinding_IOrganizationService">
        <textMessageEncoding />
        <httpsTransport />
      </binding>
    </customBinding>
  </bindings>
  <client>
    <endpoint address="https://myorg.api.crm4.dynamics.com/XRMServices/2011/Organization.svc"
    binding="customBinding" bindingConfiguration="CustomBinding_IOrganizationService"
    contract="CRMOrgService.IOrganizationService" name="CustomBinding_IOrganizationService" />
  </client>
 </system.serviceModel>

然后我可以将其分配给组织服务:

var binding = new CustomBinding("CustomBinding_IOrganizationService");
orgService.Endpoint.Binding = binding;

最后我可以拨打网络服务:

var contacts = orgService.RetrieveMultiple(new QueryExpression
{
    EntityName = "contact",
    ColumnSet = new ColumnSet("firstname", "lastname")
})
.Entities
.Select(item => item.ToEntity<Contact>());

但是,在调用组织服务时,我收到错误:

  

验证邮件的安全性时发生错误

我被引导相信这个错误实际上吞没了真正的错误(感谢微软)所以我不知道什么是真正的错误。
网上有很多文档说它的客户端和服务器时间不同步,但我认为不是这样。我不能证明微软的服务器什么时候开机,但我的时钟绝对准确,并且在适合英国的时区。

有谁知道我做错了什么? 或者,如果没有用户名/密码,有不同的方式进行身份验证吗? 或者我只是咆哮错误的树,我应该使用用户名/密码吗?

1 个答案:

答案 0 :(得分:2)

似乎CRM Online不支持任何类型的匿名或被动身份验证,并且必须始终提供有效的用户名和密码。

我只是简单地创建了一个仅用于API访问的用户,并使用这些凭据对CRM进行身份验证。虽然这不是我想要的,但它确实可以正常工作。

我喜欢某人证明我错了,但现在看来这是不可能的。