views:

2180

answers:

8

Hi Guys, I'm using the Zend framework and the openid selector from http://code.google.com/p/openid-selector/ - however I find I can't login using sites like Google and Yahoo as they use direct identity based login system whereby one is just redirected to a url as opposed to entering a unique url of their own for authentication.

I've checked out many options and hacks but none of them seem to work. How can i get this to work here btw - how is it implemented at stack overflow? I could really use all the help here guys..


Edit

Well the issue here is that from what I have noticed is that the Zend OpenID class doesn't support OpenID 2.0 the thing is that a typical open ID providor gives you a unique url such as your-name.openid-providor.com or openid-providor.com/your-name and the Zend OpenId class just parses through that url and then redirects you to the providor website where upon authentication you are redirected back.

In the case of Yahoo and google - you don't enter a unique url instead you are redirected to the providors login site and upon login and authentication you are redirected back - so basically whats happeining is that the zend_openID object when it parses to tell who the providor is it fails to tell from the general url itself. Like when you click on teh Google link it redirects you to https://www.google.com/accounts/o8/id

Its more an issue with the zend openid object here and there isn't any help on zend related forums - so I was wondering if someone had already hacked or had an alteration I could make to the class to accomplish this. Sorry if I'm missing something but I'm kinda new to this and programming with open ID and have just started to get my feet wet.


Thanks for the follow up - I did check into RPX a while back and they do have a php class but I wasnt able to check it out plus I really just want to for now get the code selector used as on stackoverflow to work with Yahoo and Google authentication. There has to be some kind of way to tweak the parsing which the Zend OpenID class uses as it runs a series of regular expression checks to make a discovery.

A: 

Did you check out the manual -- Zend_OpenId_Consumer basics? Check out 38.2.2 on that page and let me know if this helps, because it should.

Specifically, I don't know if Google offers OpenID. I know that Yahoo worked because I've tried it a while back.

