<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SteveLove.org &#187; openid</title>
	<atom:link href="http://stevelove.org/tag/openid/feed/" rel="self" type="application/rss+xml" />
	<link>http://stevelove.org</link>
	<description>Code, Literature and Other Worthless Pursuits</description>
	<lastBuildDate>Mon, 28 Jun 2010 21:53:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Saying good bye to OpenID</title>
		<link>http://stevelove.org/2010/01/06/saying-good-bye-to-openid/</link>
		<comments>http://stevelove.org/2010/01/06/saying-good-bye-to-openid/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 17:49:05 +0000</pubDate>
		<dc:creator>Steve Love</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://stevelove.org/?p=141</guid>
		<description><![CDATA[For the last several months I've been intending to announce that I'm no longer going to be doing any development on Dope OpenID. Today's announcement of the PHPClasses Zeitgeist was the kick in the pants I needed.]]></description>
			<content:encoded><![CDATA[<p>When I started digging in to OpenID a couple years ago, it was only because someone in the company&#8217;s marketing department thought it sounded cool and therefore we needed it on our Web site.<span id="more-141"></span></p>
<p>At that time, I&#8217;d only ever set up a personal OpenID endpoint so I started looking around on what it would take to become an OpenID consumer in order to authenticate our users. After trying various things, I settled on the <a href="http://www.phpclasses.org/browse/package/3290.html">Simple OpenID class</a> that I found on <a href="http://www.phpclasses.org">PHPClasses.org</a>. The only problem was that it wasn&#8217;t OpenID 2.0 compliant, and therefore wouldn&#8217;t work with Yahoo. So I worked my way through the OpenID specifications and got it functioning the way I wanted, even releasing the new code as <a href="/projects/dope-openid">Dope OpenID</a>. Still, we never saw more than a few hundred people taking advantage of OpenID on our site (out of a million or so active users).</p>
<p>Since then, all I can say is that OpenID has become significantly less exciting. I haven&#8217;t updated the code in a long while, though someone will occasionally post a modification in the comments. I actually <a href="http://github.com/stevelove/Dope-OpenID">put the source up on GitHub</a> hoping the modifications would get merged in that way.</p>
<p>Anyway, all that to say for the last several months I&#8217;ve been intending to announce that I&#8217;m no longer going to be doing any development on Dope OpenID. Today&#8217;s announcement of the <a href="http://www.phpclasses.org/zeitgeist">PHPClasses Zeitgeist</a> was the kick in the pants I needed. While OpenID was the <a href="http://www.phpclasses.org/zeitgeist/year/2007/">top search on PHPClasses in 2007</a>, it didn&#8217;t even make the list in 2008 or 2009. In my opinion, the average user still has no idea what OpenID is and they&#8217;re just more trusting of things that sound familiar to them, like Facebook Connect.</p>
<p>So, to sum up, I&#8217;m no longer doing any development on Dope OpenID. I will leave the project page up for a while and continue to allow comments, but I&#8217;d much rather let someone else take over the project if they have an interest in it. Or else just fork it on GitHub.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevelove.org/2010/01/06/saying-good-bye-to-openid/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dope OpenID 1.0.1 released</title>
		<link>http://stevelove.org/2009/07/08/dope-openid-1-0-1-released/</link>
		<comments>http://stevelove.org/2009/07/08/dope-openid-1-0-1-released/#comments</comments>
		<pubDate>Thu, 09 Jul 2009 02:31:50 +0000</pubDate>
		<dc:creator>Steve Love</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[attribute exchange]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://stevelove.org/?p=107</guid>
		<description><![CDATA[Late last night I pushed out an update for Dope OpenID to add better support for Attribute Exchange with Google and other providers. You can download the latest version right now from the project page. In addition, because Dope OpenID is an open source project, I&#8217;ve made the source code available on github. Collaborators are [...]]]></description>
			<content:encoded><![CDATA[<p>Late last night I pushed out an update for Dope OpenID to add better support for Attribute Exchange with Google and other providers. You can download the latest version right now from the <a href="http://stevelove.org/projects/dope-openid/">project page</a>.</p>
<p>In addition, because Dope OpenID is an open source project, I&#8217;ve made the source code available on <a href="http://github.com/stevelove/Dope-OpenID/tree/master">github</a>. Collaborators are welcome! Or take the code and go in a completely different direction.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevelove.org/2009/07/08/dope-openid-1-0-1-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple OpenID updated: Now supports Google accounts and Attribute Exchange</title>
		<link>http://stevelove.org/2008/12/21/simple-openid-updated-now-supports-google-accounts-and-attribute-exchange/</link>
		<comments>http://stevelove.org/2008/12/21/simple-openid-updated-now-supports-google-accounts-and-attribute-exchange/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 03:12:36 +0000</pubDate>
		<dc:creator>Steve Love</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[attribute exchange]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://stevelove.org/?p=21</guid>
		<description><![CDATA[At the request of a reader, I&#8217;ve updated Simple OpenID by adding support for Google&#8217;s OpenID implementation for Gmail users, as well as some other changes. Download the latest version here. After a couple months, Google is finally publishing its XRDS document (like Yahoo does) from www.gmail.com. So what I&#8217;ve done is add a line [...]]]></description>
			<content:encoded><![CDATA[<p>At the request of a reader, I&#8217;ve updated Simple OpenID by adding support for Google&#8217;s OpenID implementation for Gmail users, as well as some other changes. Download the latest version <a href="http://stevelove.org/projects/dope-openid/">here</a>.<span id="more-21"></span></p>
<p>After a couple months, Google is finally publishing its XRDS document (like Yahoo does) from www.gmail.com. So what I&#8217;ve done is add a line that checks for &#8220;google&#8221; or &#8220;gmail&#8221; in the user&#8217;s OpenID, and if found, standardizes the input as &#8220;http://gmail.com&#8221;, at which point we can use Yadis to discover the server location. I implemented it this way because I figure users might be confused whether their provider URL is &#8220;http://google.com&#8221; or &#8220;http://gmail.com&#8221;. As an added bonus, it also allows people to enter &#8220;username@gmail.com&#8221; and it will still work. I don&#8217;t know of any clear guidelines on this, so if anyone knows of a better way to implement it, please let me know.</p>
<p>This brings us to Attribute Exchange (AX) and Simple Registration (SREG) info. Simple OpenID now supports both. Just use the <span class="code">SetRequiredFields</span> and <span class="code">SetOptionalFields</span> methods as before. Some OpenID providers use AX info, some use SREG, and some ignore both. Google, for example, will only return the user&#8217;s email address, and only if you specify it as a required field.</p>
<p>Other changes: I&#8217;ve added the ability to set PAPE auth policies and a time limit on authentication (max_auth_age). I haven&#8217;t tested these to see if they work though. If you&#8217;re interested, try it out and let me know the results. I commented out the section that deals with standardizing XRI strings after I noticed it&#8217;s only half implemented. I&#8217;ll work on both of these parts as time permits.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevelove.org/2008/12/21/simple-openid-updated-now-supports-google-accounts-and-attribute-exchange/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: WordPress.com and the Simple OpenID PHP Class</title>
		<link>http://stevelove.org/2008/08/25/how-to-wordpresscom-and-the-simple-openid-php-class/</link>
		<comments>http://stevelove.org/2008/08/25/how-to-wordpresscom-and-the-simple-openid-php-class/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 02:22:29 +0000</pubDate>
		<dc:creator>Steve Love</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://stevelove.org/?p=19</guid>
		<description><![CDATA[[Note: This post contains outdated information. Please visit the project page here for the latest information.] In my previous post, I told you how to get the Simple OpenID PHP Class working with Yahoo. Now we&#8217;re going to focus on WordPress.com. This turned out to be very easy once I realized the problem. The Problem: [...]]]></description>
			<content:encoded><![CDATA[<p><big><b>[Note: This post contains outdated information. Please visit the project page <a href="http://stevelove.org/projects/dope-openid/">here</a> for the latest information.]</b></big></p>
<p>In my <a href="http://www.stevelove.org/2008/08/how-to-yahoo-and-the-simple-openid-php-class/">previous post</a>, I told you how to get the Simple OpenID PHP Class working with Yahoo. Now we&#8217;re going to focus on WordPress.com. This turned out to be very easy once I realized the problem. <span id="more-19"></span></p>
<p>The Problem:<br />
When you try to authenticate a WordPress OpenID using Simple OpenID you&#8217;re redirected to the correct URL, but it just displays your blog page rather than asking you to log in.</p>
<p>The Solution:<br />
After a closer look at the URL we find the problem. The WordPress OpenID server URL takes the form <span class="code">http://<em>username</em>.wordpress.com/?openidserver=1</span>. Fair enough. But the query string that we&#8217;ve appended with our request parameters also begins with a <span class="code">?</span> to set it apart from the rest of the URL. So, all we need to do is check the OpenID server URL we found during discovery for an existing query string. If it already has one, we&#8217;ll append our parameters with an <span class="code">&#038;</span>, otherwise we&#8217;ll use the <span class="code">?</span> as usual.</p>
<p><!--more--></p>
<p>Let&#8217;s change the <span class="code">GetRedirectURL</span> method to the following.</p>
<p>[php]<br />
function GetRedirectURL(){<br />
    $params = array();<br />
    $params['openid.return_to'] = urlencode($this-&gt;URLs['approved']);<br />
    if($this-&gt;version == &quot;2.0&quot;){<br />
        $params['openid.ns'] = urlencode($this-&gt;openid_ns);<br />
        $params['openid.claimed_id'] = urlencode($this-&gt;openid_url_identity);<br />
        $params['openid.realm'] = urlencode($this-&gt;URLs['trust_root']);<br />
    }else{<br />
        $params['openid.trust_root'] = urlencode($this-&gt;URLs['trust_root']);<br />
    }<br />
    $params['openid.mode'] = &#8216;checkid_setup&#8217;;<br />
    $params['openid.identity'] = urlencode($this-&gt;openid_url_identity);</p>
<p>    if (isset($this-&gt;fields['required'])<br />
      &amp;&amp; (count($this-&gt;fields['required']) &gt; 0)) {<br />
        $params['openid.sreg.required'] = implode(&#8216;,&#8217;,$this-&gt;fields['required']);<br />
    }<br />
    if (isset($this-&gt;fields['optional'])<br />
      &amp;&amp; (count($this-&gt;fields['optional']) &gt; 0)) {<br />
        $params['openid.sreg.optional'] = implode(&#8216;,&#8217;,$this-&gt;fields['optional']);<br />
    }<br />
    if(strstr($this-&gt;URLs['openid_server'], &quot;?&quot;)){<br />
        $urlJoiner = &quot;&amp;&quot;;<br />
    }else{<br />
        $urlJoiner = &quot;?&quot;;<br />
    }<br />
    return $this-&gt;URLs['openid_server'] . $urlJoiner . $this-&gt;array2url($params);<br />
}<br />
[/php]</p>
<p>And that&#8217;s it! Our WordPress OpenID should now authenticate properly with Simple OpenID. If it still doesn&#8217;t seem to work right, you can <a href="http://www.stevelove.org/projects/openid/class.openid.phps">download</a> the version that I&#8217;m using and see if that helps.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevelove.org/2008/08/25/how-to-wordpresscom-and-the-simple-openid-php-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Yahoo and the Simple OpenID PHP Class</title>
		<link>http://stevelove.org/2008/08/24/how-to-yahoo-and-the-simple-openid-php-class/</link>
		<comments>http://stevelove.org/2008/08/24/how-to-yahoo-and-the-simple-openid-php-class/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 21:58:29 +0000</pubDate>
		<dc:creator>Steve Love</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[yahoo]]></category>

		<guid isPermaLink="false">http://stevelove.org/?p=17</guid>
		<description><![CDATA[[Note: This post contains outdated information. Please visit the project page here for the latest information.] I&#8217;ve been working on OpenID a lot lately and I&#8217;ve latched on to a great starter PHP class called, obviously enough, Simple OpenID PHP Class (Simple OpenID). It&#8217;s easy enough to implement, but I quickly noticed that it didn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p><big><b>[Note: This post contains outdated information. Please visit the project page <a href="http://stevelove.org/projects/dope-openid/">here</a> for the latest information.]</b></big></p>
<p>I&#8217;ve been working on OpenID a lot lately and I&#8217;ve latched on to a great starter PHP class called, obviously enough, <a href="http://www.phpclasses.org/browse/package/3290.html">Simple OpenID PHP Class</a> (Simple OpenID). It&#8217;s easy enough to implement, but I quickly noticed that it didn&#8217;t work with Yahoo (among others). Basically it would return an error saying it couldn&#8217;t find an OpenID server at Yahoo. <span id="more-17"></span></p>
<p>At this point, I thought about switching to the very full featured <a href="http://openidenabled.com/php-openid/">JanRain PHP OpenID library</a> but it&#8217;s way more than I need right now. So I decided to stick it out with Simple OpenID and see if I couldn&#8217;t get it working like it should. In the end, I was able to get it working with Yahoo. I&#8217;ll show you how. If you find things aren&#8217;t coming together like they should, you can <a href="http://stevelove.org/projects/dope-openid/">download</a> the version of Simple OpenID that I&#8217;m now using.</p>
<p>What You&#8217;ll Need:</p>
<ul>
<li><a href="http://www.phpclasses.org/browse/package/3290.html">Simple OpenID</a> (requires cURL) Link points to the original file. Download my updated version <a href="http://stevelove.org/projects/dope-openid/">here</a>.</li>
<li>The PHP Yadis Library. This tutorial assumes you&#8217;re using the stand-alone download <a href="http://openidenabled.com/files/php-openid/files/PHP-yadis-1.0.2.tar.gz">here</a>.</li>
</ul>
<p>Summary:<br />
As it currently stands, Simple OpenID is built more or less to <a href="http://openid.net/specs/openid-authentication-1_1.html">OpenID 1.1 specifications</a>. What we&#8217;re going to do is add support for the <a href="http://openid.net/specs/openid-authentication-2_0.html">2.0 specifications</a>, which Yahoo requires. </p>
<p>It is assumed that you already have Simple OpenID installed and working with at least a few providers (Technorati and AOL seem to work right out of the box). If you need help getting it installed, look at the comments in the class itself, or check out the example included with the class.</p>
<p>Caveat:<br />
To be honest, I haven&#8217;t read the 2.0 specifications in full, so I may have missed some requirements here and there. I&#8217;ve added in the ones that I noticed and knew wouldn&#8217;t take much time to implement in a somewhat proper manner. The scope of this tutorial is only to get Simple OpenID working with Yahoo, not filling out every detail the class currently lacks.</p>
<p>Setup:<br />
First up is Yadis (if you&#8217;re interested, there&#8217;s more info <a href="http://yadis.org/wiki/Main_Page">here</a> and <a href="http://en.wikipedia.org/wiki/Yadis">here</a>). Extract the Yadis library that you downloaded. Find the Services directory and copy it to the same directory on your server where you have Simple OpenID. Something like this:</p>
<p><span class="code"><br />
www/Services/<br />
www/class.openid.php<br />
</span></p>
<p>All done? Okay, let&#8217;s get started!</p>
<p>At the time of this writing, the latest version of Simple OpenID is <span class="code">class.openid.v3.php</span>, so we&#8217;ll be working with that. Open it up in your editor of choice now.</p>
<p>Stop right there at line 1. We&#8217;re interested in compatibility here, people. Not only could that PHP short tag be mistaken for an XML opening tag, but it won&#8217;t work on a PHP installation that has short tags disabled. Change it to the full tag. It&#8217;s just three extra characters. Do it.</p>
<p>[php]<br />
&lt;?php<br />
[/php]</p>
<p>Now let&#8217;s add in the Yadis classes by adding the following on line 66.</p>
<p>[php]<br />
require_once &#8216;Services/Yadis/Yadis.php&#8217;;<br />
[/php]</p>
<p>Simple OpenID is currently equipped to locate an OpenID server by sending a request to the identity URL provided by the user and parsing the HTML response that&#8217;s returned. Yahoo doesn&#8217;t work this way. We have to use Yadis discovery to locate the server. Edit the <span class="code">GetOpenIDServer</span> method so that it looks like the code below.</p>
<p>[php]<br />
function GetOpenIDServer(){</p>
<p>    //Try Yadis Protocol discovery first<br />
    $http_response = array();<br />
    $fetcher = Services_Yadis_Yadis::getHTTPFetcher();<br />
    $yadis_object = Services_Yadis_Yadis::discover($this-&gt;openid_url_identity,<br />
                                                $http_response, $fetcher);</p>
<p>    // Yadis object is returned if discovery is successful<br />
    if($yadis_object != null){<br />
        $service_list = $yadis_object-&gt;services();<br />
        $types = $service_list[0]-&gt;getTypes();<br />
        $servers = $service_list[0]-&gt;getURIs();<br />
        $delegates = $service_list[0]-&gt;getElements(&#8216;openid:Delegate&#8217;);<br />
    }else{ // Else try HTML discovery<br />
        $response = $this-&gt;CURL_Request($this-&gt;openid_url_identity);<br />
        list($servers, $delegates) = $this-&gt;HTML2OpenIDServer($response);<br />
    }<br />
    if (count($servers) == 0){<br />
        $this-&gt;ErrorStore(&#8216;OPENID_NOSERVERSFOUND&#8217;);<br />
        return false;<br />
    }<br />
    if (isset($types[0])<br />
      &amp;&amp; ($types[0] != &quot;&quot;)){<br />
	$this-&gt;SetServiceType($types[0]);<br />
    }<br />
    if (isset($delegates[0])<br />
      &amp;&amp; ($delegates[0] != &quot;&quot;)){<br />
        $this-&gt;SetIdentity($delegates[0]);<br />
    }<br />
    $this-&gt;SetOpenIDServer($servers[0]);<br />
    return $servers[0];<br />
}<br />
[/php]</p>
<p>If you look at line 278 now, you&#8217;ll see we added a call to a method named <span class="code">SetServiceType</span>. Since there are still providers out there using OpenID 1.1 (i.e. livejournal.com) we need to make sure we can handle the specifications for whatever we come across. We&#8217;ll have to set the service type based on the version being used. Let&#8217;s add the <span class="code">SetServiceType</span> method at line 85.</p>
<p>[php]<br />
function SetServiceType($a){<br />
    // Hopefully the provider is using OpenID 2.0 but let&#8217;s check<br />
    // the protocol version in order to handle backwards compatibility.<br />
    // Probably not the best method, but it works for now.<br />
    if(stristr($a, &quot;2.0&quot;)){<br />
        $ns = &quot;http://specs.openid.net/auth/2.0&quot;;<br />
        $version = &quot;2.0&quot;;<br />
    }<br />
    else if(stristr($a, &quot;1.1&quot;)){<br />
        $ns = &quot;http://openid.net/signon/1.1&quot;;<br />
        $version = &quot;1.1&quot;;<br />
    }else{<br />
        $ns = &quot;http://openid.net/signon/1.0&quot;;<br />
        $version = &quot;1.0&quot;;<br />
    }<br />
    $this-&gt;openid_ns = $ns;<br />
    $this-&gt;version   = $version;<br />
}<br />
[/php]</p>
<p>What this does is check the service type we found during discovery and set the namespace (<span class="code">openid.ns</span>) and version appropriately. At this point, if we test what we have, we&#8217;ll be able to find Yahoo&#8217;s OpenID server address and redirect our user there to authenticate. But instead of being asked to login, our user will get this message from Yahoo:</p>
<blockquote><p>Sorry! You will not be able to login to this website as it is using an older version of the the OpenID technology. Yahoo! only supports OpenID 2.0 because it is more secure. For more information, check out the OpenID documentation at Yahoo! Developer Network.</p></blockquote>
<p>So it seems there&#8217;s more to OpenID 2.0 support than just adding in Yadis discovery. Don&#8217;t bother checking out the OpenID documentation at Yahoo! Developer Network, though. The only useful thing there is a link to the specifications for OpenID 2.0. After glancing through the specs, we find out we need to send some information to Yahoo as part of the URL query string.</p>
<p>If you look at the GetRedirectURL method, you&#8217;ll see on lines 307-311 we&#8217;re setting up our parameters array with the following: <span class="code">openid.return_to, openid.mode, openid.identity, openid.trust_root</span>. Lines 313-320 add the request for any <span class="code">sreg</span> info you want to get back from the OpenID provider.</p>
<p>That&#8217;s enough for the 1.1 specs, but not for 2.0. If, as is the case with Yahoo, we&#8217;re dealing with a 2.0 provider, we also need to send <span class="code">openid.ns</span> and <span class="code">openid.claimed_id</span>. In addition, the specs say that <span class="code">openid.trusted_root</span> has been renamed <span class="code">openid.realm</span> for 2.0. Let&#8217;s add our conditional code and change the <span class="code">GetRedirectURL</span> method to the following.</p>
<p>[php]<br />
function GetRedirectURL(){<br />
    $params = array();<br />
    $params['openid.return_to'] = urlencode($this-&gt;URLs['approved']);<br />
    if($this-&gt;version == &quot;2.0&quot;){<br />
        $params['openid.ns'] = urlencode($this-&gt;openid_ns);<br />
        $params['openid.claimed_id'] = urlencode($this-&gt;openid_url_identity);<br />
        $params['openid.realm'] = urlencode($this-&gt;URLs['trust_root']);<br />
    }else{<br />
        $params['openid.trust_root'] = urlencode($this-&gt;URLs['trust_root']);<br />
    }<br />
    $params['openid.mode'] = &#8216;checkid_setup&#8217;;<br />
    $params['openid.identity'] = urlencode($this-&gt;openid_url_identity);</p>
<p>    if (isset($this-&gt;fields['required'])<br />
      &amp;&amp; (count($this-&gt;fields['required']) &gt; 0)) {<br />
        $params['openid.sreg.required'] = implode(&#8216;,&#8217;,$this-&gt;fields['required']);<br />
    }<br />
    if (isset($this-&gt;fields['optional'])<br />
      &amp;&amp; (count($this-&gt;fields['optional']) &gt; 0)) {<br />
        $params['openid.sreg.optional'] = implode(&#8216;,&#8217;,$this-&gt;fields['optional']);<br />
    }<br />
    return $this-&gt;URLs['openid_server'] . &quot;?&quot;. $this-&gt;array2url($params);<br />
}<br />
[/php]</p>
<p>As you can see above, the value of <span class="code">openid.claimed_id</span> is the same as <span class="code">openid.identity</span>.</p>
<p>If you try our code now, you should be able to reach Yahoo&#8217;s OpenID login server. Great! Log in if you&#8217;re not already, and you&#8217;ll see a button that says &#8220;Let Me In.&#8221; (You&#8217;ll probably also see a scary warning message that says your website hasn&#8217;t confirmed its identity with Yahoo. Don&#8217;t worry about this for now; we&#8217;ll take care of it later.)</p>
<p>Click the &#8220;Let Me In&#8221; button and you&#8217;ll be taken back to the URL you specified as the <span class="code">return_to</span> address. But for some reason, there&#8217;s an error message that says &#8220;Could not validate the OpenID at http://yahoo.com/&#8221;. This message comes from the <span class="code">ValidateWithServer</span> method, so something must be going wrong here.</p>
<p>When we made our first request to Yahoo, we sent some parameters in the URL. When the user clicks &#8220;Let Me In&#8221;, Yahoo sends its own parameters appended to the <span class="code">return_to</span> address. You can see them if you look at the URL where you got the error message. If you look closely, you&#8217;ll see one of the parameters returned is <span class="code">openid.signed</span>. The value is a comma-separated list of parameters that Yahoo wants us to validate. Basically, Yahoo wants us to send these data back so they can let us know if anything has been tampered with in transit.</p>
<p>If you look at lines 341-345, you can see that we&#8217;re building another array of parameters that we&#8217;re going to validate with Yahoo. <span class="code">openid.assoc_handle, openid.signed</span> and <span class="code">openid.sig</span> are all declared outright. Then beginning on line 347, you can see we&#8217;re taking the comma-separated list, the signed parameters returned with <span class="code">openid_signed</span>, and replacing all instances of &#8220;<span class="code">sreg.</span>&#8221; with &#8220;<span class="code">sreg_</span>&#8220;, then storing it as an array (<span class="code">$arr_signed</span>). Since the comma-separated list contains variables that are passed in the URL, PHP will automatically add them in our global <span class="code">$_GET</span> array. But anything like <span class="code">openid.sreg.fullname</span> will become <span class="code">$_GET['openid_sreg_fullname']</span> when PHP parses the variables.</p>
<p>On line 348, there&#8217;s a for loop that goes through each of the signed parameters and uses logic to grab the value from <span class="code">$_GET['openid_sreg_fullname']</span> and store it as <span class="code">$params['openid.sreg.fullname']</span>.</p>
<p>And finally line 355 sets <span class="code">openid.mode</span> to &#8220;<span class="code">check_authentication</span>&#8221; and adds it to our array of parameters.</p>
<p>So if the for loop adds all of the signed parameters that Yahoo gives us, why are we getting an error? Well, let&#8217;s look at the signed parameters Yahoo is asking for.</p>
<ul>
<li>assoc_handle</li>
<li>claimed_id</li>
<li>identity</li>
<li>mode</li>
<li>ns</li>
<li>ns.pape</li>
<li>op_endpoint</li>
<li>pape.auth_policies</li>
<li>pape.nist_auth_level</li>
<li>response_nonce</li>
<li>return_to</li>
<li>signed</li>
</ul>
<p>If you recall, the variable names containing periods or dots are going to be converted to underscores when added to the <span class="code">$_GET</span> array. Line 347 takes care of any names taking the form &#8220;<span class="code">sreg.</span>&#8221; but as you can see, we need to do something with names containing &#8220;<span class="code">ns.</span>&#8221; and &#8220;<span class="code">pape.</span>&#8221; as well. Let&#8217;s rewrite the <span class="code">ValidateWithServer</span> method to reflect this.</p>
<p>[php]<br />
function ValidateWithServer(){</p>
<p>    $params             = array();<br />
    $arr_underscores    = array(&#8216;ns_&#8217;, &#8216;pape_&#8217;, &#8216;sreg_&#8217;);<br />
    $arr_periods        = array(&#8216;ns.&#8217;, &#8216;pape.&#8217;, &#8216;sreg.&#8217;);<br />
    $arr_getSignedKeys  = explode(&quot;,&quot;,str_replace($arr_periods, $arr_underscores, $_GET['openid_signed']));</p>
<p>    // Send only required parameters to confirm validity<br />
    foreach($arr_getSignedKeys as $key){<br />
        $paramKey = str_replace($arr_underscores, $arr_periods, $key);<br />
        $params[&quot;openid.$paramKey&quot;] = urlencode($_GET[&quot;openid_$key&quot;]);<br />
    }<br />
    if($this-&gt;openid_version != &quot;2.0&quot;){<br />
        $params['openid.assoc_handle'] = urlencode($_GET['openid_assoc_handle']);<br />
        $params['openid.signed'] = urlencode($_GET['openid_signed']);<br />
    }<br />
    $params['openid.sig'] = urlencode($_GET['openid_sig']);<br />
    $params['openid.mode'] = &quot;check_authentication&quot;;</p>
<p>    $openid_server = $this-&gt;GetOpenIDServer();<br />
    if ($openid_server == false){<br />
        return false;<br />
    }<br />
    $response = $this-&gt;CURL_Request($openid_server,&#8217;POST&#8217;,$params);<br />
    $data = $this-&gt;splitResponse($response);</p>
<p>    if ($data['is_valid'] == &quot;true&quot;) {<br />
        return true;<br />
    }else{<br />
        return false;<br />
    }<br />
}<br />
[/php]</p>
<p>If you try the code now, you should have a successful validation. Excellent!</p>
<p>But &#8230; what about that scary warning message we saw on the Yahoo OpenID endpoint?</p>
<p>To get rid of that, you need to create an XRDF file to let Yahoo know who you are. Create a file called &#8220;<span class="code">yadis.xrdf</span>&#8221; and place it somewhere on your server. The important part of this file is that you tell it where your <span class="code">return_to</span> URL is. The file should look like this.</p>
<p>[xml]<br />
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br />
&lt;xrds:XRDS<br />
    xmlns:xrds=&quot;xri://$xrds&quot;<br />
    xmlns:openid=&quot;http://openid.net/xmlns/1.0&quot;<br />
    xmlns=&quot;xri://$xrd*($v*2.0)&quot;&gt;<br />
    &lt;XRD&gt;<br />
        &lt;Service priority=&quot;0&quot;&gt;<br />
            &lt;Type&gt;http://specs.openid.net/auth/2.0/return_to&lt;/Type&gt;<br />
            &lt;URI&gt;http://yourdomain.com:80/path-to/your_return_to.php&lt;/URI&gt;<br />
        &lt;/Service&gt;<br />
    &lt;/XRD&gt;<br />
&lt;/xrds:XRDS&gt;<br />
[/xml]</p>
<p>All you need to do now is send a header from your site that reveals the location of your XRDF file. <del datetime="2009-07-04T23:33:03+00:00">I&#8217;m not certain on this, but it appears that you need to send this header from the index page of your OpenID login area. For example, if your login form is at <span class="code">http://example.com/openid/login.php</span>, the header should be sent from <span class="code">http://example.com/openid/index.php</span> in order for Yahoo to find it. Add the following code to the top of your index page.</del> This header must be sent from the root of the URL you specified as your &#8220;trust root&#8221;. There cannot be any output before this header or it won&#8217;t work. It must be the very first thing, probably just after the opening PHP tag.</p>
<p>[php]<br />
header(&#8216;X-XRDS-Location:http://yourdomain.com/path-to/yadis.xrdf&#8217;);<br />
[/php]</p>
<p>What&#8217;s next?</p>
<p>There&#8217;s plenty more to do for the 2.0 specs. For example, while an OpenID could take the form of &#8220;<span class="code">http://example.com/user</span>&#8220;, it could also look like &#8220;<span class="code">xri://=john.smith</span>&#8221; or something equally strange. XRI support is something else that has been added to the 2.0 specs. All we need to do is add some logic to handle these types of identities. Since this kind of logic already exists in the <span class="code">SetIdentity</span> method, let&#8217;s add it there.</p>
<p>[php]<br />
function SetIdentity($a){ 	// Set Identity URL</p>
<p>    $xriIdentifiers = array(&#8216;=&#8217;, &#8216;$&#8217;, &#8216;!&#8217;, &#8216;@&#8217;, &#8216;+&#8217;);<br />
    $xriProxy = &#8216;http://xri.net/&#8217;;</p>
<p>    // Is this an XRI string?<br />
    // Check for &quot;xri://&quot; prefix or XRI Global Constant Symbols<br />
    if (stripos($a, &#8216;xri://&#8217;) || in_array($a[0], $xriIdentifiers)){<br />
        // Attempts to convert an XRI into a URI by removing the &quot;xri://&quot; prefix and<br />
        // appending the remainder to the URI of an XRI proxy such as &quot;http://xri.net&quot;<br />
        if (stripos($a, &#8216;xri://&#8217;) == 0) {<br />
            if (stripos($a, &#8216;xri://$ip*&#8217;) == 0) {<br />
                $a = substr($a, 10);<br />
            } elseif (stripos($a, &#8216;xri://$dns*&#8217;) == 0) {<br />
                $a = substr($a, 11);<br />
            } else {<br />
                $a = substr($a, 6);<br />
            }<br />
        }<br />
            $a = $xriProxy.$a;<br />
    }</p>
<p>    if ((stripos($a, &#8216;http://&#8217;) === false)<br />
      &amp;&amp; (stripos($a, &#8216;https://&#8217;) === false)){<br />
        $a = &#8216;http://&#8217;.$a;<br />
    }</p>
<p>    $this-&gt;openid_url_identity = $a;<br />
}<br />
[/php]</p>
<p>Also, during Yadis discovery, we may discover more than one provider redirect URL. The reason for this, as far as I can tell, is for load balancing or providing alternatives in case the first one we try returns an error. We&#8217;ll need to modify the code to check each endpoint&#8217;s priority level, and be prepared to retry several times in case one or more endpoints return an error response. However, that&#8217;s something for another tutorial.</p>
<p>Simple OpenID also seems to have a problem with WordPress.com identities. It&#8217;s easy enough to solve, and you can find my solution <a href="http://www.stevelove.org/2008/08/how-to-wordpresscom-and-the-simple-openid-php-class/">here</a>.</p>
<p><a href="http://stevelove.org/projects/dope-openid/">Download</a> the version of Simple OpenID that I&#8217;m now using.</p>
]]></content:encoded>
			<wfw:commentRss>http://stevelove.org/2008/08/24/how-to-yahoo-and-the-simple-openid-php-class/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

