Web Services Reloaded1

A Deconstruction and Reconstruction of Web Services.

This is a living document. Over time it will grow in content (and formatting) to encompass a system for exchanging structured XML messages over the Internet. I know that doesn't sound very novel, but this may turn into someting good.

The contents of this page are driven from the "real-time" thinking going on in the web services category of my blog. As these specs begin to mature, and (hopefully) as interest in them grows, I'll switch over to a Wiki. For now, I'll update this page myself.

This document describes an XML messaging system named Moxie that I believe is simpler than the SOAP Web Services stack while maintaining the power of that series of standards. It borrows all of the good ideas from SOAP, WS-Addressing, WS-Security and so on, and leaves behind the cruft. It also borrows liberally from the philosophy of the REST Web Services camp. The hope is to get the best of both worlds and to deliver something useful and unique.

It's my contention that part of the problem with the current WS-* standards is that they are built on the very flimsy layer of SOAP and WSDL. SOAP started life as an XML-based RPC mechanism that relied too heavily on HTTP. Even as useful standards and practices were added on to this foundation they had to deal with the fact that the underlying SOAP infrastructure was less than satisfactory. Things became so complicated that another organization, the Web Services Interoperability Organization (WSI), was formed simply to standardize the standard.

The design philosophy of Moxie (in contrast with SOAP Web Services) is as follows:


Moxie

A Message Oriented XML Internet Exchange server 2

Moxie is a distributed, asynchronous, Internet scalable, XML messaging system. It is optionally secure and (possibly) reliable. It is analagous to a traditional Message Oriented Messaging (MOM) system such as MQ Series, but rather than topics and queues, Moxie uses "drop-boxes". Applications write messages to a Moxie server drop-box and other applications read them back using XQuery. Moxie Architecture

Moxie Transport3

Moxie uses its own simple, connectionless, stateless transport that is easilly tunneled through other transports. The Moxie transport (MXTP) is little more than a transient socket connection, all protocol and data semantics are carried as part of the XML message. Moxie uses MXTP instead of HTTP as I subscribe to the REST view that HTTP is not a generic transport but an application level transport with its own semantics, semantics that differ from Moxies. MXTP is connectionless, stateless, and primitive expressly to convince administrators to allow it through the firewall. Also, I believe that all message information should persist with the message end-to-end rather than exist in heavy-weight, point-to-point protocols.

Applications that wish to post a message will make a TCP connection to a Moxie server on port 26. Moxie will process the message, return an XML formatted status response, and disconnect. If no message is delivered from the client, Moxie will disconnect after 60 seconds (configurable).

Applications that wish to read a message will make a TCP connection to a Moxie server on port 264. Moxie will process the message, return an XML formatted message with the status and any appropriate messages, and disconnect. If no message is delivered from the client, Moxie will disconnect after 60 seconds (configurable).

Moxie Processing

An application can request that messages be sent to a "drop box." I use the term drop box to avoid overloading the words "topic," "queue," etc. It's difficult to do the same for participants in a message exchange, so an application that sends (does a write) a message is a "sender," and an application that picks up a message is a "recipient."

A drop box is a simple URL. Since Moxie uses it's own transport, the URL scheme is "moxie:" The path to the mailbox can be arbitrarily deep. Each path element can have its own access control. An example drop box is moxie://server.domain.tld/humanresources/newemployee. Moxie reserves the root path element "moxie" for it's own use. That is, no application can create a drop box of the name server.domain.tld/moxie/...

Drop boxes are created when an application registers its intent to receive messages. To register a drop box with Moxie an application sends a "write" message to the Moxie drop box "/moxie/registry." This message format has yet to be defined, but it will allow you to specify allowed inbound message formats, security, access control, etc. It is likely to be modeled after the WS-Policy family of standards. A sender can discover this information by sending a read message to the /moxie/registry drop box. For instance, the read message might ask for all applications using a specified dropbox, or all applications using secure messaging, or all applications that accept messages described by a particular schema. And all this via XQuery, not UDDI. Though not (yet) centralized, it should be straight forward to, say, set up a master Moxie server that can aggregate the registries of other Moxie servers.

In addition to the /moxie/registry drop box, Moxie has the /moxie/catchall drop box. This dropbox is for all messages that were sent to the root drop-box (i.e., server-name).

Without any access control, any application can send messages to or retrieve messages from any particular drop box. Access control can be used to limit who is able to act as a sender or recipient for a drop box. Access control mechanisms have yet to be defined, but I suspect they will be standard (maybe XACML based); limiting who is allowed to read and write based on user, domain, etc.

A sender connects to a single Moxie server to deliver a message. A message can be addressed to multiple drop boxes on multiple servers (same as SMTP). If the message is destined for another server, Moxie will relay it. By default messages are one-way, that is no reply is expected. If the sender wants a reply, they can include an address to which replies should be sent and a unique identifier so that replies can be correlated with the original message. If the recipient requires it, a sender can sign and/or encrypt a message.