Till
Actually I am using this very piece of code in the manual as it is. However its not working with google and Yahoo at all. I've tried some hacks online but they don't work :( how has stack overflow accomplished this btw?
Ali
@Ali Stackoverflow is build on asp.net (I think). Anyway, I'd suggest you supply more info, e.g. your code, your error message -- then I could try to help. Or you post on the fw-general@ mailing list.
Till
Google doesn't provide openID, Google has their own GoogleID, which can be associated with openIDs.
tharkun
+1  A: 

I'm dealing with similar issues. I'm planning on using RPX now with Zend Framework. Maybe I'll write an adapter. Just to let you know.

Info: 'RPS now' provides an all-in-one interface and UI for user registration with

  • facebook
  • Google
  • Yahoo
  • mySpaceID
  • Windows LiveID
  • OpenID
  • aol
tharkun
+1  A: 

I'm pretty sure that Yahoo only works with OpenID 2.0. If you want to support Yahoo users, you're going to have to upgrade to a library with 2.0 support. That's going to be a matter of more than tweaking some parsing.

keturn
+2  A: 

Going over all the advice provided - I've decided to ditch using the zend_openid class [ sorry about that zend ] and instead I've switched to using JanRains OpenID library. Its taken a few hours to get it up and running with my project but atleast its working like a breeze. Had to make a lot of hacking and a bit of code spill over to get it working but its worth it.

I couldn't use any of Zend adapters with Zend-Auth to settle this new code library in as the library did the authentication on its own. SO I hacked and made a generic adapter that just returned a filled zend_result set to the Auth object thus I authenticate using my library and merely store the result in the Auth object pulling a bit of a fast one one the Zend-Auth object rather than have to rewrite my code again.

The library is available at http://openidenabled.com/php-openid/

Thanks for all the help guys.

Ali
A: 

Thanks for the information. I started by using JanRain's library, but I have problems with getting Simple Registration to work: I have not succeeded in getting any data that way. And there is no documentation on using Attribute Exchange. :(

So, I found and was trying Zend/OpenId, but had the same problem as you: no Yahoo!, Google and who knows what else support. Reading this, it seems I'll have to get back to JanRain; RPX is not an option in my case as it's a third party service.

Janis
Its a bit painful to get it to work with JanRain but its very robust. You need to create an Authentication adapter which is totally generic and doesn't do any authentication as all the authentication would be done by JanRain. The Generic adapter you create would merely just return basic information upon authentication from janrain such as the OpenID code and whatever you choose to fill the adapter with...
Ali
JanRain is pain. It's sad to know that Zend is pain too :(
jayarjo
+5  A: 

Little late to the game but I was able to get this working with some hacks I found around the interwebs.

First. Yahoo. To get Yahoo working all I had to do was change the JavaScript to use me.yahoo.com instead of just yahoo.com and it worked perfectly with the version of the Zend Framework I'm using. Unfortunately Google still wasn't, so some hacking was in order.

All of these changes go in Zend/OpenId/Consumer.php

First, in the _discovery method add the following on the series of preg_match checks that starts at around line 740.

} else if (preg_match('/<URI>([^<]+)<\/URI>/i', $response, $r)) {
  $version = 2.0;
  $server = $r[1];

I added this right before the return false; statement that's in the else {} block.

Second, in the _checkId method you'll need to add 3 new blocks (I haven't dug around enough to know what causes each of these three cases to be called, so I covered all to be on the safe side.

Inside the $version <= 2.0 block, you'll find an if/else if/else block. In the first if statement ($this->_session !== null) add this to the end:

if ($server == 'https://www.google.com/accounts/o8/ud') {
  $this->_session->identity = 'http://specs.openid.net/auth/2.0/identifier_select';
  $this->_session->claimed_id = 'http://specs.openid.net/auth/2.0/identifier_select';
}

In the else if (defined('SID') block add this to the end:

if ($server == 'https://www.google.com/accounts/o8/ud') {
  $_SESSION['zend_openid']['identity'] = 'http://specs.openid.net/auth/2.0/identifier_select';
  $_SESSION['zend_openid']['claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select';
}

And then after the else block (so outside the if/else if/else block all together, but still inside the $version <= 2.0 block) add this:

if ($server == 'https://www.google.com/accounts/o8/ud') {
  $params['openid.identity'] = 'http://specs.openid.net/auth/2.0/identifier_select';
  $params['openid.claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select';
}
Steven Surowiec
Pretty late - but again thanks for the tip would bookmark this definitely for any other project - for now I've meticulously tweaked and integrated the JanRain library into my code.Thanks for the info ;)
Ali
The three blocks are called depending if as session and the associated Zend session classes have been started already. The first block is true if Zend_Session has been used to start the session and is stored in the _session variable of the consumer object. The second block is true if the session has been started by session_start() or session.auto_start. The final block starts a new session with Zend_Session_Namespace
bearver
+3  A: 

I need to use Google's OpenID stuff, and I tried Steven's code and couldn't get it to work as-is. I've made some modifications.

The _discovery change method is still the same:

Zend/OpenId/Consumer.php, line 765, add:

} else if (preg_match('/<URI>([^<]+)<\/URI>/i', $response, $r)) {
    $version = 2.0;
    $server = $r[1];

The rest is different, though:

Zend/OpenId/Consumer.php, line 859 (after making the above change), add:

if (stristr($server, 'https://www.google.com/') !== false) {
    $id = 'http://specs.openid.net/auth/2.0/identifier_select';
    $claimedId = 'http://specs.openid.net/auth/2.0/identifier_select';
}

This is right before:

$params['openid.identity'] = $id;

$params['openid.claimed_id'] = $claimedId;

And to get it to return the ID, once authorized:

Zend/Auth/Adapter/OpenId.php, line 278:

if(isset($_REQUEST['openid_identity']))
{
    $this->_id = $_REQUEST['openid_identity'];
    $id = $this->_id;
}

This is right before:

return new Zend_Auth_Result(
    Zend_Auth_Result::SUCCESS,
    $id,
    array("Authentication successful"));

Note that I have not thoroughly tested this code. The code below is even more shakey.

I have spent more time and I've gotten it to work with my Google Apps domain with the following changes, in addition to the above:

Zend/OpenId/Consumer.php, line 734

     $discovery_url = $id;
     if(strpos($discovery_url, '/', strpos($discovery_url, '//')+2) !== false) {
      $discovery_url = substr($discovery_url, 0, strpos($discovery_url, '/', strpos($discovery_url, '//')+2));
     }
     $discovery_url .= '/.well-known/host-meta';
     $response = $this->_httpRequest($discovery_url, 'GET', array(), $status);
        if ($status === 200 && is_string($response)) {
            if (preg_match('/Link: <([^><]+)>/i', $response, $r)) {
       $id = $r[1];
      }
        }

This is right after:

/* TODO: OpenID 2.0 (7.3) XRI and Yadis discovery */

I believe that was the only change I had to make. I'm pretty sure there's supposed to be some checking involved with the above for security reasons, but I haven't looked far enough into it to see what they would be.

Thanks for the tip - I just ditched using the Zend class and incorporated JanRains OpenID library instead. Figured if I had to hack away at existing code it made better sense to create my own wrapper class on a more robust code model..
Ali
A: 

Yahoo does not support Simple Registration yet, it is being experimented with few sites such as rpxnow