The very nature of WebFinger is experimentation.
This means we are likely to see implementation before a fully baked specification. Since at the moment the various bits and pieces of the protocol are somewhat scattered across multiple drafts, this post will attempt to provide a quick implementer guide for those looking to jump right in and get something working.
Server Side
Providers looking to support the WebFinger protocol need to create two resources, a host-meta file for the domain they wish to enable WebFinger on, and an endpoint (or endpoints) for the XRD documents describing their accounts. A third (and optional for providers) part of the protocol is going to provide DNS support for obtaining host-meta, which right now is proposed as an SRV record, but since it is still not fully baked will be skipped for now.
WebFinger uses the host-meta template mechanism to declare its endpoint, taking the entire account identifier, the acct: URI, as input. For example:
http://example.com/describe?uri={uri}
Once the provider decided on the location of its account XRD endpoints, it should publish that information to clients using its host-meta file. Host-meta is a general purpose, well-known location document that provides metadata information about the host. In this case, it provides information on how to find descriptors for accounts on the host.
The host-meta file is located at /.well-known/host-meta at the root of the domain it is about. For example:
http://example.com/.well-known/host-meta
It must contain the following (it may contain additional child elements, but at this point none are defined):
<?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>example.com</hm:Host> <Link rel='lrdd' template='http://example.com/describe?uri={uri}'> <Title>Resource Descriptor</Title> </Link> </XRD>
Providers must set the <Host> element to match their domain name and ‘template’ to match their WebFinger endpoints structure. The template syntax is very simple. Variable names are placed in ‘{}’ and their value must be percent-encoded when expended. Template authors should make sure that their template results in a compliant URI that is properly encoded.
At this point the only thing left on the server side is to implement the WebFinger user XRD endpoints to return an XRD for each account at the chosen location. The account XRD must include at a minimum:
<?xml version='1.0' encoding='UTF-8'?> <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'> <Subject>acct:joe@example.com</Subject> </XRD>
Which only says that this XRD describes the user account ‘joe@example.com’ and nothing else.The rest of the XRD content for accounts is still very much an open question, but a few ideas being experimented with are demonstrated in this example XRD:
<?xml version='1.0' encoding='UTF-8'?> <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'> <Subject>acct:joe@example.com</Subject> <Alias>http://example.com/profiles/joe</Alias> <Link rel='http://portablecontacts.net/spec/1.0' href='http://example.com/api/people/' /> <Link rel='http://webfinger.net/rel/profile-page' type='text/html' href='http://example.com/profiles/joe' /> <Link rel='http://microformats.org/profile/hcard' type='text/html' href='http://example.com/profiles/joe' /> <Link rel='describedby' type='text/html' href='http://example.com/profiles/joe' /> <Link rel='http://webfinger.net/rel/avatar' href='http://example.com/profiles/joe/photo' /> </XRD>
The <Alias> element indicates an alternative URI the account might be known as. This would typically be an HTTP profile page, email address (prefixed with a mailto: URI scheme), or another account URI. The first link provides the location of the user’s Portable Contacts service. The next three links point to a profile page which has multiple relations to the account (it is its profile, hcard document, etc.). The last is a link to the avatar associated with the account.
This is all very experimental so please feel free to, well, experiment.
Client Side
The client’s first task is to obtain a normalized account identifier. This can be done by asking the end user to manually type in their identifier (usually their email address), or by providing them with a list of providers and a place to enter their username at that provider. The client can also encounter an account URI as a link or where URIs are usually found.
Either way, the client must end up with an account identifier structured as an ‘acct:userinfo@host‘ URI. Note that the acct: URI scheme should not be exposed or expected from end users. It should only be used internally to represent account identifiers. It can be used in documents as links to indicate ownership or a relationship to someone. Once that is obtained, the client performs the following steps:
- Parse the account URI and identify the host name.
- Obtain the host-meta file for the host at http://host/.well-known/host-meta using an HTTP GET request. The client must obey HTTP redirection (3xx) and should only use a document received with a success result code (2xx). This is where a DNS query will be added once it is figured out.
- Ensure that the host-meta has a matching <Host> element for the requested host. This will become more important when we add trust and signatures to the protocol.
- Find the first <Link> element that has a ‘rel’ attribute with a value of ‘lrdd’. Get the ‘template’ attribute from that <Link>.
- Substitute the template variable ‘{uri}’ with the full account URI (including the ‘acct:’ scheme) after percent-encoding it.
- Fetch the account XRD by making an HTTP GET request to the URI generated by the template.
At this point the client looks for whatever data it understands and can use in the XRD. See above for ideas on what can be found in account XRD documents.
Updates
12/11
- Replaced relation type ‘http://lrdd.net/rel/descriptor’ with ‘lrdd’ which will be submitted for registration with the LRDD specification.
11/26
- Updated to the latest XRD and host-meta schemas which include a simpler template vocabulary and syntax.
- Changed the relation type to LRDD ‘http://lrdd.net/rel/descriptor’.
- Changed template to take the full account URI including scheme.
9/17
- Replaced the WebFinger rel value in host-meta from ‘http://webfinger.info/rel/service’ to ‘http://webfinger.net/rel/acct-desc’ and added a title.
- Switched to use webfinger.net instead of webfinger.info
- Changed the account XRD example to include a link to an avatar.
- Replaced the {id} variable with {uri}.
9/10
- Merged the webfinger and describedby links in host-meta into a single Link. We are still debating which one to use. If we use describedby alone, we will need to switch to use {%uri} instead of {%id}.
- Remove the foo user example link.
So I have one question regarding those URITemplates. In the host-meta of Google we see http://www.google.com/s2/webfinger/?q={%id}. How do I know the semantics of it? Is this defined for the Rel value being used? (then it’s wrong in the Google example as it’s also being used for describedby)
I got this problem when trying to write a more general discovery service which of course cannot know about all possible template paramaters and thus needs some way of selecting the right “plugin” which can convert the template to a proper URI.
In general, the rel value defines the vocabulary of the template. In the case of host-meta, the host-meta specification will define a basic default set and allow relations to override it.
Was the -tag (you mentioned in one of your first xrd-posts: http://hueniverse.com/2009/03/the-xrd-extensibility-model/ ) replaced by the tag?
What tag? I am not sure what you mean.
Thanks for the answer! I have another question: If there are multiple URIs or templates defined in the XRD, what is the best practice to choose one. Do I simply take the first one, check if it’s working and if not go to the next one?
And Matthias lost some tag-markup I think as it was filtered out 😉
The XRI TC is currently considering allowing only a single URI or URITemplate for each link. Either way, you should pick links based on them matching your criteria in the order they are presented in the file. If the first fails, you should try the second and so on. These are normative SHOULD in the spec.
http://eaut.org/
In this description, it would be useful to how a provider can delegate an email address to a third-party provider, like myopenid.com.
Is there a list of commonly-used rel values? I’m starting to put together webfinger data for my users I’m having trouble finding a reference for stuff I should actually put in the descriptor file.
Not really. Most people copy over the Gmail example.