2

We've customised IdentityServer 2 to provide identity federation capability into Azure AD (for Office 365, etc). This has a WS-Federation endpoint for the passive requester flow and WS-Trust for active clients. The MEX endpoint for WS-Trust should return the WSDL for the WS-Trust SOAP in response to both a POST (as Lync uses) and GET (as Windows 10 sign in uses). Unfortunately, it is returning HTTP 400: ws-trust system.servicemodel.protocolexception "There is a problem with the XML that was received from the network".

As can be seen in the source: 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;

An instance of System.ServiceModel.Security.WSTrustServiceHost is being stood up to handle calls to WS-Trust, and handle its metadata. Checking the ServiceMetadataBehavior that is added by default in WSTrustServiceHost ctor, we can see that it does enable metadata for GET over both HTTP and HTTPS. http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Security/WSTrustServiceHost.cs,8c80389f2532b060,references

So I'm a little confused why https://myhost.com/issue/wstrust/mex returns the metadata when hit with a POST, but returns 400 when you send it a GET. The exception is being thrown in a EnqueueMessageAsyncResult.CompleteParseAndEnqueue() in System.ServiceModel http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Channels/HttpPipeline.cs,b347567a68ab778c,references

Any help greatly appreciated!

Rob Potter
  • 948
  • 6
  • 28

2 Answers2

2

For others stuck in the same place, I have explicitly set the TokenServiceHostFactory to respond to 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;
    }
}
Rob Potter
  • 948
  • 6
  • 28
  • Hi Rob, I see you were working on getting win10 aad sign in to work in combination with IdentityServer. Did you end up getting this to work? After a lot of effort trying to get aad sign in to work with our own custom IdP, we ended up giving up and setting it up with ADFS instead. Not the optimal solution for us. Just knowing it works with a non MS supported platform would be encouraging, and I have considered giving IdentityServer a look as a replacement for our custom solution. – MarkHasper Dec 21 '17 at 19:51
  • 2
    I responded to your question on Twitter, but for future visitors here is the answer... In addition to the above there is also a bug in the WSDL parser of all current Windows 10 builds, Basically, Win10 requires that the Trust13Issue operation is listed as the final node in that element - any other position and it won't work. Workaround is to host a static copy of your WSDL where you've reordered the operation elements by hand. Brittle, but it works. Note also that Win10 will use WS-Trust 1.3 endpoints in preference to Feb2005, so only need to modify those bindings. – Rob Potter Jan 05 '18 at 08:18
  • 2
    Thanks to your tips I now have a POC working with IdentityServer2 :-). I was having trouble with the mex endpoint of IDS so I hosted a static copy of the mex output from ADFS edited only to point to the IDS WS-Trust 1.3 endpoint. The WS-Trust 2005 endpoint in the mex I pointed to something nonexistent. One more interesting thing I noticed is that AAD federation now appears to support OpenId Connect. If you call `Get-MSOLDomainFederationSettings` there is a discovery endpoint listed. During win 10 login I also saw calls to a nonexistent openid discovery endpoint on my IDS server. Surprising! – MarkHasper Feb 23 '18 at 10:10
  • @MarkHasper we are also integrating IdentityServer2 with AzureAD. Successfuly able to set WS-Federation and domain joining/web signin succeeds. But, when trying to login to Windows 10 device, I can see call from Windows10 device hitting WS-Federation meta datapoint (https://myhost/FederationMetadata/2007-06/FederationMetadata.xml) and I get breakpoint hit. But, after that no call can be traced and authentication fails. I have added HttpGet endpoint for WSTrustService host. Seems that I am missing something. Can you please help? – SmartCoder Feb 18 '21 at 08:34
0

Those who get stuck with this issue, there is a workaround of taking ADFS metadata file and then changing WS-TRUST1.3 endpoints of usernamemixed and certificatemixed with your own WS-Trust13 implementation. Microsoft seems to support only its own ADFS metadata file. I contacted Microsoft support too but they are yet to provide an answer. Although they acknowledge that metadata parsing may be hardcoded to ADFS and not aligned with standard WS-TRUST13 metadata implementation.

        <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>
SmartCoder
  • 856
  • 6
  • 11