Rella
Rella

Reputation: 66955

Has any one got class.openid.php working with google openID?

I am trying to study class.openid.php because it is simpler and smaller than
lightopenid
. for my purposes 200 lines do matter. But class.openid.php does not work with google openID https://www.google.com/accounts/o8/id, prints to me such error:

ERROR CODE: OPENID_NOSERVERSFOUND
ERROR DESCRIPTION: Cannot find OpenID Server TAG on Identity page.

is it possible to make class.openid.php (any version) work with google openID and how to do such thing?

class.openid.php can be taken here but it did not worked for me out of the box so I had to find all <? and replace tham with <?php in case someone would like to see code I've got:

html interface page:

<?php
require('class.openid.v3.php');

if ($_POST['openid_action'] == "login"){ // Get identity from user and redirect browser to OpenID Server
    $openid = new SimpleOpenID;
    $openid->SetIdentity($_POST['openid_url']);
    $openid->SetTrustRoot('http://' . $_SERVER["HTTP_HOST"]);
    $openid->SetRequiredFields(array('email','fullname'));
    $openid->SetOptionalFields(array('dob','gender','postcode','country','language','timezone'));
    if ($openid->GetOpenIDServer()){
        $openid->SetApprovedURL('http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PATH_INFO"]);     // Send Response from OpenID server to this script
        $openid->Redirect();    // This will redirect user to OpenID Server
    }else{
        $error = $openid->GetError();
        echo "ERROR CODE: " . $error['code'] . "<br>";
        echo "ERROR DESCRIPTION: " . $error['description'] . "<br>";
    }
    exit;
}
else if($_GET['openid_mode'] == 'id_res'){  // Perform HTTP Request to OpenID server to validate key
    $openid = new SimpleOpenID;
    $openid->SetIdentity($_GET['openid_identity']);
    $openid_validation_result = $openid->ValidateWithServer();
    if ($openid_validation_result == true){         // OK HERE KEY IS VALID
        echo "VALID";
    }else if($openid->IsError() == true){           // ON THE WAY, WE GOT SOME ERROR
        $error = $openid->GetError();
        echo "ERROR CODE: " . $error['code'] . "<br>";
        echo "ERROR DESCRIPTION: " . $error['description'] . "<br>";
    }else{                                          // Signature Verification Failed
        echo "INVALID AUTHORIZATION";
    }
}else if ($_GET['openid_mode'] == 'cancel'){ // User Canceled your Request
    echo "USER CANCELED REQUEST";
}
?>
<html>
<head>
    <title>OpenID Example</title>
</head>
<body>
<div>
<fieldset id="openid">
<legend>OpenID Login</legend>
<form action="<?php echo 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PATH_INFO"]; ?>" method="post" onsubmit="this.login.disabled=true;">
<input type="hidden" name="openid_action" value="login">
<div><input type="text" name="openid_url" class="openid_login"><input type="submit" name="login" value="login &gt;&gt;"></div>
<div><a href="http://www.myopenid.com/" class="link" >Get an OpenID</a></div>
</form>
</fieldset>
</div>
<div style="margin-top: 2em; font-family: arial; font-size: 0.8em; border-top:1px solid gray; padding: 4px;">Sponsored by: <a href="http://www.fivestores.com">FiveStores</a> - get your free online store; includes extensive API for developers; <i style="color: gray;">integrated with  <a href="http://en.wikipedia.org/wiki/OpenID">OpenID</a></i></div>
</body>
</html>

and php class

<?php
/*
    FREE TO USE Under License: GPLv3
    Simple OpenID PHP Class 
    Some modifications by Eddie Roosenmaallen, [email protected]
*/

class SimpleOpenID{
    var $openid_url_identity;
    var $URLs = array();
    var $error = array();
    var $fields = array(
        'required'   => array(),
        'optional'   => array(),
    );

    function SimpleOpenID(){
        if (!function_exists('curl_exec')) {
            die('Error: Class SimpleOpenID requires curl extension to work');
        }
    }

    function SetOpenIDServer($a){
        $this->URLs['openid_server'] = $a;
    }

