Question

I've searched the site but can't find anything that exactly matches this situation.

Cliff's Notes:

Trying to implement Federated login on GAE, using the sample python code at https://developers.google.com/appengine/docs/python/users/, with a custom OpenID Provider. GAE returns either at HTTP 500 or HTTP 204 depending on the server setup. There are no entries in the application logs on the admin console. Most likely it is a problem to do with the XRDS file and the discovery process. I'd appreciate any suggestions as to a cause or possible debugging methods. Thanks in advance.

Problem Details:

The code works fine when using the following providers in the 'federated_identity' parameter of the users.create_login_url() function:

  • https://www.google.com/accounts/o8/id
  • yahoo.com
  • aol.com
  • myopenid.com

The issues start when trying to use our own custom OpenID Provider. We have set up the OpenID plugin on a couple of Wordpress installs on different hosts for testing purposes. The plugin makes use of XRDS-Simple to publish the XRDS document at domain.com/?xrds. Example document contents:

<?xml version="1.0" encoding="UTF-8" ?>
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)" xmlns:simple="http://xrds-simple.net/core/1.0" xmlns:openid="http://openid.net/xmlns/1.0">
<XRD xml:id="main" version="2.0">
    <Type>xri://$xrds*simple</Type>

    <!-- OpenID Consumer Service -->
    <Service priority="10">
        <Type>http://specs.openid.net/auth/2.0/return_to</Type>
        <URI>https://goff.wpengine.com/index.php/openid/consumer</URI>
    </Service>

    <!-- OpenID Provider Service (0) -->
    <Service priority="0">
        <Type>http://specs.openid.net/auth/2.0/server</Type>
        <URI>https://goff.wpengine.com/index.php/openid/server</URI>
        <LocalID>http://specs.openid.net/auth/2.0/identifier_select</LocalID>
    </Service>

    <!-- AtomPub Service -->
    <Service priority="10">
        <Type>http://www.w3.org/2007/app</Type>
        <MediaType>application/atomsvc+xml</MediaType>
        <URI>https://goff.wpengine.com/wp-app.php/service</URI>
    </Service>
</XRD>

I have verified that the OpenID provider works by using it to log in to other OpenID enabled sites, including other Wordpress installs with the OpenID plugin and Stackoverflow.

When using the login link http://api.lighthouseuk.net/_ah/login_redir?claimid=https://goff.wpengine.com/?xrds&continue=http://api.lighthouseuk.net/ GAE returns a HTTP 500 error after several seconds. We haven't found any reason for this - there are no log entries in the admin console - but I suspect it may have something to do with the configuration on wpengine.com not returning the XRDS file or caching an incorrect one.
We have semi-confirmed this by running an identical setup on our dev server which has no caching enabled. Now when we visit the login link GAE returns a HTTP 302 response followed by a HTTP 204 response: http://www.google.com/gen_204?reason=EmptyURL.

As far as I can tell, after requesting the XRDS file GAE makes no further requests to our server. This leads me to believe that there might be a problem with the XRDS file but I can't find any details in the documentation about required attributes.

Things tried:

Login on other systems

If you send an authentication request to the URI specified in the XRDS document the OpenID server responds correctly by prompting the user to log in. Again this suggests that GAE takes issues with the XRDS file because no authentication request is made to our server. I can't figure out how to debug it when there are no errors recorded in the logs.
e.g. https://goff.wpengine.com/openid/server?openid.ns=http://specs.openid.net/auth/2.0&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&openid.identity=http://specs.openid.net/auth/2.0/identifier_select &openid.return_to=http://api.lighthouseuk.net/checkauth&openid.realm=http://api.lighthouseuk.net/&openid.mode=checkid_setup

SSL

Obviously for a production environment we would be using SSL on both Wordpress and GAE but currently this is just a proof of concept. cURL, by default I believe, attempts to check the validity of SSL certificates so we've tried various combinations of SSL setting, including having none at all. Seemingly no effect.

Wordpress permalinks

As the XRDS document, by default, points to /index.php/openid/server/ we attempted different combinations of permalink setting in Wordpress to see if it had any effect. It didn't.

URL encode

URL encoding the claimid seemed to have no effect - we still received the HTTP 204 response.

Was it helpful?

Solution

After giving up for a while I revisited this issue and managed to solve it. Answering here in case anyone else faces the same issues. Ultimately it was down to my use of secure URLs.

TL;DR

It should have been the first thing I checked but, make sure you have an SSL certificate on your server so that the OpenID server is accessible via a secure URL. You will get a HTTP 500 error from GAE if the URL is not secure or if the SSL certificate does not validate (Obvious in hindsight but, this caught me out on a different test site with a custom generated SSL certificate).
In addition, make sure that the XRDS document contains said secure address in the <URI> element.

Setup Details

  • Using OpenID plugin Version 3.3.4
  • Using XRDS-Simple plugin Version 1.1
  • Wordpress version 3.8
  • Hosted on WPEngine.com
  • Google App Engine instance running the gae-boilerplate code (federated identity enabled)

Modifications

I played around with fiddler2 to see if I could learn anything more about the requests made to and from GAE. I compared the access logs from my OpenID server on WPEngine with the data I could pull from fiddler2 about the stackexchange OpenID server (openid.stackexchange.com).

XRDS-Simple Plugin

I modified this plugin to include an additional filter for the Wordpress HTTP headers:

add_filter('wp_headers', 'xrds_add_xrds_location');

function xrds_add_xrds_location($headers) {
    error_log('Adding XRDS header', 0);
    $headers['X-XRDS-Location'] = get_bloginfo('url').'/?xrds';
    return $headers;
}

After that I modified the xrds_write() function to simply return the following xml:

<?xml version="1.0" encoding="UTF-8"?>
            <xrds:XRDS
                xmlns:xrds="xri://$xrds"
                xmlns:openid="http://openid.net/xmlns/1.0"
                xmlns="xri://$xrd*($v*2.0)">
                <XRD>
                    <Service priority="10">
                        <Type>http://specs.openid.net/auth/2.0/server</Type>
                        <Type>http://openid.net/extensions/sreg/1.1</Type>
                        <Type>http://axschema.org/contact/email</Type>



                        <URI>http://goff.wpengine.com/index.php/openid/server</URI>
                    </Service>
                </XRD>
            </xrds:XRDS>

This got rid of the http://www.google.com/gen_204?reason=EmptyURL redirect and simply returned a HTTP 500 error.
Curious, I tried various different things to get any response out of GAE (remember GAE does not show error that occur in the /_ah/ handlers.
As a last resort I modified the <URI> element to be https instead of http. This did the trick! I was successfully redirected to goff.wpengine.com and was asked to verify that I wanted to login. Excited, I clicked verify. PHP Fatal error: Call to a member function needsSigning() on a non-object. Balls. At least now I could ascertain problems from the PHP error log.

OpenID Plugin

After some quick Googling I found a thread on Google Code for the OpenID plugin. People had had similar issues and the consensus was that it was due to a plugin conflict. Comment #55 from user infinite.alis mentioned that adding the Relying Party to the user's 'Trusted Sites' consistently solved the problem. Lo and behold, after adding the address to my trusted sites the entire authentication flow completed without error!

Conclusion

I have yet to do a post mortem to figure out which of the changes to XRDS-Simple made the difference. I suspect that simply changing the <URI> element in XRDS-Simple to https would solve the problem (My previous tests with SSL only focused on making sure the users.create_login_url() function was passed a secure address, not that the XRDS file described the OpenID server via a secure address). Possibly need to play around with the filters for get_bloginfo('url') in the xrds_write() function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top