ADFS错误 – MSIS9605:客户端不允许访问请求的资源

我有Dynamics CRM 2016的内部部署安装,它具有使用ADFS 4.0(Server 2016)实例configuration的基于声明的身份validation。 通过ADFSlogging到CRM工作正常。 我有一个单独的Node.js应用程序尝试使用Microsoft提供的ADAL库访问CRM Web API来执行身份validation。 我已经使用PowerShell为具有客户端ID和密钥的此Node应用程序创build了一个ADFS客户端。 当节点代码执行以从ADFS获取用于调用CRM Web API的令牌时,出现错误MSIS9605:客户端不允许访问请求的资源 。 很明显,这个调用正在到达ADFS,但我似乎无法find一种方法来configurationADFS,以允许客户访问由ADFS保护的其他资源。

这里是Get-ADFSRelyingPartyTrust的输出:

AllowedAuthenticationClassReferences : {} EncryptionCertificateRevocationCheck : CheckChainExcludeRoot PublishedThroughProxy : False SigningCertificateRevocationCheck : CheckChainExcludeRoot WSFedEndpoint : https://crm.mysite.com/ AdditionalWSFedEndpoint : {} ClaimsProviderName : {} ClaimsAccepted : {, , } EncryptClaims : True Enabled : True EncryptionCertificate : [Subject] CN=*.mysite.com, OU=Domain Control Validated [Issuer] CN=Go Daddy Secure Certificate Authority - G2, OU=http://certs.godaddy.com/repository/, O="GoDaddy.com, Inc.", L=Scottsdale, S=Arizona, C=US [Serial Number] 2DC..............91 [Not Before] 11/23/2016 9:41:00 PM [Not After] 1/19/2018 3:51:41 PM [Thumbprint] 2FC..................AADD Identifier : {https://demo.mysite.com/, https://crm.mysite.com/} NotBeforeSkew : 0 EnableJWT : True AlwaysRequireAuthentication : False Notes : OrganizationInfo : ObjectIdentifier : 8e869c1e-..........8b5a ProxyEndpointMappings : {} ProxyTrustedEndpoints : {} ProtocolProfile : WsFed-SAML RequestSigningCertificate : {} EncryptedNameIdRequired : False SignedSamlRequestsRequired : False SamlEndpoints : {} SamlResponseSignature : AssertionOnly SignatureAlgorithm : http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 TokenLifetime : 0 AllowedClientTypes : Public, Confidential IssueOAuthRefreshTokensTo : AllDevices RefreshTokenProtectionEnabled : True RequestMFAFromClaimsProviders : False ScopeGroupId : Name : crm.mysite.com AutoUpdateEnabled : True MonitoringEnabled : True MetadataUrl : https://crm.mysite.com/federationmetadata/2007-06/federationmetadata.xml ConflictWithPublishedPolicy : False IssuanceAuthorizationRules : IssuanceTransformRules : @RuleTemplate = "PassThroughClaims" @RuleName = "Pass Through UPN" c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"] => issue(claim = c); @RuleTemplate = "PassThroughClaims" @RuleName = "Pass Through Primary SID" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"] => issue(claim = c); @RuleTemplate = "MapClaims" @RuleName = "Transform Windows Account Name to Name" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"] => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType); @RuleTemplate = "PassThroughClaims" @RuleName = "App Claim" c:[Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-clie nt-application"] => issue(claim = c); DelegationAuthorizationRules : LastPublishedPolicyCheckSuccessful : True LastUpdateTime : 1/4/2017 8:24:16 PM LastMonitoredTime : 1/5/2017 8:02:07 PM ImpersonationAuthorizationRules : AdditionalAuthenticationRules : AccessControlPolicyName : Permit everyone AccessControlPolicyParameters : ResultantPolicy : RequireFreshAuthentication:False IssuanceAuthorizationRules: { Permit everyone } 

这里是使用ADAL的Node.js函数( https://github.com/AzureAD/azure-activedirectory-library-for-nodejs )。 我知道它在标题中有Azure,但它正在成功地与ADFS通信,并且在问题日志中有评论,说明我正在做的事情是可能的。

 let ADAuthenticationContext = require('adal-node').AuthenticationContext; const authorityHostUrl = 'https://sso.mysite.com'; const tenant = 'adfs'; let authorityUrl = authorityHostUrl + '/' + tenant; const clientId = 'c43002e2-............67c'; const clientSecret = 'lT..................jjh'; const resource = 'https://crm.mysite.com/'; let crm = module.exports = {}; let context = new ADAuthenticationContext(authorityUrl, false); crm.test = function() { context.acquireTokenWithClientCredentials(resource, clientId, clientSecret, function(err, tokenResponse) { if (err) { console.log('well that didn\'t work: ' + err.stack); } else { console.log(tokenResponse); } }); }; 

另外,从ADFS事件日志:

 Encountered error during OAuth token request. Additional Data Exception details: Microsoft.IdentityServer.Web.Protocols.OAuth.Exceptions.OAuthUnauthorizedClientException: MSIS9321: Received invalid OAuth request. The client 'c43002e2-f1a6-4786-9234-f71e971c167c' is forbidden to access the resource 'https://demo.mysite.com/'. at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthProtocolContext.ValidateScopes(String scopeParameter, String clientId, String relyingPartyId) at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthClientCredentialsContext.ValidateCore() 

任何洞察力将是伟大的,因为我对ADFS很新,而且这个消息似乎表明ADFS中的东西是不正确的。

您需要创build一个规则来根据传入的声明来允许或拒绝用户。

在Windows Server 2016中,您可以使用访问控制策略创build一个允许或拒绝用户根据传入声明的规则。 此外,您可以允许所有用户访问信赖方,使用“ 允许所有人访问控制策略”或“ 允许所有用户”规则模板

您可以参考下面的文章,通过使用AD FSpipe理创build规则。

https://technet.microsoft.com/en-us/windows-server-docs/identity/ad-fs/operations/create-a-rule-to-permit-or-deny-users-based-on-an-传入-权利要求?F = 255&MSPPError = -2147217396

或者,您也可以使用以下命令以及在PowerShell中运行的相关参数。

 Add-ADFSRelyingPartyTrust -Name "Fabrikam" -MetadataURL "https://fabrikam.com/federationmetadata/2007-06/federationmetadata.xml" -IssuanceAuthorizationRules '=> issue(Type ="http://schemas.microsoft.com/authorization/claims/permit", value="true");' 

在Windows Server 2016上,即使访问策略设置为“允许所有人”,您也需要明确授予客户端对资源的权限。

试试这个命令:

 Grant-AdfsApplicationPermission -ClientRoleIdentifier "clientName" -ServerRoleIdentifier "https://service.url"