使用ADAL通过Angular 2向Dynamics CRM Web API发出未经授权的HTTP请求

使用ADAL通过Angular 2向Dynamics CRM Web API发出未经授权的HTTP请求,angular,azure,dynamics-crm,azure-active-directory,adal,Angular,Azure,Dynamics Crm,Azure Active Directory,Adal,我正在尝试使用Angular创建一个应用程序,它可以通过Web API连接到Dynamics CRM。以下是我遵循的步骤: 1。在Azure中注册了本机应用程序,授予了所需的委派权限,并更新了清单以允许隐式流 2。在CRM中创建了一个应用程序用户,将其应用程序ID设置为my Azure注册应用程序的客户端ID。为我的应用程序用户分配了自定义安全角色 3.克隆了许多Angular 2 quickstart Git存储库,这些存储库通过ADAL(例如)与Azure AD进行身份验证 4.更新了克隆代

我正在尝试使用Angular创建一个应用程序,它可以通过Web API连接到Dynamics CRM。以下是我遵循的步骤:

1。在Azure中注册了本机应用程序,授予了所需的委派权限,并更新了清单以允许隐式流

2。在CRM中创建了一个应用程序用户,将其应用程序ID设置为my Azure注册应用程序的客户端ID。为我的应用程序用户分配了自定义安全角色

3.克隆了许多Angular 2 quickstart Git存储库,这些存储库通过ADAL(例如)与Azure AD进行身份验证

4.更新了克隆代码的adal配置,设置了my
租户
客户端ID
重定向URI
端点

到目前为止,这是成功的。我可以启动应用程序并通过浏览器以我的应用程序用户或其他CRM用户(Azure AD的一部分)的身份登录。这将返回一个令牌

5.尝试向
v8.0
v8.2
发送
http.get
(我听说
v8.2
不支持跨域调用):

getEntities():承诺

内容如下:

No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access. 
The response had HTTP status code 401.
查看我的Chrome浏览器的“网络”选项卡,我收到两个响应:

答复1 概述

Request URL:https://ms-dyn365-prevxxxxxx/api/data/v8.2/accounts
Request Method:OPTIONS
Status Code:200 OK
Remote Address:104.44.xxx.xxx:xxx
Referrer Policy:no-referrer-when-downgrade
Request URL:https://ms-dyn365-prevxxxxx.crm4.dynamics.com/api/data/v8.2/accounts
Request Method:GET
Status Code:401 Unauthorized
Remote Address:104.xx.xxx.xxx:xxx
Referrer Policy:no-referrer-when-downgrade
标题

Access-Control-Allow-Headers:authentication,content-type,odata-maxversion,odata-version
Access-Control-Allow-Methods:GET
Access-Control-Allow-Origin:http://localhost:3000
Access-Control-Expose-Headers:Preference-Applied,OData-EntityId,Location,ETag,OData-Version,Content-Encoding,Transfer-Encoding,Content-Length,Retry-After
Access-Control-Max-Age:3600
Content-Length:0
Date:Thu, 13 Apr 2017 10:08:01 GMT
Server:Microsoft-IIS/8.5
Set-Cookie:crmf5cookie=!NDyiupL55lrWWLtPQKTK52dwbxk9wdEAHeCiec0/z/7x9KWXe2dVIdQCGvL0S/HAp7F3N0OGfeWf/70=;secure; path=/
Strict-Transport-Security:max-age=31536000; includeSubDomains
Vary:Origin
X-Powered-By:ASP.NET
Cache-Control:private
Content-Length:49
Content-Type:text/html
Date:Thu, 13 Apr 2017 10:08:01 GMT
REQ_ID:b2be65bc-xxxx-4b34-xxxx-5c39812650xx
Server:Microsoft-IIS/8.5
Set-Cookie:ReqClientId=xxxxxxxx-70b5-45f9-9b84-30f59481bxxx; expires=Wed, 13-Apr-2067 10:08:01 GMT; path=/; secure; HttpOnly
Strict-Transport-Security:max-age=31536000; includeSubDomains
WWW-Authenticate:Bearer authorization_uri=https://login.windows.net/xxxxxxxx-87e4-4d81-8010-xxxxxxxxxxxxx/oauth2/authorize, resource_id=https://ms-dyn365-prevxxxxxx.crm4.dynamics.com/
X-Powered-By:ASP.NET
答复2 概述

Request URL:https://ms-dyn365-prevxxxxxx/api/data/v8.2/accounts
Request Method:OPTIONS
Status Code:200 OK
Remote Address:104.44.xxx.xxx:xxx
Referrer Policy:no-referrer-when-downgrade
Request URL:https://ms-dyn365-prevxxxxx.crm4.dynamics.com/api/data/v8.2/accounts
Request Method:GET
Status Code:401 Unauthorized
Remote Address:104.xx.xxx.xxx:xxx
Referrer Policy:no-referrer-when-downgrade
标题