    function SetTrustRoot($a){
        $this->URLs['trust_root'] = $a;
    }

    function SetCancelURL($a){
        $this->URLs['cancel'] = $a;
    }

    function SetApprovedURL($a){
        $this->URLs['approved'] = $a;
    }

    function SetRequiredFields($a){
        if (is_array($a)){
            $this->fields['required'] = $a;
        }else{
            $this->fields['required'][] = $a;
        }
    }

    function SetOptionalFields($a){
        if (is_array($a)){
            $this->fields['optional'] = $a;
        }else{
            $this->fields['optional'][] = $a;
        }
    }

    function SetIdentity($a){   // Set Identity URL
            if ((stripos($a, 'http://') === false)
               && (stripos($a, 'https://') === false)){
                $a = 'http://'.$a;
            }
            $this->openid_url_identity = $a;
    }

    function GetIdentity(){     // Get Identity
        return $this->openid_url_identity;
    }

    function GetError(){
        $e = $this->error;
        return array('code'=>$e[0],'description'=>$e[1]);
    }

    function ErrorStore($code, $desc = null){
        $errs['OPENID_NOSERVERSFOUND'] = 'Cannot find OpenID Server TAG on Identity page.';
        if ($desc == null){
            $desc = $errs[$code];
        }
        $this->error = array($code,$desc);
    }

    function IsError(){
        if (count($this->error) > 0){
            return true;
        }else{
            return false;
        }
    }

    function splitResponse($response) {
        $r = array();
        $response = explode("\n", $response);
        foreach($response as $line) {
            $line = trim($line);
            if ($line != "") {
                list($key, $value) = explode(":", $line, 2);
                $r[trim($key)] = trim($value);
            }
        }
        return $r;
    }

    function OpenID_Standarize($openid_identity = null){
        if ($openid_identity === null)
            $openid_identity = $this->openid_url_identity;

        $u = parse_url(strtolower(trim($openid_identity)));

        if (!isset($u['path']) || ($u['path'] == '/')) {
            $u['path'] = '';
        }
        if(substr($u['path'],-1,1) == '/'){
            $u['path'] = substr($u['path'], 0, strlen($u['path'])-1);
        }
        if (isset($u['query'])){ // If there is a query string, then use identity as is
            return $u['host'] . $u['path'] . '?' . $u['query'];
        }else{
            return $u['host'] . $u['path'];
        }
    }

    function array2url($arr){ // converts associated array to URL Query String
        if (!is_array($arr)){
            return false;
        }
        $query = '';
        foreach($arr as $key => $value){
            $query .= $key . "=" . $value . "&";
        }
        return $query;
    }

    function CURL_Request($url, $method="GET", $params = "") { // Remember, SSL MUST BE SUPPORTED
            if (is_array($params)) $params = $this->array2url($params);
            $curl = curl_init($url . ($method == "GET" && $params != "" ? "?" . $params : ""));
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($curl, CURLOPT_HEADER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_HTTPGET, ($method == "GET"));
            curl_setopt($curl, CURLOPT_POST, ($method == "POST"));
            if ($method == "POST") curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            $response = curl_exec($curl);

            if (curl_errno($curl) == 0){
                $response;
            }else{
                $this->ErrorStore('OPENID_CURL', curl_error($curl));
            }
            return $response;
    }

