New version of the OpenID component

Published on February 06, 2008 and tagged with cakephp  component  openid

Just uploaded a new version of the OpenID component I wrote sometime ago. It uses now version 2.0.0 of the PHP OpenID library, which supports the OpenID 2.0 specification.

As the API has changed a bit, let me make a simple example to show you how the component is used.

First we create the login form:

<?php
// app/views/users/login.ctp
if (isset($message)) {
    echo '<p class="error">'.$message.'</p>';
}
echo $form->create('User', array('type' => 'post', 'action' => 'login'));
echo $form->input('OpenidUrl.openid', array('label' => false));
echo $form->end('Login');
?>

As next step we have to implement the login action in our controller:

// app/controllers/users_controller.php
class UsersController extends AppController {
    var $components = array('Openid');
    var $uses = array();

    function login() {
        $returnTo = 'http://'.$_SERVER['SERVER_NAME'].'/users/login';

        if (!empty($this->data)) {
            try {
                $this->Openid->authenticate($this->data['OpenidUrl']['openid'], $returnTo, 'http://'.$_SERVER['SERVER_NAME']);
            } catch (InvalidArgumentException $e) {
                $this->setMessage('Invalid OpenID');
            } catch (Exception $e) {
                $this->setMessage($e->getMessage());
            }
        } elseif (count($_GET) > 1) {
            $response = $this->Openid->getResponse($returnTo);

            if ($response->status == Auth_OpenID_CANCEL) {
                $this->setMessage('Verification cancelled');
            } elseif ($response->status == Auth_OpenID_FAILURE) {
                $this->setMessage('OpenID verification failed: '.$response->message);
            } elseif ($response->status == Auth_OpenID_SUCCESS) {
                echo 'successfully authenticated!';
                exit;
            }
        }
    }

    private function setMessage($message) {
        $this->set('message', $message);
    }
}

The login action basically performs three things. If it is called with a GET request without any parameters, it simply shows the login form. If we submit the login form, then the OpenID authentication process is started and you will be redirected to your OpenID provider. And when you get redirected back from the OpenID provider, we process the response.

That’s it. You can download the component from the download area (and don’t forget to read the installation instructions).

Happy baking :)

See also: Using the OpenID Simple Registration Extension