Access-Control-Allow-Headers:authentication,content-type,odata-maxversion,odata-version
Access-Control-Allow-Methods:GET
Access-Control-Allow-Origin:http://localhost:3000
Access-Control-Expose-Headers:Preference-Applied,OData-EntityId,Location,ETag,OData-Version,Content-Encoding,Transfer-Encoding,Content-Length,Retry-After
Access-Control-Max-Age:3600
Content-Length:0
Date:Thu, 13 Apr 2017 10:08:01 GMT
Server:Microsoft-IIS/8.5
Set-Cookie:crmf5cookie=!NDyiupL55lrWWLtPQKTK52dwbxk9wdEAHeCiec0/z/7x9KWXe2dVIdQCGvL0S/HAp7F3N0OGfeWf/70=;secure; path=/
Strict-Transport-Security:max-age=31536000; includeSubDomains
Vary:Origin
X-Powered-By:ASP.NET
Cache-Control:private
Content-Length:49
Content-Type:text/html
Date:Thu, 13 Apr 2017 10:08:01 GMT
REQ_ID:b2be65bc-xxxx-4b34-xxxx-5c39812650xx
Server:Microsoft-IIS/8.5
Set-Cookie:ReqClientId=xxxxxxxx-70b5-45f9-9b84-30f59481bxxx; expires=Wed, 13-Apr-2067 10:08:01 GMT; path=/; secure; HttpOnly
Strict-Transport-Security:max-age=31536000; includeSubDomains
WWW-Authenticate:Bearer authorization_uri=https://login.windows.net/xxxxxxxx-87e4-4d81-8010-xxxxxxxxxxxxx/oauth2/authorize, resource_id=https://ms-dyn365-prevxxxxxx.crm4.dynamics.com/
X-Powered-By:ASP.NET

注意:我可以通过邮递员成功访问Web API:

1.我输入
https://www.getpostman.com/oauth2/callback
作为Azure中我的应用程序的回调URL

2.打开Postman,按如下设置参数,然后按Request Token:

令牌名称:令牌
验证URL:https://login.windows.net/common/oauth2/authorize?resource=https://ms-dyn365-prevxxxxxx.crm4.dynamics.com
访问令牌URL:https://login.microsoftonline.com/common/oauth2/token
客户ID:xxxxxxxx-ebd3-429c-9a95-XXXXXXXXXX
回调URL:https://www.getpostman.com/oauth2/callback
授权类型:授权代码
3。这将打开一个我登录的网页

4.返回一个令牌,我将其添加到邮递员获取标题中:

Content-Type: application/json
Authorization: Bearer eyJ0eXAiO...
5.派一名接送邮递员:

GEThttps://ms-dyn365-prevxxxxxx.crm4.dynamics.com/api/data/v8.2/accounts
6。帐户已成功返回


如果我在我的应用程序中使用相同的令牌,我仍然会收到401错误。

访问控制允许来源
表明问题是由跨域引起的

通常,我们可以在服务器上使用JSONP或设置
accesscontrolalloworigin
头。如果JSONP和header都无法设置,因为服务是由第三方提供的,我们还可以创建一个服务代理,允许从特定的原始文件调用

关于AJAX跨域问题的更多细节,您可以参考本文

更新 经过进一步调查,该问题属于服务器端问题,与REST请求的特定版本相关

REST的
8.2
版本目前不支持跨域。作为一种解决方法,我们可以使用
8.0
,它对我来说非常有效,如下图所示:

将代码演示附加到测试:


  • 当您在Azure中注册应用程序时,是否将“”设置为“登录URL”?@PawelGradecki我在Azure中实际上看不到“登录URL”的选项(我正在使用较新的Azure门户)。我可以看到“主页”和“重定向URI”,它们都被设置为“localhost:3000”。还有其他的查询在工作吗?例如,您是否尝试获取帐户?因为目前您正在查询元数据,我的猜测是,即使使用CORS,也不可能做到这一点(尽管我没有找到任何信息支持这一假设),而且您应该在get中使用“application/json”而不是“application/jsonp”request@PawelGradecki我尝试了/api/data/v8.2/accounts,但收到了相同的错误
    application/jsonp
    在我的问题中是个错误,我的代码实际上使用了
    json
    ,对不起!我现在编辑了我的问题。谢谢你的回答<代码>访问控制允许源站
应该在服务器上启用(我无法控制),因为它是托管在Azure中的Dynamics 365。我不喜欢使用JSONP,因为我知道可以使用JSON;Microsoft在他们的示例中就是这样做的。@DaveClark根据您提到的文档,它对同源策略使用CORS。并且您的代码中的头被设置为JSONP,请按照您提到的提供的代码示例对其进行修改。@DaveClark该问题与REST的特定版本有关,请查看更新并告知是否有帮助。根据我的理解,该问题是服务器端问题,不应与客户端相关。我正在使用Office 365的CRM进行测试,Angular 1和Angular 2对我来说都很好。对于此问题,您可以检查服务器端是否支持CORS。如果没有,您可以开发一个web API作为代理作为解决办法。@DaveClark我已经链接了测试代码示例供您参考。代码示例仅用于测试CORS问题,当您单击Get消息时,它无法工作,但您可以通过Chrome的newwork选项卡检查成功的请求。