IdentityServer 2 中的 WS-Trust MEX 端点 returns GET 请求的 HTTP 400

WS-Trust MEX endpoint in IdentityServer 2 returns HTTP 400 for GET requests

我们自定义了 IdentityServer 2 以在 Azure AD(用于 Office 365 等)中提供身份联合功能。它有一个用于被动请求者流的 WS-Federation 端点和一个用于主动客户端的 WS-Trust。 WS-Trust 的 MEX 端点应该 return WS-Trust SOAP 的 WSDL 以响应 POST(如 Lync 使用)和 GET(如 Windows 10 登录使用) .不幸的是,它正在 returning HTTP 400:ws-trust system.servicemodel.protocolexception "There is a problem with the XML that was received from the network"。

从源码中可以看出: https://github.com/IdentityServer/IdentityServer2/blob/master/src/Libraries/Thinktecture.IdentityServer.Protocols/WSTrust/TokenServiceHostFactory.cs

var host = new WSTrustServiceHost(config, baseAddresses);

// add behavior for load balancing support
host.Description.Behaviors.Add(new UseRequestHeadersForMetadataAddressBehavior());

// modify address filter mode for load balancing
var serviceBehavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
serviceBehavior.AddressFilterMode = AddressFilterMode.Any;
serviceBehavior.IncludeExceptionDetailInFaults = true;

正在建立 System.ServiceModel.Security.WSTrustServiceHost 的一个实例来处理对 WS-Trust 的调用,并处理其元数据。检查 WSTrustServiceHost ctor 中默认添加的 ServiceMetadataBehavior,我们可以看到它确实为 GET over HTTP 和 HTTPS 启用了元数据。 http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Security/WSTrustServiceHost.cs,8c80389f2532b060,references

所以我有点困惑为什么 https://myhost.com/issue/wstrust/mex return 使用 POST 时是元数据,但是当你发送 GET 时 return 是 400 .在 System.ServiceModel 中的 EnqueueMessageAsyncResult.CompleteParseAndEnqueue() 中抛出异常 http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Channels/HttpPipeline.cs,b347567a68ab778c,references

非常感谢任何帮助!

对于其他卡在同一个地方的人,我已明确设置 TokenServiceHostFactory 以响应 HTTP GET。

// added for AAD Windows 10 sign in - device requests metadata with GET
ServiceMetadataBehavior metad = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metad == null)
    metad = new ServiceMetadataBehavior();
for (int i = 0; i < baseAddresses.Length; i++)
{
    // there will be two bindings: one for http and one secure
    switch (baseAddresses[i].Scheme)
    {
        case "http":
            metad.HttpGetEnabled = true;
            metad.HttpGetUrl = new Uri(baseAddresses[i], "/issue/wstrust/mex");
            break;
        case "https":
            metad.HttpsGetEnabled = true;
            metad.HttpsGetUrl = new Uri(baseAddresses[i], "/issue/wstrust/mex");
            break;
    }
}

那些遇到这个问题的人,有一个解决方法,即获取 ADFS 元数据文件,然后使用您自己的 WS-Trust13 实现更改 usernamemixed 和 certificatesmixed 的 WS-TRUST1.3 端点。微软似乎只支持它自己的 ADFS 元数据文件。我也联系了 Microsoft 支持,但他们尚未提供答复。尽管他们承认元数据解析可能被硬编码到 ADFS 并且与标准 WS-TRUST13 元数据实现不一致。

        <wsdl:port name="CertificateWSTrustBinding_IWSTrust13Async" binding="tns:CertificateWSTrustBinding_IWSTrust13Async">
        <soap12:address location="https://sts.gemalto.com/adfs/services/trust/13/certificatemixed"/>
        <wsa10:EndpointReference>
            <wsa10:Address>https://sts.gemalto.com/adfs/services/trust/13/certificatemixed</wsa10:Address>
        </wsa10:EndpointReference>
    </wsdl:port>
    <wsdl:port name="UserNameWSTrustBinding_IWSTrust13Async" binding="tns:UserNameWSTrustBinding_IWSTrust13Async">
        <soap12:address location="https://sts.gemalto.com/adfs/services/trust/13/usernamemixed"/>
        <wsa10:EndpointReference>
            <wsa10:Address>https://sts.gemalto.com/adfs/services/trust/13/usernamemixed</wsa10:Address>
        </wsa10:EndpointReference>
    </wsdl:port>