Question

I need to query a WS Trust 1.4 service using .NET to enable a SAML 2.0 Authentication scenario.

EDIT: To be more precise I need to support an User Interaction Challenge on the client side which is defined in WS Trust 1.4.

I looked into WIF which provides direct access to WS Trust via the WSTrustChannelFactory (see trustChannelFactory.TrustVersion in the codesnippet...) but it seems that there is only support for WS-Trust 1.3 and Feb2005?

            WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(getBinding(), "http:/localhost...");

            trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
            WSTrustChannel channel = (WSTrustChannel)trustChannelFactory.CreateChannel();

            RequestSecurityToken rst = new RequestSecurityToken();

            RequestSecurityTokenResponse rstr = null;
            SecurityToken token = channel.Issue(rst, out rstr);

Does anybody know how to implement such a direct WS-Trust Query using .NET?

I cannot use a WSHttpFederation Binding since we need to work with SAML 2.0 and have to retrieve the SAMl 2.0 Authentication Requests from the Application Server before passing them to the IdP.

I could of course roll my own client-side WS-Trust 1.4. implementation, but perhaps there is an easier way...

Was it helpful?

Solution

I extended the WIF WS Trust implementation using .NET Extension methods. Here you can see the first part (Issue Request with RST and SAML Authn Request) as an example on how to reuse the things which are already defined in WIF. I used a IL Disassembler to see how things are done inside WIF which was pretty helpful on the way...

internal static RequestSecurityTokenResponseWithSAML2Assertion Issue(this WSTrustChannel pThis,
        string pSAML2AuthnRequest,
        Func<ProfileSelectionChallengeType, wsTrust14.ChoiceSelectedType> pProfileSelectionCallback)
    {
        if (pThis != null)
        {
            if (pThis.ChannelFactory != null &&
                pThis.ChannelFactory.Endpoint != null &&
                pThis.ChannelFactory.Endpoint.Binding != null)
            {
                // Create RST Request
                RequestSecurityToken rst = new RequestSecurityToken("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue");
                rst.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0";

                // we use WS Trust 1.4 but .NET WIF only provides support for WS Trust 1.3
                // so we add the needed Challenge support and reuse most of the WIF stuff
                if (pThis.TrustVersion != System.ServiceModel.Security.TrustVersion.WSTrust13)
                {
                    throw new Exception("Given WS Trust Version not supported!");
                }

                // create a WS Trust 1.3 SOAP Message
                Message issueRequest = Message.CreateMessage(pThis.ChannelFactory.Endpoint.Binding.MessageVersion,
                    "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue",
                    new WSTrustRequestBodyWriter(rst,
                        pThis.WSTrustRequestSerializer,
                        pThis.WSTrustSerializationContext));

                // add SAML Authn Request to the WS Trust request
                XmlDocument messageAsXml = issueRequest.serializeToXml();
                messageAsXml = SAMLSupport.addSAMLAuthenticationRequest(messageAsXml, pSAML2AuthnRequest);
                issueRequest = issueRequest.generateFromXml(messageAsXml);

                // invoke the WS Trust service on the STS
                Message responseMessage = pThis.Issue(issueRequest);

                // check what we received as answer...
                var response = pThis.parseAndHandleResponse(responseMessage, pProfileSelectionCallback);
                return response;
            }
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top