     function HTML2OpenIDServer($content) {
        $get = array();

        // Get details of their OpenID server and (optional) delegate
        preg_match_all('/<link[^>]*rel=[\'"]openid.server[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);
        preg_match_all('/<link[^>]*href=\'"([^\'"]+)[\'"][^>]*rel=[\'"]openid.server[\'"][^>]*\/?>/i', $content, $matches2);
        $servers = array_merge($matches1[1], $matches2[1]);

        preg_match_all('/<link[^>]*rel=[\'"]openid.delegate[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);

        preg_match_all('/<link[^>]*href=[\'"]([^\'"]+)[\'"][^>]*rel=[\'"]openid.delegate[\'"][^>]*\/?>/i', $content, $matches2);

        $delegates = array_merge($matches1[1], $matches2[1]);

        $ret = array($servers, $delegates);
        return $ret;
    }

    function GetOpenIDServer(){
        $response = $this->CURL_Request($this->openid_url_identity);
        list($servers, $delegates) = $this->HTML2OpenIDServer($response);
        if (count($servers) == 0){
            $this->ErrorStore('OPENID_NOSERVERSFOUND');
            return false;
        }
        if (isset($delegates[0])
          && ($delegates[0] != "")){
            $this->SetIdentity($delegates[0]);
        }
        $this->SetOpenIDServer($servers[0]);
        return $servers[0];
    }

    function GetRedirectURL(){
        $params = array();
        $params['openid.return_to'] = urlencode($this->URLs['approved']);
        $params['openid.mode'] = 'checkid_setup';
        $params['openid.identity'] = urlencode($this->openid_url_identity);
        $params['openid.trust_root'] = urlencode($this->URLs['trust_root']);

        if (isset($this->fields['required'])
          && (count($this->fields['required']) > 0)) {
            $params['openid.sreg.required'] = implode(',',$this->fields['required']);
        }
        if (isset($this->fields['optional'])
          && (count($this->fields['optional']) > 0)) {
            $params['openid.sreg.optional'] = implode(',',$this->fields['optional']);
        }
        return $this->URLs['openid_server'] . "?". $this->array2url($params);
    }

    function Redirect(){
        $redirect_to = $this->GetRedirectURL();
        if (headers_sent()){ // Use JavaScript to redirect if content has been previously sent (not recommended, but safe)
            echo '<script language="JavaScript" type="text/javascript">window.location=\'';
            echo $redirect_to;
            echo '\';</script>';
        }else{  // Default Header Redirect
            header('Location: ' . $redirect_to);
        }
    }

    function ValidateWithServer(){
        $params = array(
            'openid.assoc_handle' => urlencode($_GET['openid_assoc_handle']),
            'openid.signed' => urlencode($_GET['openid_signed']),
            'openid.sig' => urlencode($_GET['openid_sig'])
        );
        // Send only required parameters to confirm validity
        $arr_signed = explode(",",str_replace('sreg.','sreg_',$_GET['openid_signed']));
        for ($i=0; $i<count($arr_signed); $i++){
            $s = str_replace('sreg_','sreg.', $arr_signed[$i]);
            $c = $_GET['openid_' . $arr_signed[$i]];
            // if ($c != ""){
                $params['openid.' . $s] = urlencode($c);
            // }
        }
        $params['openid.mode'] = "check_authentication";

        $openid_server = $this->GetOpenIDServer();
        if ($openid_server == false){
            return false;
        }
        $response = $this->CURL_Request($openid_server,'POST',$params);
        $data = $this->splitResponse($response);

        if ($data['is_valid'] == "true") {
            return true;
        }else{
            return false;
        }
    }
}
?>

Upvotes: 1

Views: 1515

Answers (3)

Mewp
Mewp

Reputation: 4715

The class in your question does not support OpenID 2.0 at all. Therefore, it will not work with Google without adding a lot of code.

Upvotes: 1

The Surrican
The Surrican

Reputation: 29864

The problem is that Google doesn't just supply an OpenID endpoint.

OpenId endpoints include an identifier for the user.

What we are having here is called a Discovery Url.

This is a static url that you can direct any user to, and the service itself will recognise the user and return a per-user unique identifying url.

This however is NOT implemented correctly by most openid client libraries, including the majority linked on the official openid website.

Even the Zend Framework libraries are incapable of handling that.

However I found a class that I analysed from various perspectives and that I am very satisfied with. At the company I work at we already integrated it successfully in several production environments and have not experienced any problems.

You may also be interested in another post of mine dealing with the issue of making Facebook an openid Provider. The class I am using, that also supports Google, can also be found there:

Best way to implement Single-Sign-On with all major providers?

Upvotes: 4

ChristopheCVB
ChristopheCVB

Reputation: 7315

Are you searching something like : http://wiki.openid.net/w/page/12995176/Libraries ?

There is a PHP section in that.

Upvotes: 1

Related Questions