Workflow

From OStatus Community Group
Revision as of 16:32, 6 August 2012 by Mnordfel (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

In these quick "walkthroughs" we inspect what different payloads are exchanged between OStatus compatible systems.

User A starts to follow Test Koski's microblog

This workflow is following the OStatus specification.

Actors in this example are the following:

User A
Username: user-a
Host : lobstermonster.org
Webfinger acct: user-a@lobstermonster.org

Test Koski 
Username: testkoski
Host: identi.ca
Webfinger acct: testkoski@identi.ca

User A knows that Test Koski's username is testkoski and is hosted at identi.ca.

In this example User A will start to follow Test Koski's public microblog feed and notifies Test Koski that he is doing so. Three main steps are done to achieve this.

  1. User A "Discovers" the LRDD of Test Koski using Webfinger
  2. User A "PubSubHubbub subscribes" to Test Koski's public feed
  3. User A sends a ActivityStream Atom Entry to Test Koski using Salmon Protocol to notify about the event

User A "Discovers" Test Koski using the LRDD and Webfinger

As specified in OStatus specification chapter 10. Discovery User A can use Test Koski's Webfinger acct -uri (acct:testkoski@identi.ca) to discover the needed information to start following him.

First thing User A needs to know is where to find Test Koski's LRDD. He can archive this by asking the host-meta from Test Koski's host. User A can parse the host of Test Koski from Test Koski's acct uri (acct:testkoski@identi.ca => identi.ca).

When the host is known, User A can now fetch the host-meta:

User A's HTTP(S) request to fetch the host-meta:

GET /.well-known/host-meta HTTP/1.0
Host: identi.ca

HTTP reply from the host identi.ca :

HTTP/1.1 200 OK
Content-Type: application/xrd+xml

<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
  <hm:Host xmlns:hm="http://host-meta.net/xrd/1.0">identi.ca</hm:Host>
  <Link rel="lrdd" template="http://identi.ca/main/xrd?uri={uri}">
    <Title>Resource Descriptor</Title>
  </Link>
</XRD>

(More detailed information about obtaining the host-meta can be read here: http://tools.ietf.org/html/draft-hammer-hostmeta-13#section-2)

From the reply payload the Host and the Link with rel="lrdd" -elements interests us. We perform following actions with them:

  1. We will do a simple sanity check against the value of the Host element: is it equal to Test Koski's (testkoski@identi.ca) host? In this example the value "identi.ca" matches Test Koski's host "identi.ca" so we are good to continue. If it's not, something is wrong and abort.
  2. Next we take the value of the "template" attribute (http://identi.ca/main/xrd?uri={uri}) from the found Link element (<Link rel="lrdd" template="http://identi.ca/main/xrd?uri={uri}">). We take Test Koski's acct URI (acct:testkoski@identi.ca) and URL encode it so that it becomes acct%3Atestkoski%40identi.ca. Then we simply replace the {uri} -mask of the template with the encoded acct. As a result we have an URL http://identi.ca/main/xrd?uri=acct%3Atestkoski%40identi.ca .

Mazel Tov! Now we are ready to fetch the users LRDD and continue our discovery process to finally being able to subscribe to a user and notify him using the salmon protocol.

So let's fetch the users LRDD from the URL http://identi.ca/main/xrd?uri=acct%3Atestkoski%40identi.ca:

User A's HTTP(S) request to fetch the LRDD:

GET /main/xrd?uri=acct%3Atestkoski%40identi.ca HTTP/1.0
Host: identi.ca

HTTP reply from identi.ca:

HTTP/1.1 200 OK
Content-Type: application/xrd+xml

<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
  <Subject>acct:testkoski@identi.ca</Subject>
  <Alias>http://identi.ca/user/209172</Alias>
  <Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="http://identi.ca/user/209172"/>
  <Link rel="http://schemas.google.com/g/2010#updates-from" href="http://identi.ca/api/statuses/user_timeline/209172.atom" type="application/atom+xml"/>
  <Link rel="http://microformats.org/profile/hcard" type="text/html" href="http://identi.ca/testkoski/hcard"/>
  <Link rel="http://gmpg.org/xfn/11" type="text/html" href="http://identi.ca/user/209172"/>
  <Link rel="describedby" type="application/rdf+xml" href="http://identi.ca/testkoski/foaf"/>
  <Link rel="salmon" href="http://identi.ca/main/salmon/user/209172"/>
  <Link rel="http://salmon-protocol.org/ns/salmon-replies" href="http://identi.ca/main/salmon/user/209172"/>
  <Link rel="http://salmon-protocol.org/ns/salmon-mention" href="http://identi.ca/main/salmon/user/209172"/>
  <Link rel="magic-public-key" href="data:application/magic-public-key,RSA.hNo0yCdfxmx2oFRQQ7J2Qps8b9DEoGL6MEoYSBIt1JXC08Wpl_D1BiYMRtkOvfoB9h1xJA-yoYZZAYDch3UR-XzNy2PLxvDUFOXaMguyTTTF6x4cY9HWZF71iQo1oN5x5C3PSOxiKNTZ1-IYCMdInszr_oFWbbFuDg77VqfpNMk=.AQAB"/>
  <Link rel="http://ostatus.org/schema/1.0/subscribe" template="http://identi.ca/main/ostatussub?profile={uri}"/>
</XRD>

This time we got much bigger XML with much more info in it. First thing we do is to remember the values of the Subject and the Alias -elements. We'll use them later. We also got lots of links that can be used to create all kind of cool user experiences. However in this example we are only interested to find the Test Koski's microblog feed, it's Pubsubhubbub's hub so that we can subscribe to it and a salmon endpoint so that we can notify the user that we are "following" him. So we just get the following links and remember them:

  • Salmon endpoint (Link with rel='samon') from the fetched LRDD:
<Link rel="salmon" href="http://identi.ca/main/salmon/user/209172"/>
<Link rel="http://schemas.google.com/g/2010#updates-from" href="http://identi.ca/api/statuses/user_timeline/209172.atom" type="application/atom+xml"/>
  • Microblog's pubsubhubbub hub? Yes, it's not here. We'll fetch is from the feed itself.

Since we miss the hub to perform pubsubhubbub subscription, we fetch the Test Koski's feed:

User A's HTTP(S) request to get the feed:

GET /api/statuses/user_timeline/209172.atom HTTP/1.0
Host: identi.ca

HTTP reply from identi.ca:

HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom" 
            xmlns:thr="http://purl.org/syndication/thread/1.0" 
            xmlns:georss="http://www.georss.org/georss" 
            xmlns:activity="http://activitystrea.ms/spec/1.0/" 
            xmlns:media="http://purl.org/syndication/atommedia" 
            xmlns:poco="http://portablecontacts.net/spec/1.0" 
            xmlns:ostatus="http://ostatus.org/schema/1.0" 
            xmlns:statusnet="http://status.net/schema/api/1/">
  <generator uri="http://status.net" version="0.9.4">StatusNet</generator>
  <id>http://identi.ca/api/statuses/user_timeline/209172.atom</id>
  <title>testkoski timeline</title>
  <subtitle>Updates from testkoski on Identi.ca!</subtitle>
  <logo>http://avatar.identi.ca/209172-96-20100804205939.jpeg</logo>
  <updated>2010-08-22T13:26:16+00:00</updated>
  <author>
    <name>testkoski</name>
    <uri>http://identi.ca/user/209172</uri>
  </author>
  <link href="http://identi.ca/testkoski" rel="alternate" type="text/html"/>
  <link href="http://identi.ca/main/sup#209172" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/>
  <link href="http://identi.ca/main/push/hub" rel="hub"/>
  <link href="http://identi.ca/main/salmon/user/209172" rel="salmon"/>
  <link href="http://identi.ca/main/salmon/user/209172" rel="http://salmon-protocol.org/ns/salmon-replies"/>
  <link href="http://identi.ca/main/salmon/user/209172" rel="http://salmon-protocol.org/ns/salmon-mention"/>
  <link href="http://identi.ca/api/statuses/user_timeline/209172.atom" rel="self" type="application/atom+xml"/>
  <entry>
    <title>test</title>
    <link rel="alternate" type="text/html" href="http://identi.ca/notice/46904698"/>
    <id>http://identi.ca/notice/46904698</id>
    <published>2010-08-21T10:52:23+00:00</published>
    <updated>2010-08-21T10:52:23+00:00</updated>
    <content type="html">This is quite cool.</content>
    <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
    <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
    <statusnet:notice_info local_id="46904698" source="web"></statusnet:notice_info>
    <link rel="ostatus:conversation" href="http://identi.ca/conversation/46543063"/>
  </entry>
</feed>

Part from all other useful information to create a nice user experience, we find the rel="hub" link that we need:

 <link href="http://identi.ca/main/push/hub" rel="hub"/>

User A "PubSubHubbub subscribes" to Test Koski's public feed

Now we are ready to subscribe to the Test Koski's feed "http://identi.ca/api/statuses/user_timeline/209172.atom". There is a good example how to subscribe to pubsubhubbub on Joseph Smarr's subscriber how-to. Following the instructions found at Joseph Smarr's blog post we subscribe to the feed "http://identi.ca/api/statuses/user_timeline/209172.atom" on hub "http://identi.ca/main/push/hub".

User A sends a ActivityStream Atom Entry to Test Koski using Salmon Protocol to notify about the event

After succesfully subscribing to Test Koski's feed, we are ready to inform him that we are "following". We achieve this by using ActivityStreams and salmon protocols.

So we create an ActivityStream as atom entry and send it to Test Koski as a salmon post. Let's first generate the ActivityStream atom representing the "User A follows Test Koski" action:

<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:activity="http://activitystrea.ms/spec/1.0/">
  <id>mimime:1282485236</id>
  <title>User A is now following Tester Koski</title>
  <author>
    <uri>acct:user-a@lobstermonster.org</uri>
    <name>User A</name>
    <link rel="photo" type="image/png" href="http://static.open.salon.com/files/default_avatar1234375017.jpg"/>
    <link rel="alternate" type="text/html" href="http://www.lobstermonster.org/profile/user-a"/>
  </author>
  <activity:actor>
    <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
    <id>http://www.lobstermonster.org/profile/user-a</id>
    <title>User A</title>
    <link rel="alternate" type="text/html" href="http://www.lobstermonster.org/profile/user-a"/>
    <link rel="avatar" type="image/png" href="http://static.open.salon.com/files/default_avatar1234375017.jpg"/>
    <link rel="photo" type="image/png" href="http://static.open.salon.com/files/default_avatar1234375017.jpg"/>
  </activity:actor>
  <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb>
  <activity:object>
    <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
    <title>Tester Koski</title>
    <id>http://identi.ca/user/209172</id>
    <link rel="alternate" type="text/html" href="http://identi.ca/user/209172"/>
    <link rel="photo" type="image/png" href="http://avatar.identi.ca/209172-256-20100804205939.jpeg"/>
  </activity:object>
</entry>

Following the ActivityStream's logic (actor - verb - object) we can notice that the above atom simply says that "the User A (actor) follows (verb) Tester Koski (object)". (The links with rel="photo" and rel="avatar" in the above example are not mandatory.)

Now comes the a bit more "complicated" part. As defined in the Salmon protocol we must sign the payload using Magic Signature protocol.

Trying to explain in short what we need to do:

  1. Take the entry payload, and encode it using the "base64url" encoding (http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-00.html#encoding_details).
  2. Create a signature of the "baes64url encoded entry" as defined in the http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-00.html#signing
  3. Create a magic envelope (http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-00.html#anchor3)
  4. Create a XML Serialization of the magic envelope (http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-00.html#anchor4)

After the 4 steps we should have an XML similar to:

<?xml version="1.0" encoding="UTF-8"?>
<me:env xmlns:me="http://salmon-protocol.org/ns/magic-env">
  <me:data type="application/atom+xml">PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGVudHJ5IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDA1L0F0b20iIHhtbG5zOmFjdGl2aXR5PSJodHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zcGVjLzEuMC8iPgogIDxpZD5taW1pbWU6MTI4MjQ4NTIzNjwvaWQ-CiAgPHRpdGxlPlVzZXIgQSBpcyBub3cgZm9sbG93aW5nIFRlc3RlciBLb3NraTwvdGl0bGU-CiAgPGNvbnRlbnQgdHlwZT0iaHRtbCI-Jmx0O2EgaHJlZj0iaHR0cDovL3d3dy5sb2JzdGVybW9uc3Rlci5vcmcvcHJvZmlsZS91c2VyLWEiJmd0O1VzZXIgQSZsdDsvYSZndDsgaXMgbm93IGZvbGxvd2luZyAmbHQ7YSBocmVmPSJodHRwOi8vaWRlbnRpLmNhL3VzZXIvMjA5MTcyIiZndDtUZXN0ZXIgS29za2kmbHQ7L2EmZ3Q7LjwvY29udGVudD4KICA8YXV0aG9yPgogICAgPHVyaT5hY2N0OnVzZXItYUBsb2JzdGVybW9uc3Rlci5vcmc8L3VyaT4KICAgIDxuYW1lPlVzZXIgQTwvbmFtZT4KICAgIDxsaW5rIHJlbD0icGhvdG8iIHR5cGU9ImltYWdlL3BuZyIgaHJlZj0iaHR0cDovL3N0YXRpYy5vcGVuLnNhbG9uLmNvbS9maWxlcy9kZWZhdWx0X2F2YXRhcjEyMzQzNzUwMTcuanBnIi8-CiAgICA8bGluayByZWw9ImFsdGVybmF0ZSIgdHlwZT0idGV4dC9odG1sIiBocmVmPSJodHRwOi8vd3d3LmxvYnN0ZXJtb25zdGVyLm9yZy9wcm9maWxlL3VzZXItYSIvPgogIDwvYXV0aG9yPgogIDxhY3Rpdml0eTphY3Rvcj4KICAgIDxhY3Rpdml0eTpvYmplY3QtdHlwZT5odHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zY2hlbWEvMS4wL3BlcnNvbjwvYWN0aXZpdHk6b2JqZWN0LXR5cGU-CiAgICA8aWQ-aHR0cDovL3d3dy5sb2JzdGVybW9uc3Rlci5vcmcvcHJvZmlsZS91c2VyLWE8L2lkPgogICAgPHRpdGxlPlVzZXIgQTwvdGl0bGU-CiAgICA8bGluayByZWw9ImFsdGVybmF0ZSIgdHlwZT0idGV4dC9odG1sIiBocmVmPSJodHRwOi8vd3d3LmxvYnN0ZXJtb25zdGVyLm9yZy9wcm9maWxlL3VzZXItYSIvPgogICAgPGxpbmsgcmVsPSJhdmF0YXIiIHR5cGU9ImltYWdlL3BuZyIgaHJlZj0iaHR0cDovL3N0YXRpYy5vcGVuLnNhbG9uLmNvbS9maWxlcy9kZWZhdWx0X2F2YXRhcjEyMzQzNzUwMTcuanBnIi8-CiAgICA8bGluayByZWw9InBob3RvIiB0eXBlPSJpbWFnZS9wbmciIGhyZWY9Imh0dHA6Ly9zdGF0aWMub3Blbi5zYWxvbi5jb20vZmlsZXMvZGVmYXVsdF9hdmF0YXIxMjM0Mzc1MDE3LmpwZyIvPgogIDwvYWN0aXZpdHk6YWN0b3I-CiAgPGFjdGl2aXR5OnZlcmI-aHR0cDovL2FjdGl2aXR5c3RyZWEubXMvc2NoZW1hLzEuMC9mb2xsb3c8L2FjdGl2aXR5OnZlcmI-CiAgPGFjdGl2aXR5Om9iamVjdD4KICAgIDxhY3Rpdml0eTpvYmplY3QtdHlwZT5odHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zY2hlbWEvMS4wL3BlcnNvbjwvYWN0aXZpdHk6b2JqZWN0LXR5cGU-CiAgICA8dGl0bGU-VGVzdGVyIEtvc2tpPC90aXRsZT4KICAgIDxpZD5odHRwOi8vaWRlbnRpLmNhL3VzZXIvMjA5MTcyPC9pZD4KICAgIDxsaW5rIHJlbD0iYWx0ZXJuYXRlIiB0eXBlPSJ0ZXh0L2h0bWwiIGhyZWY9Imh0dHA6Ly9pZGVudGkuY2EvdXNlci8yMDkxNzIiLz4KICAgIDxsaW5rIHJlbD0icGhvdG8iIHR5cGU9ImltYWdlL3BuZyIgaHJlZj0iaHR0cDovL2F2YXRhci5pZGVudGkuY2EvMjA5MTcyLTI1Ni0yMDEwMDgwNDIwNTkzOS5qcGVnIi8-CiAgPC9hY3Rpdml0eTpvYmplY3Q-CjwvZW50cnk-Cg==</me:data>
  <me:encoding>base64url</me:encoding>
  <me:alg>RSA-SHA256</me:alg>
  <me:sig>nbhQ6-IKL_pyZ5v7dEZznBQxnXG2j8bgaPuCkuMn2lUtQs_flS8-X_yPwzLLu6rYlfWjO9cw6b5CKKnfaBWWT-fjEqszOgaFnqenguHcJRIQvPa8Y22L4inhb88TbrtSLaN6ZdBZnGjEOWSHwkH5tL6YxNL5h-Gxm7kYA2RT5Hg=</me:sig>
</me:env>

(todo: fix the above example, the keyhash of the me:sig element in the above example is missing. The examples in the MagicEnvelope specification seems to be wrong too).

Now when we have the ActivityStream Atom entry representing a "follow" action as a Magic Envelope, we can send it to Test Koski. As we remember the Test Koski's salmon endpoint "http://identi.ca/main/salmon/user/209172" from the Test Koski's LRDD we are ready to HTTP POST the Magic Envelope there. When User A POSTs the Magic Envelope to the salmon endpoint, following events occur:

  1. Test Koski receives the Magic Envelope
  2. Test Koski decodes the <me:data> -element from the received Magic Envelope and discovers the Author's URI (acct:user-a@lobstermonster.org)
  3. Test Koski discovers the User A's "magic-public-key" using Webfinger
  4. Test Koski verifies that the Magic Signature is valid
  5. Handles the Atom entry payload

User A's HTTP request to POST the Magic Envelope:

POST /main/salmon/user/209172 HTTP/1.0
Accept: */*
Host: identi.ca
Content-type: application/magic-envelope+xml
Content-Length: 2724

<?xml version="1.0" encoding="UTF-8"?>
<me:env xmlns:me="http://salmon-protocol.org/ns/magic-env">
  <me:data type="application/atom+xml">PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGVudHJ5IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDA1L0F0b20iIHhtbG5zOmFjdGl2aXR5PSJodHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zcGVjLzEuMC8iPgogIDxpZD5taW1pbWU6MTI4MjQ4NTIzNjwvaWQ-CiAgPHRpdGxlPlVzZXIgQSBpcyBub3cgZm9sbG93aW5nIFRlc3RlciBLb3NraTwvdGl0bGU-CiAgPGNvbnRlbnQgdHlwZT0iaHRtbCI-Jmx0O2EgaHJlZj0iaHR0cDovL3d3dy5sb2JzdGVybW9uc3Rlci5vcmcvcHJvZmlsZS91c2VyLWEiJmd0O1VzZXIgQSZsdDsvYSZndDsgaXMgbm93IGZvbGxvd2luZyAmbHQ7YSBocmVmPSJodHRwOi8vaWRlbnRpLmNhL3VzZXIvMjA5MTcyIiZndDtUZXN0ZXIgS29za2kmbHQ7L2EmZ3Q7LjwvY29udGVudD4KICA8YXV0aG9yPgogICAgPHVyaT5hY2N0OnVzZXItYUBsb2JzdGVybW9uc3Rlci5vcmc8L3VyaT4KICAgIDxuYW1lPlVzZXIgQTwvbmFtZT4KICAgIDxsaW5rIHJlbD0icGhvdG8iIHR5cGU9ImltYWdlL3BuZyIgaHJlZj0iaHR0cDovL3N0YXRpYy5vcGVuLnNhbG9uLmNvbS9maWxlcy9kZWZhdWx0X2F2YXRhcjEyMzQzNzUwMTcuanBnIi8-CiAgICA8bGluayByZWw9ImFsdGVybmF0ZSIgdHlwZT0idGV4dC9odG1sIiBocmVmPSJodHRwOi8vd3d3LmxvYnN0ZXJtb25zdGVyLm9yZy9wcm9maWxlL3VzZXItYSIvPgogIDwvYXV0aG9yPgogIDxhY3Rpdml0eTphY3Rvcj4KICAgIDxhY3Rpdml0eTpvYmplY3QtdHlwZT5odHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zY2hlbWEvMS4wL3BlcnNvbjwvYWN0aXZpdHk6b2JqZWN0LXR5cGU-CiAgICA8aWQ-aHR0cDovL3d3dy5sb2JzdGVybW9uc3Rlci5vcmcvcHJvZmlsZS91c2VyLWE8L2lkPgogICAgPHRpdGxlPlVzZXIgQTwvdGl0bGU-CiAgICA8bGluayByZWw9ImFsdGVybmF0ZSIgdHlwZT0idGV4dC9odG1sIiBocmVmPSJodHRwOi8vd3d3LmxvYnN0ZXJtb25zdGVyLm9yZy9wcm9maWxlL3VzZXItYSIvPgogICAgPGxpbmsgcmVsPSJhdmF0YXIiIHR5cGU9ImltYWdlL3BuZyIgaHJlZj0iaHR0cDovL3N0YXRpYy5vcGVuLnNhbG9uLmNvbS9maWxlcy9kZWZhdWx0X2F2YXRhcjEyMzQzNzUwMTcuanBnIi8-CiAgICA8bGluayByZWw9InBob3RvIiB0eXBlPSJpbWFnZS9wbmciIGhyZWY9Imh0dHA6Ly9zdGF0aWMub3Blbi5zYWxvbi5jb20vZmlsZXMvZGVmYXVsdF9hdmF0YXIxMjM0Mzc1MDE3LmpwZyIvPgogIDwvYWN0aXZpdHk6YWN0b3I-CiAgPGFjdGl2aXR5OnZlcmI-aHR0cDovL2FjdGl2aXR5c3RyZWEubXMvc2NoZW1hLzEuMC9mb2xsb3c8L2FjdGl2aXR5OnZlcmI-CiAgPGFjdGl2aXR5Om9iamVjdD4KICAgIDxhY3Rpdml0eTpvYmplY3QtdHlwZT5odHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zY2hlbWEvMS4wL3BlcnNvbjwvYWN0aXZpdHk6b2JqZWN0LXR5cGU-CiAgICA8dGl0bGU-VGVzdGVyIEtvc2tpPC90aXRsZT4KICAgIDxpZD5odHRwOi8vaWRlbnRpLmNhL3VzZXIvMjA5MTcyPC9pZD4KICAgIDxsaW5rIHJlbD0iYWx0ZXJuYXRlIiB0eXBlPSJ0ZXh0L2h0bWwiIGhyZWY9Imh0dHA6Ly9pZGVudGkuY2EvdXNlci8yMDkxNzIiLz4KICAgIDxsaW5rIHJlbD0icGhvdG8iIHR5cGU9ImltYWdlL3BuZyIgaHJlZj0iaHR0cDovL2F2YXRhci5pZGVudGkuY2EvMjA5MTcyLTI1Ni0yMDEwMDgwNDIwNTkzOS5qcGVnIi8-CiAgPC9hY3Rpdml0eTpvYmplY3Q-CjwvZW50cnk-Cg==</me:data>
  <me:encoding>base64url</me:encoding>
  <me:alg>RSA-SHA256</me:alg>
  <me:sig>nbhQ6-IKL_pyZ5v7dEZznBQxnXG2j8bgaPuCkuMn2lUtQs_flS8-X_yPwzLLu6rYlfWjO9cw6b5CKKnfaBWWT-fjEqszOgaFnqenguHcJRIQvPa8Y22L4inhb88TbrtSLaN6ZdBZnGjEOWSHwkH5tL6YxNL5h-Gxm7kYA2RT5Hg=</me:sig>
</me:env>

Test Koski now reads the <me:data> -element's value from the received Magic Envelope and base64url decodes it. The base64url decoded <me:data> value :

<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:activity="http://activitystrea.ms/spec/1.0/">
  <id>mimime:1282485236</id>
  <title>User A is now following Tester Koski</title>
  <author>
    <uri>acct:user-a@lobstermonster.org</uri>
    <name>User A</name>
    <link rel="photo" type="image/png" href="http://static.open.salon.com/files/default_avatar1234375017.jpg"/>
    <link rel="alternate" type="text/html" href="http://www.lobstermonster.org/profile/user-a"/>
  </author>
  <activity:actor>
    <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
    <id>http://www.lobstermonster.org/profile/user-a</id>
    <title>User A</title>
    <link rel="alternate" type="text/html" href="http://www.lobstermonster.org/profile/user-a"/>
    <link rel="avatar" type="image/png" href="http://static.open.salon.com/files/default_avatar1234375017.jpg"/>
    <link rel="photo" type="image/png" href="http://static.open.salon.com/files/default_avatar1234375017.jpg"/>
  </activity:actor>
  <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb>
  <activity:object>
    <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
    <title>Tester Koski</title>
    <id>http://identi.ca/user/209172</id>
    <link rel="alternate" type="text/html" href="http://identi.ca/user/209172"/>
    <link rel="photo" type="image/png" href="http://avatar.identi.ca/209172-256-20100804205939.jpeg"/>
  </activity:object>
</entry>

Test Koski parses the <author><uri> -element's value "acct:user-a@lobstermonster.org" and discovers it's magic-public-key using Webfinger. The "Webfinger" is exactly the same as User A did to "discover" Test Koski.

Test Koski's HTTP request:

GET /.well-known/host-meta HTTP/1.0
Host: lobstermonster.org

HTTP reply from lobstermonster.org:

HTTP/1.1 200 OK
Content-Type: application/xrd+xml

<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0" xmlns:hm="http://host-meta.net/xrd/1.0">
  <hm:Host>lobstermonster.org</hm:Host>
  <Link rel="lrdd" template="http://www.lobstermonster.org/lrdd?uri={uri}">
    <Title>Resource Descriptor</Title>
  </Link>
</XRD>

Test Koski checks the Host value and finds the LRDD's template. Test Koski fills the template and reads User A's LRDD.

Test Koski's HTTP request to fetch User A's LRDD:

GET /lrdd?uri=acct%3Auser-a%40lobstermonster.org HTTP/1.0
Host: www.lobstermonster.org

HTTP reply from www.lobstermonster.org:

HTTP/1.1 200 OK
Content-Type: application/xrd+xml

<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
  <Subject>acct:user-a@lobstermonster.org</Subject>
  <Alias>http://www.lobstermonster.org/profile/user-a</Alias>
  <Link rel="http://webfinger.net/rel/profile-page" href="http://www.lobstermonster.org/profile/user-a" type="text/html"/>
  <Link rel="http://schemas.google.com/g/2010#updates-from" href="http://www.lobstermonster.org/atom/user-a" type="application/atom+xml"/>
  <Link rel="salmon" href="http://www.lobstermonster.org/salmon/user-a"/>
  <Link rel="http://salmon-protocol.org/ns/salmon-replies" href="http://www.lobstermonster.org/salmon/user-a"/>
  <Link rel="http://salmon-protocol.org/ns/salmon-mention" href="http://www.lobstermonster.org/salmon/user-a"/>
  <Link rel="magic-public-key" href="data:application/magic-public-key,RSA.nxlVHoQ084AZI9mAyosCM8Hkj40lAGJOtHP--l9KsDlFFZPaq8PNFQEyoY9iecRfKuB_lT5Q8MpUW1Rz3ZRmdO5zA7awtLmOZJ1B1bAbACBVVKkfCEGFrlX5DkE10LbjDOS22BAJ5Br9tEPO5sIV4zvpqlGECsks6WGp__L1vp8=.AQAB"/>
</XRD>

Now Test Koski can parse the Link with rel="magic-public-key" and get's the href value. He parses the public key from the href value:

RSA.nxlVHoQ084AZI9mAyosCM8Hkj40lAGJOtHP--l9KsDlFFZPaq8PNFQEyoY9iecRfKuB_lT5Q8MpUW1Rz3ZRmdO5zA7awtLmOZJ1B1bAbACBVVKkfCEGFrlX5DkE10LbjDOS22BAJ5Br9tEPO5sIV4zvpqlGECsks6WGp__L1vp8=.AQAB 

Now Test Koski is ready to verify the payload as defined in "http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-00.html#verifying". Test Koski is sure that the Salmon came from User A and can handle the event as he wants.

User A is now subscribed to Test Koski's public feed and informed Test Koski about it. Goal achieved.

Next we check what happens when Test Koski publishes "a note" to his feed and how User A can comment it. To be continued ...