This document describes how to support YADIS service discovery using only Apache configuration. This is desirable because it makes your YADIS identity URL faster and more reliable to use, and it doesn't require running any code on your server.
If you are a quick study at configuring Apache, you can get your identity URL configured by:
mod_rewrite
,
mod_negotiation
, and mod_headers
are
enabled in your server-level configuration, and that
RewriteEngine On
appears in your server-level
(not just .htaccess
) configuration.
.htaccess
and type map files.
.htaccess
and type map files to match
your server configuration. The type map file should be where
you want your identity URL to be.
This configuration is for Apache 2.0. It has not been tested, but this configuration should also work for Apache 1.3 and 2.2.
The configuration for the identity URL is achieved using
.htaccess
directives using the standard Apache
modules mod_negotiation
and mod_headers
.
These directives will also work with some small changes if they
are put in a <Directory>
section of the server-level
configuration. Experiment and have fun.
There are minimal server-level requirements for the
configuration described here. Most of the configuration is in a
.htaccess
file. For this configuration to work, you
need configuration like the following:
# Change the paths to match your server configuration. LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so RewriteEngine On
mod_negotiation
is compiled into most Apache
configurations by default, but make sure that it's enabled.
This directory contains the following files:
identity
.htaccess
home.html
yadis.xml
The following (relative) URLs will be served by Apache:
identity
yadis.xml
Adding a header is trivially supported by the Header directive. The scope of the directive is set to only the URL that is to be used as the identity.
The directive is as follows:
<Files identity_url_content_name> # Add the X-YADIS-Location header to the response if the response # is a 200 Header onsuccess set X-YADIS-Location http://my-web-site.example.com/yadis.xml </Files>
At this point, the URL can be used as an identity URL by any compliant relying party, with no further configuration. The content negotiation step is an optimization that will make it faster to use your identity URL, but can be omitted.
If you are using only this configuration, then
identity_url_content_name
is the file that you want
to be served for your identity URL. For other configurations,
read on.
The YADIS services document is of type
application/xrds+xml
. In order for content
negotiation to work, the content type must be set correctly in
the HTTP response headers. It is also a good idea to set the
content type even if you are not using content negotiation so
that the client knows how to treat the file in general.
We force apache to use the correct content type with this configuration:
<Files yadis.xml> # Make sure that Apache serves the YADIS services document as the # correct content-type. ForceType application/xrds+xml </Files>
If you are using content negotiation, you will need to create an Apache type-map file indicating the locations of the documents to use when different content-types are requested. There are two requirements for using this system with YADIS. First, any content that is returned that is not a YADIS services document must have the X-YADIS-Location header set. Second, the YADIS services document must be returned with the proper content-type.
Those requirements are taken care of by the preceeding two configuration snippets, so all that is left is to set up the type map.
The simplest usable type map is a file with the following contents:
Content-Type: application/xrds+xml; qs=0.8 URI: yadis.xml Content-Type: */*; qs=0.9 URI: identity_url_content_name
To use this type-map, you need to put the file in your directory and tell apache that it is a type-map:
<Files type_map_name> # Tell apache that this file is a type-map that should be handled # by mod_negotiation SetHandler type-map </Files>
In this configuration, identity_url_content_name
should be the file that contains the content that you
want displayed for regular requests for your identity URL and
type_map_name
should be the name that you want to
use for your identity URL.
There is one more wrinkle. Because the content must be available to Apache and the type-map also points to the same URL internally, there are now two URLs that are usable as identity URLs. This is OK, but to reduce confusion, there is one more configuration trick in the file. This trick makes direct requests for the content URL to redirect to the identity URL:
# Don't allow direct access to the .html file, so that there's no # confusion about which one is the idenity URL. This redirect means # that no matter which of the direct content URL or the desired # identity URL is entered, only the desired identity URL will be used # by YADIS consumers. RewriteEngine On # In order for this test to succeed, RewriteEngine must be turned On # in the site-wide apache configuration. Unless it is, the SCRIPT_URL # variable will not be set. RewriteCond "%{ENV:SCRIPT_URL}" "^server_relative_content_url$" # Redirect requests for the non-YADIS content to the identity URL. RewriteRule "^server_relative_content_url$" "server_relative_identity_url" [R,L]
You can test your configuration with any tool that will retrieve
a URL and show you redirects and headers. We used wget
.
Retrieve the YADIS services document and make sure that the
response has the correct Content-Type
header.
$ wget -S http://openidenabled.com/yadis-test/apache/yadis.xml --14:12:50-- http://openidenabled.com/yadis-test/apache/yadis.xml => `yadis.xml' Resolving openidenabled.com... 67.137.230.70 Connecting to openidenabled.com|67.137.230.70|:80... connected. HTTP request sent, awaiting response... HTTP/1.1 200 OK Date: Wed, 07 Dec 2005 22:12:50 GMT Server: Apache/2.0.54 (Debian GNU/Linux) Last-Modified: Wed, 07 Dec 2005 19:46:48 GMT ETag: "f0074-130-69a95a00" Accept-Ranges: bytes Content-Length: 304 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: application/xrds+xml Length: 304 [application/xrds+xml] 100%[====================================>] 304 --.--K/s 14:12:50 (10.74 MB/s) - `yadis.xml' saved [304/304]
Make sure that the Content-Type
header is set to
application/xrds+xml
.
Retrieve the identity URL and make sure that the header pointing to the YADIS services document is correct.
$ wget -S http://openidenabled.com/yadis-test/apache/identity --14:16:41-- http://openidenabled.com/yadis-test/apache/identity => `identity' Resolving openidenabled.com... 67.137.230.70 Connecting to openidenabled.com|67.137.230.70|:80... connected. HTTP request sent, awaiting response... HTTP/1.1 200 OK Date: Wed, 07 Dec 2005 22:16:41 GMT Server: Apache/2.0.54 (Debian GNU/Linux) Content-Location: home.html Vary: negotiate,accept TCN: choice Last-Modified: Wed, 07 Dec 2005 21:56:26 GMT ETag: "f0079-1eeb-39443680;f0077-64-3a93e800" Accept-Ranges: bytes Content-Length: 7915 X-YADIS-Location: http://openidenabled.com/yadis-test/apache/yadis.xml Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html Expires: Wed, 07 Dec 2005 22:16:41 GMT Length: 7,915 (7.7K) [text/html] 100%[====================================>] 7,915 --.--K/s 14:16:41 (85.98 KB/s) - `identity' saved [7915/7915]
Check to see that the X-YADIS-Location
header is
present and contains the URL to your YADIS services document.
Retrieve the content URL and look for a redirect to the identity URL.
$ wget -S http://openidenabled.com/yadis-test/apache/home.html --14:20:35-- http://openidenabled.com/yadis-test/apache/home.html => `home.html' Resolving openidenabled.com... 67.137.230.70 Connecting to openidenabled.com|67.137.230.70|:80... connected. HTTP request sent, awaiting response... HTTP/1.1 302 Found Date: Wed, 07 Dec 2005 22:20:35 GMT Server: Apache/2.0.54 (Debian GNU/Linux) Location: http://openidenabled.com/yadis-test/apache/identity Content-Length: 235 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html; charset=iso-8859-1 Location: http://openidenabled.com/yadis-test/apache/identity [following] --14:20:35-- http://openidenabled.com/yadis-test/apache/identity => `identity' Reusing existing connection to openidenabled.com:80. HTTP request sent, awaiting response... HTTP/1.1 200 OK Date: Wed, 07 Dec 2005 22:20:35 GMT Server: Apache/2.0.54 (Debian GNU/Linux) Content-Location: home.html Vary: negotiate,accept TCN: choice Last-Modified: Wed, 07 Dec 2005 21:56:26 GMT ETag: "f0079-1eeb-39443680;f0077-64-3a93e800" Accept-Ranges: bytes Content-Length: 7915 X-YADIS-Location: http://openidenabled.com/yadis-test/apache/yadis.xml Keep-Alive: timeout=15, max=99 Connection: Keep-Alive Content-Type: text/html Expires: Wed, 07 Dec 2005 22:20:35 GMT Length: 7,915 (7.7K) [text/html] 100%[====================================>] 7,915 40.82K/s 14:20:35 (40.72 KB/s) - `identity' saved [7915/7915]
Check that there is a redirect to your identity URL and that the redirected URL has the YADIS header present.
Retrieve the identity URL with an Accept
header
that indicates a preference for
application/xrds+xml
.
$ wget --header="Accept: application/xrds+xml; q=1, text/html; q=0.9" \ -S http://openidenabled.com/yadis-test/apache/identity --14:25:45-- http://openidenabled.com/yadis-test/apache/identity => `identity' Resolving openidenabled.com... 67.137.230.70 Connecting to openidenabled.com|67.137.230.70|:80... connected. HTTP request sent, awaiting response... HTTP/1.1 200 OK Date: Wed, 07 Dec 2005 22:25:45 GMT Server: Apache/2.0.54 (Debian GNU/Linux) Content-Location: yadis.xml Vary: negotiate,accept TCN: choice Last-Modified: Wed, 07 Dec 2005 19:46:48 GMT ETag: "f0074-130-69a95a00;f0077-64-3a93e800" Accept-Ranges: bytes Content-Length: 304 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: application/xrds+xml Expires: Wed, 07 Dec 2005 22:25:45 GMT Length: 304 [application/xrds+xml] 100%[====================================>] 304 --.--K/s 14:25:45 (10.74 MB/s) - `identity' saved [304/304]
Check that the Content-Type
is
application/xrds+xml
. Also look at the contents of
the file to make sure that it contains the XRDS file.
Copyright (c) 2005 JanRain, Inc.