#1034 new
warren.strange (at gmail)

OpenID 2.0 - XRDS discovery handling

Reported by warren.strange (at gmail) | August 11th, 2011 @ 09:18 PM

Framework version: 1.2.2
Platform you're using: Ubuntu

Problem: Play! OpenID support will not authenticate correctly against Oracle OIF Provider. It does not parse the XRDS doc correctly.

I discussed this with the Oracle engineer and he thinks that OIF behavior is OK - so this may be an error in the Play OpenID code.

See the detailed email exchange below:

Response from OIF engineer:

I think OIF is ok:

  • If OP Identifier is not found, then Claimed Identifier is searched
  • Having found the Claimed  Identifier, the local ID is *optional*

The Play! Code does not seem to handle that use case: if server is null, then it should use the URL that was provided to download the XRDS, as that URL is the OP Identifier (7.3.1)

From: Warren Strange

Hmmmm... Looking through the spec, I interpret this to imply the OIF server response is not quite right.

See: OpenID Service Elements

TOC OP Identifier Element

An OP Identifier Element is an <xrd:Service> element with the following information:

An <xrd:Type> tag whose text content is "http://specs.openid.net/auth/2.0/server".
An <xrd:URI> tag whose text content is the OP Endpoint URL Claimed Identifier Element

A Claimed Identifier Element is an <xrd:Service> element with the following information:

An <xrd:Type> tag whose text content is "http://specs.openid.net/auth/2.0/signon".
An <xrd:URI> tag whose text content is the OP Endpoint URL.  

An <xrd:LocalID> tag (optional) whose text content is the OP-Local Identifier. Extracting Authentication Data

Once the Relying Party has obtained an XRDS document, it MUST first search the document (following the rules described in [XRI_Resolution_2.0]) for an OP Identifier Element. If none is found, the RP will search for a Claimed Identifier Element.

In the OIF response below, there is no OP identifier ( /server is missing), so that would imply there must be a Claimed identifier - but the response is also missing the LocalID tag.

Or I am misreading the spec....

On 11-08-11 01:00 PM, Warren Strange wrote:


I have a sample Play! app that is not authenticating properly against OIF. I am trying to figure out if it is the Play implementation that is faulty, or OIF is returning something it shouldn't. I have traced it down to the relevant section:

Here is what OIF returns as the XRDS doc:

<?xml version="1.0" standalone="yes" ?>
<xrds:XRDS xmlns="xri://$xrd($v2.0)" xmlns:openid="http://openid.net/xmlns/1.0" xmlns:xrds="xri://$xrds">



And here is what the Play! implementation does.

server = XPath.selectText("//Type[text()='http://specs.openid.net/auth/2.0/server']/following-sibling::URI/te..., xrds);
claimedId = XPath.selectText("//Type[text()='http://specs.openid.net/auth/2.0/signon']/following-sibling::LocalI..., xrds);
if (claimedId == null) {

claimedId = "http://specs.openid.net/auth/2.0/identifier_select";

} else {

server = XPath.selectText("//Type[text()='http://specs.openid.net/auth/2.0/signon']/following-sibling::URI/text()", xrds);


if (server == null) {

return false;

The problem is that "server" ends up being null and the authentication fails. So either their XPath selection is wrong, or OIF is not quite returning the right thing. It looks like they are expecting "http://specs.openid.net/auth/2.0/server'" in the XRDS document. Should it be there?

Comments and changes to this ticket

  • Art McBain

    Art McBain March 19th, 2012 @ 12:24 AM

    • Tag changed from openid xrds discovery to openid xrds discovery, openid

    I also found a server that only returns a Claimed Identifier Element. I believe the returned XRDS is correct based on the spec (as cited above). Play seems to handle it in the manner above: deciding the server is null and thus failing the auth.

    The XPath is correct, the problem I see is the following if is bad. The following (it seems to me) would work better:

    server = by way of "http://specs.openid.net/auth/2.0/server" + URI
    claimedId = "http://specs.openid.net/auth/2.0/signon" + LocalID
    if not server:
      server = by way of "http://specs.openid.net/auth/2.0/signon" + URI
      claimedId = "http://specs.openid.net/auth/2.0/identifier_select"
    if not server

    I've tried the above with the server returning only the Claimed Identifier Element and Google, works in both places. Perhaps someone with better understanding of the OpenID 2.0 spec can weigh in.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2>Play framework</h2>

Play makes it easier to build Web applications with Java. It is a clean alternative to bloated Enterprise Java stacks. It focuses on developer productivity and targets RESTful architectures. Learn more on the <a href="http://www.playframework.org">http://www.playframework.org</a> website.<br><br>

<h2>Source code is hosted on github</h2>Check out our repository at <a href="http://github.com/playframework/play">http://github.com/playframework/play</a><br><br>

<h2>Contributing, creating a patch</h2> Please read the <a href="http://play.lighthouseapp.com/projects/57987/contributor-guide">contributor guide</a><br><br>

<h2>Reporting Security Vulnerabilities</h2> Since all bug reports are public, please report any security vulnerability directly to <em>guillaume dot bort at gmail dot com</em>.<br><br>

<h2>Creating a bug report</h2> Bug reports are incredibly helpful, so take time to report bugs and request features in our ticket tracker. We’re always grateful for patches to Play’s code. Indeed, bug reports with attached patches will get fixed far quickly than those without any.<br><br>

Please include as much relevant information as possible including the exact framework version you're using and a code snippet that reproduces the problem.<br><br>

Don't have too much expectations. Unless the bug is really a serious "everything is broken" thing, you're creating a ticket to start a discussion. Having a patch (or a branch on Github we can pull from) is better, but then again we'll only pull high quality branches that make sense to be in the core of Play.