To retrieve messages a recipient connects to a single moxie server and sends a read message containing an XPath/XQuery expression. Moxie will return all matching messages for processing. It's possible for multiple applications to retrieve a single message if access control permits. It's possible for the recipient to request any part of a message, even to transform it on the server before receiving it. If a message indicates it's expecting a reply, the recipient should send a reply to the address stated in the message.

A Moxie server gives each message a default time to live (TTL). That is, after a message is recived it will be available in a drop box for X amount of time. The default TTL value is 24 hours. After this time the message will be moved to a history drop box named $ORIGINAL_DROP_BOX/history. For example, moxie://server.domain.tld/humanresources/newemployee/history. A recipient may alter the default TTL on a per drop box level. A sender may include a Timestamp in a message. If so, then the <Expires> element will be honored, but only if it is less than the drop box's TTL.

I still have to put some serious thinking into the possible issue of retrieving previously retrieved messages.

Moxie Messages

Currently there are two types of messages: read and write. In the future there may be more, such as take, subscribe, or notify.

The XML Schema description of a Moxie message can be found here: http://wanderingbarque.com/moxie/2005/06/messaging.xsd. XML Schema has a number of limitations that do not allow me to express exactly the requirements of Moxie. In the future I'll provide a Schematron schema which, I think, does, but I have to learn Schematron first.

A Minimalist Moxie Write Message.


<?xml version="1.0" encoding="utf-8"?>
<mox:Envelope 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://wanderingbarque.com/moxie/2005/06/messaging.xsd http://wanderingbarque.com/moxie/2005/06/messaging.xsd"
  xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">
  
  <mox:Action>write</mox:Action>

  <mox:Message>
    <mox:Header>
      <mox:To>moxie://moxie.wanderingbarque.com/humanresources/newemployee</mox:To>
    </mox:Header>
    <mox:Body schemaType="xsd">
      <emp:Employee xmlns:emp="urn:example.org:employee" >
        <emp:EmployeeId>A-123</emp:EmployeeId>
        <emp:LastName>Smith</emp:LastName>
        <emp:FirstName>Joe</emp:FirstName>
        <emp:Salary>100000</emp:Salary>
        <emp:GovtId>123-45-6789</emp:GovtId>
      </emp:Employee>
    </mox:Body>
  </mox:Message>
</mox:Envelope>

Let's walk through this. Moxie uses a variation on the standard envelope pattern. The outermost (root) element is an <Envelope> tag. This wraps up an <Action> element and a <Message> element. The Message tag in turn encloses a <header> and a <body>. You may be wandering about this extra level of indirection. Why not simply have the Header and Body tags inside an Envelope, ala SOAP? Why introduce the Message tag?

My original intent was to do just that, a header and body inside an envelope. But I wanted to worry about security in this first release of the Moxie message format, and when experimenting with security I found that many problems simply disappear if security information is not kept in the message header, but external to it. I could have simply added a security block to the envelope (and I did), but grouping the header and body together more easily allows for signing an entire message. We'll talk more about this when we discuss security later. For now, the <Message> element is there to simply group the message header and body together for more effective security.

The <Action> element can currently be either "read" or "write." I may add more in the future like "take," "subscribe," or "notify." Or I may not. For now, there's read and write, which I believe are self-explanatory.

Inside the message header of a "write" message there's a mandatory <To> tag. This is an interesting element. It contains a simple URL (not the silly SOAP-work-around EndpointReference of WS-Addressing) using the "moxie:" scheme and specifying a Moxie server and an optional drop-box. In this case the Moxie server is "moxie.wanderingbarque.com" and the drop-box is "/humanresources/newemployee." There can be multiple <To>s in a write message. If so, the Moxie server will place a copy of the message into each drop-box. If any of the <To>s point to another server, Moxie will relay it. There will, of course, need to be some anti-relaying stuff built in, to prevent Moxie spam.

The <Body> tag has one optional attribute, schemaType. This attribute specifies which type of schema, if any, describes the embedded message. The allowed values for schemaType are: "xsd," "relaxng," "schematron," "dtd," "nvp," and "none." The default is "none." All of these should be self-explanatory except, maybe, "nvp" which is "name value pair," and describes a schema that I'll build into Moxie allowing for free-form XML echoing an HTTP POST. The presence of the schemaType attribute presumes that sender is allowed to decide what schema type to use to describe the message they are sending, and therefore how the message is formatted. This may indeed be the case for, say, a genric XML "pretty print" service. In practice, however, allowable messages will be more narrowly proscribed by the application that setup the drop box.

The rest of the <Body> element is any old XML you want (or that the drop-box allows), so long as it's well formed (and, possibly, valid against it's schema). Note that the XML Schema description of a Moxie message doesn't literally allow for any old XML, it mandates that the XML be namespace qualified. But that's one of the many limitations of XML Schema, and not what I have in mind -- A Moxie message body can contain any valid XML.

When a write message is received, Moxie will validate it for well-formedness and (optionally) against the message schema. If all is well, the entire message, from the <Envelope> tag down will be deposited in the appropriate drop boxes or relayed to another Moxie server. Regardless of the success of the write a status message will be returned from the server indicating what happened, and the connection will be dropped.

Response from a Successful Write


