New version of the OpenID component

Published on 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

79 comments baked

  • klevo

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

    Anyway great component, thanks!

  • cakebaker

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

  • Matti Putkonen

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

  • cakebaker

    @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

    [...] 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

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

  • Jeremy

    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

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

  • Jeremy

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

  • Jeremy

    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

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

  • CakePHP and OpenID - cakebaker

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

  • knud

    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

    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

    @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

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

  • cakebaker

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

  • knud

    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

    @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

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

  • cakebaker

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

  • knud

    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

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

  • Calin Don

    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

    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

    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

    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

    @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

    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

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

  • knud

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

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

  • cakebaker

    @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

    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

    @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

    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

    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

    @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/

    @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

    @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

    @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

    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

    @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

    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

    @Knud: Cool, looks nice :)

  • WyriHaximus

    @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

    Thank, this is now fixed.

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

  • Neters Landreau

    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

    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

    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

    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

    @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

    @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

    @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

    @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

    @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

    @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

    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

    @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

    @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

    @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

    @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

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

    Anyway, I hope it works fine now.

  • Arne Diekmann

    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

    @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

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

  • Mr-Yellow

    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

    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

    @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

    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

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

  • cakebaker

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

  • Andrea

    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

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

    Hope this helps!

  • Brendan

    This does not appear to support anything that uses HTTPS. I could not get it to work for Google or for Yahoo.

    It does, however, work for simple URLs like myOpenID

    Any information on how I can get this to work with Google and Yahoo too?

  • cakebaker

    @Brendan: Hm, is OpenSSL installed and enabled in your php.ini?

  • PelleP

    I am trying to get the component working on my project, but it seems like something is redirecting to the $returnTo path by itself and it newer comes into the handleOpenIDResponse() function. In my adress field I got this long get-statement and the authorization with myOpenID works. What to do? Please help! :)

  • cakebaker

    @PelleP: Hm, I’m not sure I understand what you mean… It works with an OpenID from myOpenID, but not with other OpenIDs? If that’s the case, what OpenIDs don’t work?

    Plus can you show some code (for example as a Gist)?

  • PelleP

    @cakebaker. Sorry for taking up your time. My problem was quite stupid. I had set the routing wrong so I got redirected to my index page instead of being sent back to the usersController.

  • cakebaker

    @PelleP: No problem, I’m glad you could fix the issue :)

Bake a comment




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

© daniel hofstetter. Licensed under a Creative Commons License