Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

WCF.js Message Level Signature? Check.

DZone's Guide to

WCF.js Message Level Signature? Check.

· Web Dev Zone ·
Free Resource

Deploy code to production now. Release to users when ready. Learn how to separate code deployment from user-facing feature releases with LaunchDarkly.

This is a very exciting moment for Wcf.js. It now supports one of the WS-Security most common scenarios - x.509 digital signatures. This is the first WS-Security implementation ever in javascript to support this. This implementation relies on xml-crypto on which I told you last time.

Look at any of the following Wcf bindings:

<wsHttpBinding>
  <binding name="NewBinding1">
    <security>
      <message clientCredentialType="Certificate" />
    </security>
  </binding>
</wsHttpBinding>
<customBinding>
  <binding name="NewBinding0">
    <textMessageEncoding />
    <security authenticationMode="MutualCertificate"
              messageSecurityVersion="WSSecurity10...">
      <secureConversationBootstrap />
    </security>
    <httpTransport />
  </binding>
</customBinding>

Assume only signatures are used (no encryption):

[ServiceBehavior(ProtectionLevel=ProtectionLevel.SignOnly)]

Then a soap request would look like this:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" ... >
  <Header>
    <ws:Action>http://tempuri.org/IService/GetData</ws:Action>
    <ws:To>http://localhost:8888/</ws:To>
    <ws:MessageID>ca62b7d7-4f74-75ed-9f5c-b09b173f6747</ws:MessageID>
    <ws:ReplyTo>
      <ws:Address>...</ws:Address>
    </ws:ReplyTo>
    <o:Security>
      <u:Timestamp xmlns:wsu="..." wsu:Id="_1">
        <u:Created>2012-05-25T12:18:38Z</u:Created>
        <u:Expires>2012-05-25T12:23:38Z</u:Expires>
      </u:Timestamp>
      <o:BinarySecurityToken ValueType="..." EncodingType="..." u:Id="sec_0">
         MIIBxDCCAWI...
      </o:BinarySecurityToken>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="...xml-exc-c14n#" />
          <SignatureMethod Algorithm="...rsa-sha1" />
          <Reference URI="#_0">
            <Transforms>
              <Transform Algorithm=".../xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="...xmldsig#sha1" />
            <DigestValue>fxQc0PEh2GHA43IXltm6gjbccsA=</DigestValue>
          </Reference>
          <Reference URI="#_1">
            <Transforms>
              <Transform Algorithm=".../xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="...xmldsig#sha1" />
            <DigestValue>L+vrfEszbn2ZtXiWfNyDG8nM1e8=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>AcOb1KJHpyQnnChEZFEL7g+LEXnv...</SignatureValue>
        <KeyInfo>
          <o:SecurityTokenReference>
            <o:Reference URI="#sec_0" ValueType="..." />
          </o:SecurityTokenReference>
        </KeyInfo>
      </Signature>
    </o:Security>
  </Header>
  <Body xmlns:wsu="..." wsu:Id="_0">
    <GetData xmlns="http://tempuri.org/">
      <value>123</value>
    </GetData>
  </Body>
</Envelope>

You can now interoperate with such services from javascript using Wcf.js with this code:

var wcf = require('wcf.js')
  , fs = require("fs")
  , TextMessageEncodingBindingElement = wcf.TextMessageEncodingBindingElement
  , HttpTransportBindingElement = wcf.HttpTransportBindingElement
  , SecurityBindingElement = wcf.SecurityBindingElement
  , CustomBinding = wcf.CustomBinding
  , Proxy = wcf.Proxy

var binding = new CustomBinding(
    [ new SecurityBindingElement({AuthenticationMode: "MutualCertificate"})
    , new TextMessageEncodingBindingElement(
                                 {MessageVersion: "Soap11WSAddressing10"})
    , new HttpTransportBindingElement()
    ])

var proxy = new Proxy(binding, "http://localhost:7171/Service")

proxy.ClientCredentials.ClientCertificate.Certificate =
        fs.readFileSync("client.pem").toString()

var message = "<Envelope xmlns='http://schemas.xmlsoap.org/soap/envelope/'>" +
                    "<Header />" +
                      "<Body>" +
                        "<GetData xmlns='http://tempuri.org/'>" +
                          "<value>123</value>" +
                        "</GetData>" +
                      "</Body>" +
                  "</Envelope>"

proxy.send(message, "http://tempuri.org/IService/GetData",
  function(message, ctx) {
    console.log(ctx)
  })

Note that a pem formatted certificate needs to be used. Wcf likes pfx formats more, so check out the instructions here on how to do the conversion.

You should also be aware that Wcf.js by default does no validate incoming signatures from the server. If you wish to validate them check out the sample here.

Deploy code to production now. Release to users when ready. Learn how to separate code deployment from user-facing feature releases with LaunchDarkly.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}