<mox:WriteResponse xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">  
  <mox:Status>
    <mox:Code>200</mox:Code>
    <mox:Message>OK</mox:Message>
  </mox:Status>
</mox:WriteResponse>

Response codes have yet to be defined, but the design will be taken from HTTP. That is, 200 series codes for success, 400 series for failure, etc.

A Minimalist Moxie Read Message


<mox:Envelope  
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://wanderingbarque.com/moxie/2005/06/messaging.xsd http://wanderingbarque.com/moxie/2005/06/messaging.xsd"
  xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">
  
  <mox:Action>read</mox:Action> 
  
  <mox:Message>
    <mox:Body>
      <mox:Xquery>
declare namespace mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd";
/mox:Envelope/mox:Message[mox:Header/mox:To="moxie.wanderingbarque.com/humanresources/newemployee"]
      </mox:Xquery>
    </mox:Body>
  </mox:Message>
</mox:Envelope>

The only unexpected bits here are the absence of a header and the <mox:Xquery> element. The <Xquery> element is the primary facilitator of the power of Moxie. Recipients can put into this element any valid XQuery expression. This will allow a recipeint (as constrained by any access controls) to, for example, retrieve from multiple drop boxes, retrieve only the message bodies, retrieve only secure messages, retrieve messages sent last week to accounts payable (using Moxie message elements we haven't discussed yet). Really, you're only constrained by the power of XQuery (which has few constraints) and your particular implementation (which may).

Another Moxie Read Message


<mox:Envelope ...>
  
  <mox:Action>read</mox:Action> 
  
  <mox:Message>
    <mox:Body>
      <mox:xquery>
declare namespace mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd";
declare namespace emp="urn:example.org:employee";

for $i /mox:Envelope
where $i/mox:Message/mox:Header/mox:From="urn:company.com:someidentifier" 
  and $i/mox:Message/mox:Body/emp:Employee/emp:LastName="Smith"
return
  $i/mox:Message
      </mox:xquery>
    </mox:Body>
  </mox:Message>
</mox:Envelope>

The above "read" message is there just to show an XQuery "FLWOR" expression instead of just a simple XPath expression.

The Moxie Response from the First Example


<mox:ReadResponse xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">  
  <mox:Status>
    <mox:Code>200</mox:Code>
    <mox:Message>OK</mox:Message>
  </mox:Status>
  <mox:Message xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">
    <mox:Header>
      <mox:To>moxie://moxie.wanderingbarque.com/humanresources/newemployee</mox:To>
    </mox:Header>
    <mox:Body schemaType="xsd">
      <emp:Employee xmlns:emp="urn:example.org:employee">
        <emp:EmployeeId>A-123</emp:EmployeeId>
        <emp:LastName>Smith</emp:LastName>
        <emp:FirstName>Joe</emp:FirstName>
        <emp:Salary>100000</emp:Salary>
        <emp:GovtId>123-45-6789</emp:GovtId>
      </emp:Employee>
    </mox:Body>
  </mox:Message>        
</mox:ReadResponse>

A read response carries a status code followed immediately by the result of the query. Notice how the retrieved message does not contain an <Envelope> element. This is not Moxie doing this, rather that's what the query specified -- return all <Message> elements contained in an <Envelope> element who's Header/To element is equal to "moxie.wanderingbarque.com/humanresources/newemployee." Realize that since this query leaves the <Envelope> tag behind the response is not valid according to the schema. It's important for recipients to be aware of this and not try to automatically validate query responses against a schema. If possible, I may make it configurable for Moxie to not return messages that are schema invalid.

Where's the "from?" You'll notice that in these examples the message does not contain who sent it or who retrieved it. There is a <From> tag, but it's optional, and so are a few more. They're explained next, along with succinct descriptions of the tags we've already encountered.

Moxie Message Elements

Envelope

REQUIRED. Wraps a Moxie read or write message, an Action element, and an optional security information block.

Envelope/Message

REQUIRED. Wraps a message header and message body.

Envelope/Action

REQUIRED. Must be set to either "read" or "write".

Envelope/Message/Header

OPTIONAL if and only if there are no header sub-elements. Contains message header elements.

Envelope/Message/Header/From

OPTIONAL. Takes a URI. See the security section for suggested use of this element. Recipient MAY REQUIRE that this element be present.

Envelope/Message/Header/To

MUST be included for "write" messages. MUST NOT be included for read messages. Takes a moxie: URL containing the server name and an optional drop box. May be more than one.

Envelope/Message/Header/ReplyTo

OPTIONAL for "write" messages. MUST NOT be included in "read" messages. Signifies that the sender expects a reply from the recipient(s). If not included, the recipient SHOULD NOT (can't really) reply. If included, the recipient SHOULD reply.

Envelope/Message/Header/ReplyId

OPTIONAL. MUST be included if <ReplyTo> is specified. MUST NOT be included otherwise. Takes a URI that is globally unique. Recommended format is moxie:server.domain.tld/UUID

Envelope/Message/Header/RelatesTo

OPTIONAL. SHOULD be included if this message represents a reply to an earlier message, in which case the value should be copied from the earlier message's <ReplyId> element. MUST NOT be included otherwise.

Envelope/Message/Header/ConversationId

OPTIONAL. Can be included if sender wants to track a series of messages. SHOULD be a globally unique value. Recommended format is moxie:server.domain.tld/UUID. If a sender is replying to an earlier me ssage and that message contains a <ConversationId>, then the reply SHOULD contain the same ConversationID. The distinction between this element and a ReplyId is that ReplyId is expected to be used to correlate one or more replies to a single message. ConversationID is supposed to persist across multiple back and forth exchanges.

Envelope/Message/Body

REQUIRED. Contains the message payload. If the message is a "write," the payload can be any valid XML document. It does not have to be described by a schema, but can be. If the message is a read, then the payload is an XQuery expression.

Envelope/Message/Body/@schemaType

OPTIONAL for "write" messages. MUST NOT be used in "read" messages. Describes what type of schema document, if any, describes this message. Allowable values are: xsd, realxng, schematron, dtd, nvp, and none. Default is none.

Envelope/Message/Body/Xquery

REQUIRED for "read" messages. MUST NOT be used for write messages. Contains the XQuery expression to read back messages from the Moxie server.

To put all this another way, a "write" message must have one or more To fields, and that's it. If the sender wants a reply, they must add a ReplyTo and a ReplyId field. They may optionally add a ConversationID. If this message is a reply to an earlier message, then they must add a RelatesTo element with the value of the eariler message's ReplyId. If that earlier message also had a ConversationId, then they should add that too. Senders may optionaly add a From field, or recipients might require that senders add one.

A "read" message has an optional From field and that's it. If the From is left out, then the Header can be left out too.

Write Response Elements

WriteResponse

REQUIRED. Wraps a response to a Moxie write message.

WriteResponse/Status

REQUIRED. Wraps a response code and a response message.

WriteResponse/Status/Code

REQUIRED. Contains an integer valued response code. TBD. 200 = OK, 400=Failed, etc.

WriteResponse/Status/Message

REQUIRED. Contains the response text.

Read Response Elements

ReadResponse

REQUIRED. Wraps a response to a Moxie write message.

ReadResponse/Status

REQUIRED. Wraps a response code and a response message.

ReadResponse/Status/Code

REQUIRED. Contains an integer valued response code. TBD. 200 = OK, 400=Failed, etc.

ReadResponse/Status/Message

REQUIRED. Contains the response text.

ReadResponse/*

OPTIONAL. Contains the result of the read query.

Security

Moxie security encompasses identification, encryption, and messages integrity. Like WS-Security (WSS), it meets these goals by leveraging the XML Digital Signature (XDS) and XML Encryption (XE) specifications. Unlike WSS, it does this without introducing any new constructs or processing requirements. For the sake of simplicity and interoperability, Moxie significantly reduces the number of moving parts that are present in XDS and XE. That is, the WSI group's work is already done.

Identification

A recipient may require a sender to identify itself in the message it sends and to control who can read from a drop box. There are exactly two ways to do this in Moxie: via the <From> field in the message header or by using digital signatures. If a drop box is under access control, Moxie will respond to a digital signature if present or to a <From> element if not. If both elements are missing and the drop box is access controlled, Moxie will reject the message.

The <From> field is not secure. It is meant for use in applications that have no security requirements but would like to have a general idea of who's sending messages, and for applications in a controlled environnment. <From> is of #anyURI type. The element content should be unique among allowed senders. Examples: mailto:placey@wanderingbarque.com, moxie://moxie.wanderingbarque.com/humanresources, urn:company.com:users:placey

For secure applications the only supported identification token is an X.509 certificate. Other commonly referenced tokens, e.g. UsernameToken, Kerberos tickets, and so on, are not supported. This should make implementations simpler and foster interoperability. This design choice is not arbitrary; simplicty and interoperability are core requirements of Moxie, and supporting an arbitrary number of identity tokens does not add as much value as it does complexity. Going forward I will probably allow for SAML tokens too. Not now, though. However, not offering a UsernameToken may seem a bit heavy handed, so let me explain.

First, a UsernameToken containing just a Username element (and not a password) is really just a From field. A username/password pair with the password in plaintext is really just a From field broken into two pieces. A username/password pair with a hashed password is really just a From field broken into two pieces with the second piece looking kind of odd. In fact, the only good use for a UsernameToken is when a nonce and a timestamp are included (to prevent replay attacks) and this information is hashed into the password. However, though not mentioned yet, Moxie has a nonce-equivalent field, the UniqueId, and a Timestamp field. More importantly, if a UsernameToken complete with nonce and timestamp were used, they would need to be signed so that the receiver would know that these elements haven't been modified by an attacker. Since a UsernameToken needs to be signed, it seems rather redundant to have it at all.

To provide an X.509 certificate as an identity token follow the instructions for Message Integrity below.

I am fully aware that rolling out a complete PKI environment is a significant undertaking. However, it's anticipated that most Moxie "users" won't be actual people, but server applications which can easily be issued a certificate. Furthermore, if a message crosses Moxie servers (say, between two organizations) signing can be relegated to the originating Moxie server, which too can easily be issued a cert. Finally, it's often reasonable to assume that intranets are "secure enough," that is the <From> field provides enough identification.

Message Integrity

There is only one way to guarantee that a message has not been modified in transit (either accidentally or maliciously) and that is to sign it. Moxie uses the XML Digital Signature specification as the means of signing a message. This is probalby one of the more brittle technologies in the XML arena as one small change to a message can render it invalid. To mitigate this brittleness and to foster interoperability Moxie limits the amount of flexibility inherent in XDS. Here are the Moxie rules for signing a message:

  1. You MUST sign the entire /Envelope/Message (that is, sign the message header and body, but not the envelope or the other elements it contains).
  2. The /Envelope/Message MUST contain a wsu:Id attribute using a simplified XPointer, e.g. wsu:Id="TheMessage." This attribute MUST be referenced via the URI attribute of the ds:Reference element.
  3. Only one canonicalization algorithm is supported, Exclusive XML Canonicalization (http://www.w3.org/2001/10/xml-exc-c14n#). As you'll see, there is no need to use the InclusiveNamespaces parameter of this algorithm.
  4. Only one keyed hashing algorithm (SignatureMethod) is supported, HMAC-SHA1 (http://www.w3.org/2000/09/xmldsig#hmac-sha1)
  5. Only one message digest (hash) algorithm is supported, SHA1 (http://www.w3.org/2000/09/xmldsig#sha1)
  6. Only one encoding mechanism is supported, base64.
  7. The KeyInfo element MUST hold the sender's key bound up in an X.509 certificate base64 encoded. No wsse:SecurityTokenReference is needed or supported. In the future I may relax this a little bit and allow for the sender's certificate to be referenced externally.

The implication of these rules (outside of simplicity and interop) is that an intermediary MUST not rewrite any part of the message after it's been signed.

In a Moxie message information about signing (and encryption) is kept external to the message in the Envelope's <Security> element. This affords us one additional level of simplicity: it is not necessary to go through any contortions to avoid signing the header while adding security information to it at the same time.

It may be useful for the Moxie server to remove the signature and replace it with the sender's common name. This will allow the recipient not to have to reprocess the signature to get the user's identity. The recipient must trust that Moxie has validated the signature. The recipient can then use the sender's common name in, say, and LDAP lookup to verify that they are a valid user or to use the sender's identity in other processing (if sender's role is "customer" ...). I have to put more thought into this. If Moxie rewrites a signed message it should store the original in a separate drop box for auditing purposes, something like: moxie://server.domain.tld/humanresources/newemployee/audit, and probalby add a reference to the message and re-sign it.

A Signed Moxie Message


<mox:Envelope 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://wanderingbarque.com/moxie/2005/06/messaging.xsd http://wanderingbarque.com/moxie/2005/06/messaging.xsd"
  xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">

  <mox:Action>write</mox:Action>
 
  <mox:Security>
    <ds:Signature>
      <ds:SignedInfo>
        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
        <ds:Reference URI="#TheMessage" >
          <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
          <ds:DigestValue>Ab75hf8ijd...</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>Q45hgfuU...</ds:SignatureValue>  
      <ds:KeyInfo>
        <ds:X509Data>
          <ds:X509Certificate>
lui+Jy4WYKGJW5xM3aHnLxOpGVIpzSg4V486hHFe7sHET/uxxVBovT7JV1A2RnWSWkXm9jAEdsm/
hs+f3NwvK23bh46mNmnCQVsUYHbYAREZpykrd/eRwNgx8T+ByeFhmSviW77n6yTcI7XU7xZT54S9
hTSyBLN2Sce1dEQpQXh5ssZK9aZTMrsFT1NBvNHC3Qq7w0Otr5V4axH3MXffsuI9WzxPCfHdalN4
rLRfNY318pc6bn00zAMw0omUWwBEJZxxBGGUc9QY3VjwNALgGDaEAT7gpURkCI85HjdnSA5SM4cY
7jAsYX/CIpEkRJcBULlTEFrBZIBYDPzRWlSdsJRJngF7yCoGWJ+/HYOyP8P4OM59FDi0kM8GwOE0
WgYrJHH92qaVhoiPTLi7
          </ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </ds:Signature>

  </mox:Security>

  <mox:Message wsu:Id="TheMessage">
    <mox:Header>
      <mox:From>urn:company.com:someidentifier</mox:From>
      <mox:To>moxie://moxie.wanderingbarque.com/humanresources/newemployee</mox:To>
      <mox:To>moxie://moxie.example.org/service/name</mox:To>
      <mox:ReplyTo>replies.company.com</mox:ReplyTo>
      <mox:ReplyId>moxie://company.com/guid/1ca3f3e5-76fa-7abc-a981-234ecc9478552</mox:ReplyId>
      <mox:ConversationId>moxie://company.com/guid/9a82ee6f-6651-3eeb-aa77-b2b1001aef72a</mox:ConversationId>
      <mox:Timestamp> 
        <mox:Created>2005-09-13T08:42:00Z</mox:Created>
        <mox:Expires>2005-10-13T09:00:00Z</mox:Expires>
      </mox:Timestamp>
    </mox:Header>
    <mox:Body schemaType="relaxng">
      <emp:Employee xmlns:emp="urn:example.org:employee" >
      <emp:Employee xmlns:emp="urn:example.org:employee">
        <emp:EmployeeId>A-123</emp:EmployeeId>
        <emp:LastName>Smith</emp:LastName>
        <emp:FirstName>Joe</emp:FirstName>
        <emp:Salary>100000</emp:Salary>
        <emp:GovtId>123-45-6789</emp:GovtId>
      </emp:Employee>
    </mox:Body>
  </mox:Message>

</mox:Envelope>

Message Encryption

Moxie uses the XML Encryption specification for message encryption. The drop box creator can decide whether Moxie should decrypt the message before storing it or whether the recipient is responsible for decryption. The difference is simply who's key is used by the sender for encryption. When encrypting a read message the message body MUST be encrypted with the Moxie server's public key. Encryption is a lot less fragile than signing so fewer restrictions have been imposed. Here are the rules:

  1. A sender MUST NOT encrypt any part of the message EXCEPT the Body. That is, the message header must not be encrypted.
  2. A sender MAY encrypt the entire body, certain elements, or just the contents of certain elements.
  3. A sender MAY use a symetric key to encrypt message data, in which case the symetric key MUST be placed in a xenc:EncryptedKey element in the Security block. The recipient's public key MUST be referenced from the embedded ds:KeyInfo element.
  4. A sender MAY use the recipient's public key to encrypt message data, in which case a reference to the public key MUST be included in the xenc:EncryptedData element and an xenc:ReferenceList MUST be included in the Security block pointing to all such public key encrypted elements.
  5. Recipient's MAY publish via the Moxie registry which encryption algorithms it supports. If so, the sender MUST honor these.

An Encrypted Moxie Message


<mox:Envelope 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://wanderingbarque.com/moxie/2005/06/messaging.xsd http://wanderingbarque.com/moxie/2005/06/messaging.xsd"
  xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
  xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">

  <mox:Action>write</mox:Action>
 
  <mox:Security>

    <!-- Using a public key to encrypt a symetric key -->
    <xenc:EncryptedKey>
      <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/> 
      <ds:KeyInfo>
        <ds:X509Data>
          <ds:X509SubjectName> 
C=US, ST=Massachusetts, L=Newburyport, O=Wandering Barque, OU=ISP, 
CN=wanderingbarque.net/emailAddress=postmaster@wanderingbarque.com
          </ds:X509SubjectName> 
        </ds:X509Data>
      </ds:KeyInfo>
      <xenc:CipherData>
        <xenc:CipherValue>d2FpbmdvbGRfE0lm4byV0...</xenc:CipherValue>
      </xenc:CipherData>
      <xenc:ReferenceList>
        <!-- A pointer to the data encrypted with the symetric key -->
        <xenc:DataReference URI="#enc1" />
      </xenc:ReferenceList>
    </xenc:EncryptedKey>

    <!-- Using a public key to encrypt data directly -->
    <xenc:ReferenceList>
      <xenc:DataReference URI="#enc2" />
    </xenc:ReferenceList>

  </mox:Security>

  <mox:Message>
    <mox:Header>
      <mox:From>urn:company.com:someidentifier</mox:From>
      <mox:To>moxie://moxie.wanderingbarque.com/humanresources/newemployee</mox:To>
      <mox:To>moxie://moxie.example.org/service/name</mox:To>
      <mox:ReplyTo>replies.company.com</mox:ReplyTo>
      <mox:ReplyId>moxie://company.com/guid/1ca3f3e5-76fa-7abc-a981-234ecc9478552</mox:ReplyId>
      <mox:ConversationId>moxie://company.com/guid/9a82ee6f-6651-3eeb-aa77-b2b1001aef72a</mox:ConversationId>
      <mox:Timestamp> 
        <mox:Created>2005-09-13T08:42:00Z</mox:Created>
        <mox:Expires>2005-10-13T09:00:00Z</mox:Expires>
      </mox:Timestamp>
    </mox:Header>
    <mox:Body schemaType="relaxng">
      <emp:Employee xmlns:emp="urn:example.org:employee" >
        <emp:EmployeeId>A-123</emp:EmployeeId>
        <emp:LastName>Smith</emp:LastName>
        <emp:FirstName>Joe</emp:FirstName>
        <emp:Salary>
          <!-- Encrypting element *contents* (via a symetric key) -->
          <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Content" Id="enc1" >
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> 
            <xenc:CipherData>
              <xenc:CipherValue>A23B45C56</xenc:CipherValue>
            </xenc:CipherData>
          </xenc:EncryptedData>
        </emp:Salary>
        <!-- Encrypting an entire element (via a public key)-->
        <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" Id="enc2" >
          <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> 
          <ds:KeyInfo>
            <ds:X509Data>
              <ds:X509SubjectName>placey@wanderingbarque.com</ds:X509SubjectName> 
            </ds:X509Data>
          </ds:KeyInfo>
          <xenc:CipherData>
            <xenc:CipherValue>Y6RH4AK3K</xenc:CipherValue>
          </xenc:CipherData>
        </xenc:EncryptedData>
      </emp:Employee>
    </mox:Body>
  </mox:Message>

</mox:Envelope>

Encryption and signing

A message may be both encrypted and signed. If a message is both encrypted and signed, then encryption MUST take place first. Otherwise it would be impossible to verify a signature (as one must sign the entire message) without first removing the encryption. It's also simpler this way and makes a little more sense.

An Encrypted and Signed Moxie Message


<mox:Envelope 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://wanderingbarque.com/moxie/2005/06/messaging.xsd http://wanderingbarque.com/moxie/2005/06/messaging.xsd"
  xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
  xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  xmlns:mox="http://wanderingbarque.com/moxie/2005/06/messaging.xsd">

  <mox:Action>write</mox:Action>
 
  <mox:Security>
    <ds:Signature>
      <ds:SignedInfo>
        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
        <ds:Reference URI="#TheMessage" >
          <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
          <ds:DigestValue>Ab75hf8ijd...</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>Q45hgfuU...</ds:SignatureValue>  
      <ds:KeyInfo>
        <ds:X509Data>
          <ds:X509Certificate>
lui+Jy4WYKGJW5xM3aHnLxOpGVIpzSg4V486hHFe7sHET/uxxVBovT7JV1A2RnWSWkXm9jAEdsm/
hs+f3NwvK23bh46mNmnCQVsUYHbYAREZpykrd/eRwNgx8T+ByeFhmSviW77n6yTcI7XU7xZT54S9
hTSyBLN2Sce1dEQpQXh5ssZK9aZTMrsFT1NBvNHC3Qq7w0Otr5V4axH3MXffsuI9WzxPCfHdalN4
rLRfNY318pc6bn00zAMw0omUWwBEJZxxBGGUc9QY3VjwNALgGDaEAT7gpURkCI85HjdnSA5SM4cY
7jAsYX/CIpEkRJcBULlTEFrBZIBYDPzRWlSdsJRJngF7yCoGWJ+/HYOyP8P4OM59FDi0kM8GwOE0
WgYrJHH92qaVhoiPTLi7
          </ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </ds:Signature>

    <xenc:EncryptedKey>
      <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/> 
      <ds:KeyInfo>
        <ds:X509Data>
          <ds:X509SubjectName> 
C=US, ST=Massachusetts, L=Newburyport, O=Wandering Barque, OU=ISP, 
CN=wanderingbarque.net/emailAddress=postmaster@wanderingbarque.com
          </ds:X509SubjectName> 
        </ds:X509Data>
      </ds:KeyInfo>
      <xenc:CipherData>
        <xenc:CipherValue>d2FpbmdvbGRfE0lm4byV0...</xenc:CipherValue>
      </xenc:CipherData>
      <xenc:ReferenceList>
        <xenc:DataReference URI="#enc1" />
      </xenc:ReferenceList>
    </xenc:EncryptedKey>

    <xenc:ReferenceList>
      <xenc:DataReference URI="#enc2" />
    </xenc:ReferenceList>

  </mox:Security>

  <mox:Message wsu:Id="TheMessage">
    <mox:Header>
      <mox:From>urn:company.com:someidentifier</mox:From>
      <mox:To>moxie://moxie.wanderingbarque.com/humanresources/newemployee</mox:To>
      <mox:To>moxie://moxie.example.org/service/name</mox:To>
      <mox:ReplyTo>replies.company.com</mox:ReplyTo>
      <mox:ReplyId>moxie://company.com/guid/1ca3f3e5-76fa-7abc-a981-234ecc9478552</mox:ReplyId>
      <mox:ConversationId>moxie://company.com/guid/9a82ee6f-6651-3eeb-aa77-b2b1001aef72a</mox:ConversationId>
      <mox:Timestamp> 
        <mox:Created>2005-09-13T08:42:00Z</mox:Created>
        <mox:Expires>2005-10-13T09:00:00Z</mox:Expires>
      </mox:Timestamp>
    </mox:Header>
    <mox:Body schemaType="relaxng">
      <emp:Employee xmlns:emp="urn:example.org:employee" >
        <emp:EmployeeId>A-123</emp:EmployeeId>
        <emp:LastName>Smith</emp:LastName>
        <emp:FirstName>Joe</emp:FirstName>
        <emp:Salary>
          <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Content" Id="enc1" >
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> 
            <xenc:CipherData>
              <xenc:CipherValue>A23B45C56</xenc:CipherValue>
            </xenc:CipherData>
          </xenc:EncryptedData>
        </emp:Salary>
        <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" Id="enc2" >
          <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> 
          <ds:KeyInfo>
            <ds:X509Data>
              <ds:X509SubjectName>placey@wanderingbarque.com</ds:X509SubjectName> 
            </ds:X509Data>
          </ds:KeyInfo>
          <xenc:CipherData>
            <xenc:CipherValue>Y6RH4AK3K</xenc:CipherValue>
          </xenc:CipherData>
        </xenc:EncryptedData>
      </emp:Employee>
    </mox:Body>
  </mox:Message>

</mox:Envelope>

Replay Attacks

It's exceedingly difficult to counter replay attacks in an asychronous messaging system. The normal mechanism (and that adopted by WSS) is to use a nonce and a timestamp hashed together with a secret password. This works but the WSS implementation has some limitations:

  1. The recipient must store the sender's password in plain text
  2. The nonce and timestamp are only defined for unsername tokens, not for other identity tokens
  3. The server must cache nonces for at least as long as the timestamp says the message is valid to ensure that they are not reused
  4. Unless this nonce cache is distributed, the message can still be replayed to some other server

Moxie uses a similar nonce/timestamp approach, but does not suffer from the above limitations. Since Moxie's only identity token is an X.509 certificate, the Moxie server does not need to store any passwords. In Moxie, the nonce (the UniqueId element) and the timestamp are part of the normal message header. Moxie does not need to cache nonces per se as the entirety of earlier messages are stored in Moxie by its very nature. Moxie need simply reject any message that has the same UniqueId as an existing message. Messages cannot be replayed to another server, as the receiving server's address is right there in the header. Furthermore, an attacker can't modify any of the header fields as the entire header and body have been signed.

Security Processing

All security processing takes place on the Moxie server not by the recipient. The recipient can be assured that any message it reads has been authenticated and decrypted. This is a good thing as it allows for centralized, policy driven security processing.

A Moxie server MUST follow these steps when processing a secured "write" message:

  1. Examine the <To> header element. If the message is addressed to a foreign server, relay it.
  2. Look for a <Security> element. If present, look for a <ds:Signature> element. If present, continue security processing.
  3. Examine the <Timestamp> header element. If not there, reject message. If there's an <Expires> message and it's expired, reject message. If there's only a <Created> element, check that the default time to live hasn't expired. If so, reject message.
  4. Examine the <UniqueId> header element. If not present, reject the message. If present, but identical to an existing UniqueId, reject message.
  5. If the message is signed, validate signature. If the signature is invalid, reject message.
  6. If the message is encrypted, decrypt it and place in drop box. If the message was also signed, store the original in a safe place (TBD) with 100% fidelity and remove the signature (as removing the encryption will invalidate the signature).
  7. When depositing a message apply access controls.

Security Elements

Envelope/Security

OPTIONAL. Contains security information and references

Envelope/Security/ds:Signature

OPTIONAL. An XML Digital Signature Signature element

Envelope/Security/xenc:EncryptedKey

OPTIONAL. An XML Encryption EncryptedKey element for holding a symetric key

Envelope/Security/xenc:ReferenceList

OPTIONAL. An XML Encryption ReferenceList element for addressing message content encrypted with a public key

Envelope/Message/Header/UniqueId

OPTIONAL. MUST be included if message is signed. MAY be included otherwise. Takes a URI that is globally unique. [UUID]. This element differs from the ReplyId element only in purpose. I simply did not want to overload ReplyId with two tasks.

Envelope/Message/Header/Timestamp

OPTIONAL. MUST be included if message is signed. Wraps a Created and an Expires element. Recipient MAY REQUIRE that this element be present for non-secure messages.

Envelope/Message/Header/Timestamp/Created

REQUIRED. The time security information was applied. Time MUST always be expressed in Coordinated Universal Time (Universal Standard Time, Grenewich Mena Time, Zulu Time, whatever time it is in England.).

Envelope/Message/Header/Timestamp/Expires

OPTIONAL. Time MUST always be expressed in Coordinated Universal Time.

Security Disclaimer

A lot of explanation and detail has been left out of the above discussion, especially if you're not already familiar with "the literature." I will flesh this out at a later time. For now, I just wanted to get the key points in.

Since "read" messages use XQuery it's possible to retrieve only parts of a message or to transform a message while reading it. This will cause any signatures to become invalid. However, that may not be a big issue as the recipient can already trust that any signature has been validated. In fact, it may have been removed.

I am not a security expert. There could be something seriously wrong with the above, in particular not allowing header encryption worries me a bit.

HTTP Interface

Though Moxie uses its own transport. It should be possible to interact with Moxie via HTTP. This will allow for a limited amount of tunneling and for moxie read messages to be embedded in browsers and other HTTP aware applications.

In Moxie a read request is always mapped to an HTTP GET and a write request is always mapped to an HTTP POST. It is illegal to map a read to a POST and impossible to map a write to a GET.

A Moxie read can be mapped to an HTTP GET by using a URL composed of a drop box and an XPath expression. For example, http://moxie.company.com/humanresources/newemployee/Envelope[Message/Body/LastName="Smith"]

Not all possible XQuery expressions can be executed this way, just a subset of XPath. Even XPath expressions will be curtailed by syntax that doesn't map to a URL, e.g. http://moxie.company.com/humanresources/newemployee//*

A Moxie write message is implemented as an HTTP POST simply by posting a complete write message.

In all cases, the client must ignore the HTTP response code, and parse the response body to find out what happend on the Moxie end.

To Be Done