73 comments baked

  • klevo February 07, 2008 at 08:39

    There’s a slight typo in the second catch block. > is not properly rendered.

    Anyway great component, thanks!

  • cakebaker February 07, 2008 at 18:21

    @klevo: Thanks for the hint, it is fixed now.

  • Matti Putkonen February 07, 2008 at 20:33

    Could this be used directly to ask for fullname during authentication ?

  • cakebaker February 08, 2008 at 09:25

    @Matti: Yes, you can use either the 4th or 5th parameter of the authenticate() method for this purpose. Simply pass an array with the fields you are interested in, but be aware that it is not guaranteed that those fields will be in the response from the OpenID server.

    Hope that helps!

  • Cherry on the… » Nouvelle version du composant OpenId February 11, 2008 at 12:17

    [...] Hofstetter aka CakeBaker a publié une version mise à jour de son composant OpenID. Elle se trouve ici avec toutes les [...]

  • Using the OpenID Simple Registration Extension - cakebaker February 12, 2008 at 10:34

    [...] the OpenID component it is quite easy to use Simple Registration. The authenticate() method provides the two parameters [...]

  • Jeremy February 24, 2008 at 03:28

    Argh, set it up, but I keep getting
    OpenID verification failed: Server denied check_authentication
    when i’m clearly allowing it, not sure where the break down is. I’ve googled the server denied message and see a lot of people with different implementations that have the issue, but haven’t found a fix for it yet, anyone run into this and know how to fix it? or at least know how to fix it?

    Thanks

  • cakebaker February 24, 2008 at 12:32

    @Jeremy: Did you test it with different OpenID providers?

  • Jeremy February 25, 2008 at 05:05

    just signed up for a different one, so i’ve tried both myopenid.com and claimid.com and am getting the same thing.

  • Jeremy February 25, 2008 at 05:31

    Just tried a separate provider, so i’ve tried myopenid.com and claimid same issue with both, and it’s definitely authorizing because the count is going up on my history in myopenid. any ideas where to go from here?

  • cakebaker February 26, 2008 at 17:52

    @Jeremy: Hm, difficult to say what the problem is. Did you debug the response you get from the OpenID provider?

  • CakePHP and OpenID - cakebaker March 09, 2008 at 18:36

    [...] Please notice there is a newer tutorial! [...]

  • knud March 15, 2008 at 07:21

    if your develop on http://localhost:3000 the you need to use
    $returnTo =’http://’.$_SERVER['SERVER_NAME'].’:’.$_SERVER['SERVER_PORT'].’/users/login’;

    Also I think you should extend the example to show how simple registration is done.

  • knud March 15, 2008 at 09:16

    I am trying the example but there is a problem.
    After the redirection return to my site $_GET on contains
    Array ( [url] => /openids/login )

    So, the script can’t get the info.

    Being a cakephp newbie I might have forgotten to do something but what ?

  • cakebaker March 15, 2008 at 17:46

    @knud: Thanks for your comments!

    I added a link to an article, where I show, how to use the Simple Registration Extension. Hope that helps.

    Difficult to say what the problem is. Can you provide more details?

  • knud March 15, 2008 at 20:50

    I used cakephp-instaweb it cut off the reply.
    When I use apache it works okey.

  • cakebaker March 16, 2008 at 11:09

    @knud: Cool to hear it is working! And regarding the problem with cakephp-instaweb, you may contact its author.

  • knud March 26, 2008 at 21:28

    I think I was to fast to conclude that it works.
    I get the error
    “OpenID verification failed: Nonce already used or out of range”
    all the time, any ideas why that could be ??

  • cakebaker March 27, 2008 at 18:26

    @knud: Hm, never encountered such an error yet. Is your site online?

    Maybe the following message helps: http://lists.openidenabled.com/pipermail/dev/2008-February/001068.html

  • knud March 27, 2008 at 19:33

    No, my site is not online yet.
    Thanks, the problem was the time on my computer as the message suggest.

  • cakebaker March 27, 2008 at 19:55

    @knud: Uff, good to hear the tip was helpful :)

  • knud March 29, 2008 at 18:29

    I have now installed ntpd, so my time is very precise and openid worked for a time.
    But I made some changes to my script which resulted in cake/php taking very long to process my script, and as a result the error is back !

    Is openid meant to work like this or is it a bug in the php-openid
    library ?

  • cakebaker March 31, 2008 at 17:31

    @knud: Hm, what changes did you make? Maybe you can mail me the code that causes the problem?

  • Calin Don April 15, 2008 at 00:30

    While working with the component I encountered an error, regarding the return_to which in the latest version of OpenId-PHP library must be a string.

    The line 47:
    $response = $consumer->complete($_GET);

    Must be changed into
    $return_to = substr($_GET['openid_return_to'], 0, strpos($_GET['openid_return_to'], “?”));
    $response = $consumer->complete($return_to);

    This fix was provided on:
    http://www.codymays.net/content/2007/02/20/the-future-and-openid/

  • knud April 15, 2008 at 05:55

    Calin, line 47 in which file ??

    I think I have found the error in php-openid.
    A openid responce return 2 nonces.
    from consumer: [janrain_nonce] => 2008-04-15T03:18:00ZW7x3v0
    from server: [openid_response_nonce] => 2008-04-15T03:18:03ZDK8rIP
    The problem is that the timestamp of the server nonce is used to check for a nonce file created with the timestamp from the consumer nonce.

    So, if the two timestamp differ within a second you will get a error.
    This will happen if you script is slow like when you use cake debug mode 3.

  • knud April 15, 2008 at 06:12

    Calin, line 47 in which file ?

    I think I have found the error in php-openid !
    A openid respone return 2 nonces:
    from consumer:[janrain_nonce] => 2008-04-15T03:18:00ZW7x3v0
    from server:[openid_response_nonce] => 2008-04-15T03:18:03ZDK8rIP
    The problem is that the time stamp from the server nonce
    is used to check for a nonce file created by the time stamp
    from the consumer nonce.

    If the 2 nonces differ within the second you will get a error.
    This happens if you script is slow or your are using cake debug mode.

    Hope someone with more insight into the php-openid code can help
    with a real fix.

  • equanimous April 15, 2008 at 06:13

    Calin, line 47 in which file ?

    I think I have found the error in php-openid !
    A openid respone return 2 nonces:
    from consumer:[janrain_nonce] => 2008-04-15T03:18:00ZW7x3v0
    from server:[openid_response_nonce] => 2008-04-15T03:18:03ZDK8rIP
    The problem is that the time stamp from the server nonce
    is used to check for a nonce file created by the time stamp
    from the consumer nonce.

    If the 2 nonces differ within the second you will get a error.
    This happens if you script is slow or your are using cake debug mode.

    Hope someone with more insight into the php-openid code can help
    with a real fix.

  • Calin Don April 15, 2008 at 15:33

    @equanimous in the app/controller/components/openid.php

    I am also facing the same problem with the nonce, although I don’t think it’s related to the above fix, because after the above fix it the authentication worked for me (for a while).

    Currently I’m digging for a solution to this… keep you posted.

  • Calin Don April 15, 2008 at 18:02

    So looks like the FileStore (Auth/OpenId/FileStore.php) is the trouble maker. The solution was to remove the contents under /app/tmp/openid . Also to see a hint why it cannot open the file containing the nonce remove the @ from Auth/OpenId/FileStore.php line 389 or else the library will complain about the nonce, but you will not see the reason.

    Btw, anyone managed to use the MySQLStore instead of the FileStore?

  • knud April 15, 2008 at 18:12

    I am sorry about the trible post.
    The page did not update, so I made some retries.

  • knud April 15, 2008 at 18:32

    calin, line 47 in that file says:
    $authRequest->addExtension($sregRequest);

    I am using openid_component_2008-02-06.zip which are you using ?

  • cakebaker April 15, 2008 at 19:07

    @Calin: I think you downloaded an old version of the component. It’s my bad, somehow the wrong page was shown after upgrading to WordPress 2.5. It’s now fixed. I’m sorry for the inconvenience…

    I don’t have used the MySQLStore yet, but it is probably a good idea to support it in one of the next versions.

    @knud: No problem, thanks to your triple post I noticed that a cache was activated which shouldn’t have been activated ;-)

    As a workaround you may try to set Security.level to “low” (in app/config/core.php), but I’m not sure it will help in your situation…

  • knud April 16, 2008 at 05:12

    After styding the problem in detail it seems that those
    how made the openid 2.0 spec really fucked up the nonce issue.

    it seems that before 2.0 nonce worked as a non standard (therefore the janrain_nonce format) ticket issued by the consumer and returned by the server.
    When the nonce was returned the consumer checked that the nonce was issued.

    But in 2.0 response_nonce is issued by the server
    and the consumer have to check that the nonce haven’t been seen before from that server.
    It seems that jan rain didn’t make a distinction between the two types of nonce when he made the last update.

    I like the ticket idea the most so I will use that,
    even it is not standard.

  • cakebaker April 17, 2008 at 17:39

    @knud: I don’t understand exactly the problem you encounter, but I would be careful with using a non-standard approach and test it with different OpenID providers (OPs). If it works with differents OPs, then go for it :)

  • Keef May 17, 2008 at 11:12

    Hello, has anyone seen this error and know how to get around it?

    “OpenID verification failed: return_to does not match return URL. Expected http://quotedb.k3f.info/login, got http://quotedb.k3f.info/login?janrain_nonce=2008-05-17T09%3A01%3A10ZCN1Nqf&openid1_claimed_id=http%3A%2F%2Fclaimid.com%2Fkeef

    I’ve seen these two trac entries, which it’s properly related to:
    http://trac.openidenabled.com/trac/ticket/74
    http://trac.openidenabled.com/trac/ticket/129

    I also tried the Development Snapshot of php-openid with no luck. Any ideas?

    Also on a separate note; I couldn’t login to your site using claimid and got the error “We were unable to authenticate your OpenID”.

  • Keef May 17, 2008 at 11:19

    Hello, has anybody had this error and found a solution to it:

    OpenID verification failed: return_to does not match return URL. Expected http://quotedb.k3f.info/login, got http://quotedb.k3f.info/login?janrain_nonce=2008-05-17T09%3A16%3A42ZZF3AnV&openid1_claimed_id=http%3A%2F%2Fclaimid.com%2Fkeef

    I’ve tried using the development snapshots of php-openid with no luck either.

  • cakebaker May 18, 2008 at 11:09

    @Keef: It’s my bad, the download link pointed to an old version of the component. Please download and try it again. I’m sorry for this inconvenience…

    And thanks for the hint that the OpenID login with claimid doesn’t work, I have to investigate what the cause is.

  • http://keef.myopenid.com/ May 18, 2008 at 18:35

    @cakebaker: Thanks a lot for the help, the component works fine with other OpenIDs that I’ve tried but seems not to with claimID which is a rather strange.

    Oh and sorry about the double post, my browser (Firefox 3) crashed right in the middle of submitting the comment and when it loaded back up (probably from cache) the comment wasn’t there so I rewrote it.

  • cakebaker May 19, 2008 at 17:19

    @Keef: I updated wp-openid (the plug-in I use in this blog for OpenID) to the latest version, but unfortunately the problem is still there :| On my local test blog it works fine.

    The same situation for the OpenID component: on my local machine it works fine, but on the server it is no longer possible to login with a claimid OpenID. At the moment I’m a bit clueless on what the problem could be…

    Don’t worry about the double post, your first comment ended in the moderation queue as it contained more than two links and so it wasn’t shown ;-)

  • Andreas June 14, 2008 at 00:04

    @keef,
    i had the same error “OpenID verification failed: return_to does not match return URL.”. So I tried differnt versions of PHP OpenID library, with no success.
    The solution that worked for me:
    Instead of a returnTo-URL like: example.com/users/login I simply use:
    example.com/index.php?url=users/login

    If anybody has an other solution to this error, i would be happy to hear it…

  • nate July 27, 2008 at 05:16

    Why is it necessary to hack the JainRain library if you’re wrapping it? Can’t you just unset the ‘url’ key before you make the call, and set it back when you’re done?

  • cakebaker July 28, 2008 at 18:31

    @nate: I’m not sure if it is really necessary to hack the JanRain library, it’s just the first approach that worked for me ;-) If I unset the “url” key, I get for some reason an OpenID verification error… I eventually have to investigate this problem further…

  • knud July 29, 2008 at 10:20

    I finally have my web site online and I think I have solved all my problems with the openid phplib.

    My web site is still in development but you can try the beta
    version on http://crowdnews.eu

    Knud

  • cakebaker July 29, 2008 at 17:09

    @Knud: Cool, looks nice :)

  • WyriHaximus July 30, 2008 at 11:09

    @Knud looks cool, only thing I get when I login with my OpenID is this error:
    Error: The requested address '/users/topstories' was not found on this server.

    @cakebaker thanks for the component, cheers!

  • knud July 30, 2008 at 18:39

    Thank, this is now fixed.

    Daniel, you are welcome to post link to new (or old) cakebaker articles on crowdnews.eu
    Knud

  • Neters Landreau August 01, 2008 at 01:08

    I am testing how this works using an openid identity.

    My first attempt at posting this was unsuccessful because I selected a persona that did not return all the required information (i.e. name and email). I will try a different persona.

  • equanimous August 03, 2008 at 13:20

    Hi Neters
    I have updated you info on http://crowdnews.eu
    I plan to make it possible to do it via openid
    but that isn\’t implemented yet.

  • Neters Landreau October 15, 2008 at 11:46

    equanimous, I tried to login to your site using my openid library but got an error telling me the nonce was missing from the response.

    I’d like to be able to find out if this is at your end or mine.

    NL

  • lboy December 03, 2008 at 13:30

    Sorry for the noobish question, but what do you typically want to do once you’ve authenticated someone successfully? I am integrating this into a site which already has its own registration/login system. I don’t know how I can merge the normal logins and openid logins into one table in the database.

  • Cees-Jan Kiewiet December 03, 2008 at 14:28

    @lboy -> On my own system I use openid as an extension on the existing user management system. When someone is authenticated it will check if the openid login is from an existing user (just link openid URL’s to users) ifso it will log that user in. If it’s not frmo a user it will attempt to create that user with information from the openid login. (Make sure you request that information!!!)

  • cakebaker December 04, 2008 at 17:12

    @lboy, Cees-Jan: Thanks for your comments!

    @lboy: Does the good answer from Cees-Jan answer your question? Or is there still something unclear?

  • lboy December 22, 2008 at 17:05

    @Cees-Jan, cakebaker: Sorry for the delay… Yes, that answer is helpful, thanks. It helped to have it written down in words, even though I think I knew roughly what I needed to do.

  • Cees-Jan Kiewiet December 27, 2008 at 19:59

    @lboy -> Yeah it’s a rough sketch tho :P. Just a little warning, sites like Yahoo.com (you can use http://yahoo.com/ as if you have an yahooID) don’t give useable data or URL’s to generate when someone uses it as openid. Making it impossible to findout who is actually loggingin. Still working on that :P.

  • cakebaker January 02, 2009 at 18:01

    @Cees-Jan: Yes, that’s true, however it looks like Yahoo wants to support Simple Registration in the future: http://developer.yahoo.net/blog/archives/2008/11/yahoo_openid_test.html

  • Cees-Jan Kiewiet January 02, 2009 at 19:05

    @cakebaker: Ok great to hear, still it’s a scenario to keep in mind that could happen with another openid provider :P.

    Ow btw happy new year :).

  • James Rickard February 13, 2009 at 05:51

    Howdy,
    Firstly thanks for the plugin, it is unreal.

    Secondly a little problem.

    We have had this up and running on our server, but it only works intermittently. It’ll work for a few turns, but then will fail with a require_once error : http://bin.cakephp.org/view/2001796370 (shown here).

    Wondering if you had any solutions to this problem. Everything is up to date, and our server seems to like everything else just fine. Every so often it just fails.

    Our site is http://gradiate.com – if you’d like to have a look.

    Thanks
    james

  • cakebaker February 14, 2009 at 18:12

    @James: Hm, sounds odd. I logged into your site for a few times, but didn’t encounter the error you describe…

    However, I fixed the // which is shown in the paths of your debug output, but I’m not sure whether this is the cause of your issue. Anyway, you can get the updated version from: http://github.com/cakebaker/openid-component/.

    Hope that helps!

  • James Rickard February 18, 2009 at 02:59

    @cakebaker – Thanks muchly for taking the time to look into it. We are still getting the error. Is there something in the server setup I maybe overlooking? I doubt it, but I guess thats where the difference is, somewhere in the background.

    Thanks again
    james

  • cakebaker February 19, 2009 at 17:52

    @James: It’s strange that the issue appears only sporadically…

    My guess is that it is some problem with the include path and ini_set/ini_get (at the top of the Openid component), but I have no idea what… So right now I’m quite clueless :|

  • James Rickard February 20, 2009 at 02:14

    @cakebaker : Thanks heaps for your help. The sporadically issue is the most annoying part of it.

    Anyways, we just went through and hardcoded the require_once links in the openID folder and it seems to be okay now. Knock wood I guess.

    Thanks again for your time.

    james

  • cakebaker February 20, 2009 at 17:38

    @James: Ah, yes, that’s the hardcore approach ;-)

    Anyway, I hope it works fine now.

  • Arne Diekmann February 25, 2009 at 00:04

    Hey mister Cakebaker,

    The plugin is running very smoothly for me, thanks for that! There is only one thing I kept wondering about: When I enter my OpenID preceeded by “https://” the response does not have the same identiy_url compared to entering the OpenID with “http://”.

    This is of course totally correct according to the OpenID Specs and my first idea was to just store the identity_url for a user with the protocol stripped and compare that with the identy_url returned by the authentication process (with the protocol stripped also) and thus making the different identity-urls map to the same user, but the specs also stated that »Relying Parties MUST differentiate between URL Identifiers that have different schemes. When end user input is processed into a URL, it is processed into a HTTP URL. If the same end user controls the same URL, differing only by scheme, and it is desired that the Identifier be the HTTPS URL, it is RECOMMENDED that a redirect be issued from the HTTP URL to the HTTPS URL. Because the HTTP and HTTPS URLs are not equivalent and the Identifier that is used is the URL after following redirects, there is no foreseen reduction in security when using this scheme. If an attacker could gain control of the HTTP URL, it would have no effect on the HTTPS URL, since the HTTP URL is not ever used as an Identifier except to initiate the discovery process.« (http://openid.net/specs/openid-authentication-2_0.html#anchor45)

    Is this something to be done in the Consumer.php or is there a way to accomplish just that with your plugin the easy way? If not I’ll have to go by the stripping-approach or try to find out wether the OpenID library can be taught to do that. Anyway any hint in the right direction would be greatly appreciated!

    Greetings,
    Caffeine

  • cakebaker March 02, 2009 at 17:31

    @Arne: Thanks for your comment!

    Well, as you quoted from the spec, “Relying Parties MUST differentiate between URL Identifiers that have different schemes.”. This means, you violate the spec if you would modify the behavior of Consumer.php (or the OpenID component) to treat https://example.com and http://example.com as the same identifier.

    So, my recommendation is to keep it like it is and to follow the spec ;-)

  • Dave May 11, 2009 at 19:16

    Awesome. This worked flawlessly. Now my apps can be openid enabled. Thanks!

  • Mr-Yellow May 15, 2009 at 08:27

    Can’t see any reason why PHP5 would be needed.

    The OpenID lib is PHP4.

    The OpenID CakePHP component is only a small amount of code to change back to PHP4.

    No reason for PHP5 except to make the script incompatible with most servers.

    -Ben

  • Mr-Yellow May 15, 2009 at 08:30

    No need for PEAR DB package as CakePHP includes all the needed database access with a rewrite of the component to use what is already available.

    -Ben

  • cakebaker May 16, 2009 at 15:13

    @Dave: You are welcome!

    @Ben: Well, PHP4 is officially dead and so it doesn’t make much sense to support it anymore. However, feel free to grab the source from GitHub and modify it accordingly, if you need the component in a PHP4 environment.

    Yes, CakePHP includes all the needed database access functionality, and I considered to use this functionality. However, in the end it was more pragmatic to use what’s already available in the OpenID lib than to write my own CakeMySQLStore.

  • John April 09, 2010 at 19:43

    Any idea if there’s a way to get this component to work with google apps domains? The problem is that there actually need to be two discoveries to find the actual location of the XRDS document for the user. First a discovery on the site XRDS is required which after some tinkering I was able to do easily enough, but when the openid response comes back it is rejected because it is not actually hosted at the domain, but on google’s server. There is a template in the site XRDS to apply the claimed id in order to get the actual location of the user XRDS document.

    For example:

    for example.com the XRDS doc would be located at https://www.google.com/accounts/o8/site-xrds?hd=example.com

    User XRDS docs are located using a similar template https://www.google.com/accounts/o8/user-xrds?uri={URLencodedClaimedID}

    however, the login process returns simply the ClaimedID.

    This is all pretty new to me, so I hope I explained it correctly. My goal is to use google provided apps login for all authentication across the entire domain.

  • Support for Google Apps OpenIDs - cakebaker April 13, 2010 at 17:13

    [...] a recent comment John mentioned that the OpenID component doesn’t work with Google Apps OpenIDs. And he was [...]

  • cakebaker April 13, 2010 at 17:15

    @John: I just released a new version of the OpenID component which supports Google Apps domains, see Support for Google Apps OpenIDs.

  • Andrea April 21, 2010 at 18:30

    I have a problem with integrating this into my existing login system. Following the advice by Cees-Jan, everytime a new user logs in via OpenId, I create a new profile on the system, and associate their openid URL. The problem is that the openid URL assigned by Google and Yahoo (and probably some more providers) is not static, and changes every time a user logs in. I think you take care of this in your component; indeed I am able to login via OpenId; my problem is that I’m not able to see whether this is a new user or an already registered one.

  • cakebaker April 22, 2010 at 17:04

    @Andrea: $response->identity_url contains the unique url for each user you can use to differentiate them.

    Hope this helps!

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License