Can't Retrieve Google User Info After Janrain's OpenID PHP Library Login

947 views Asked by At

I start saying that I HATE OpenID, because it's poorly implemented/documented.

I'm trying to use "openid-php-openid-2.2.2-24". Here the source code: https://github.com/openid/php-openid

When I try to use the authentication example, it returns to me: "You have successfully verified https://www.google.com/accounts/o8/id?id=[...] as your identity.

No PAPE response was sent by the provider."

but there's no shadow of email, nickname or fullname of google openid login data. While reading the file ("/openid/examples/consumer/finish_auth.php"), I note that SREG variables have to be printed between the "You have successfully verified" and "No PAPE response" messages, but they don't:

    $success = sprintf('You have successfully verified ' .
                       '<a href="%s">%s</a> as your identity.',
                       $esc_identity, $esc_identity);

    if ($response->endpoint->canonicalID) {
        $escaped_canonicalID = escape($response->endpoint->canonicalID);
        $success .= '  (XRI CanonicalID: '.$escaped_canonicalID.') ';
    }

    $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);

    $sreg = $sreg_resp->contents();

    if (@$sreg['email']) {
        $success .= "  You also returned '".escape($sreg['email']).
            "' as your email.";
    }

    if (@$sreg['nickname']) {
        $success .= "  Your nickname is '".escape($sreg['nickname']).
            "'.";
        $_SESSION['nickname'] = escape($sreg['nickname']);
    }

    if (@$sreg['fullname']) {
        $success .= "  Your fullname is '".escape($sreg['fullname']).
            "'.";
    }

$pape_resp = Auth_OpenID_PAPE_Response::fromSuccessResponse($response);

if ($pape_resp) {
    [...]
} else {
        $success .= "<p>No PAPE response was sent by the provider.</p>";
}

I've tried to print the content of $sreg['email'], $sreg['nickname'] and $sreg['fullname'], but they return all blank contents (null/empty values).

I need to retrieve the email address of the account which users use to login in..

Dante

1

There are 1 answers

0
cweiske On

To get the question off the unanswered list, I post dante's answer here as answer:


I solved my problem. Example usage of AX in PHP OpenID: Example usage of AX in PHP OpenID After 2 days of research, I've just now found the answer ("but Google uses AX (attribute exchange) instead of SReg for additional data"). Why Google must always be so different?

However, the code in that stackoverflow answer page doesn't work for me (my hosting server returns 500 internal server error code). So, I post here "my code" (it's so rough):

oid_ax_common.php

<?php

// Circumnavigate bugs in the GMP math library that can be result in signature
// validation errors
define('Auth_OpenID_BUGGY_GMP', true);

$path_extra = dirname(dirname(dirname(__FILE__)));
$path = ini_get('include_path');
$path = $path_extra . PATH_SEPARATOR . $path;
ini_set('include_path', $path);


function displayError($message) {
    $error = $message;
    include './index.php';
    exit(0);
}

function doIncludes() {
    /**
     * Require the OpenID consumer code.
     */
    require_once "Auth/OpenID/Consumer.php";

    /**
     * Require the "file store" module, which we'll need to store
     * OpenID information.
     */
    require_once "Auth/OpenID/FileStore.php";

    /**
     * Require the Simple Registration extension API.
     */
    //require_once "Auth/OpenID/SReg.php";
    require_once "Auth/OpenID/AX.php";

    /**
     * Require the PAPE extension module.
     */
    require_once "Auth/OpenID/PAPE.php";
}

doIncludes();

global $pape_policy_uris;
$pape_policy_uris = array(
              PAPE_AUTH_MULTI_FACTOR_PHYSICAL,
              PAPE_AUTH_MULTI_FACTOR,
              PAPE_AUTH_PHISHING_RESISTANT
              );

function &getStore() {
    /**
     * This is where the example will store its OpenID information.
     * You should change this path if you want the example store to be
     * created elsewhere.  After you're done playing with the example
     * script, you'll have to remove this directory manually.
     */
    $store_path = null;
    if (function_exists('sys_get_temp_dir')) {
        $store_path = sys_get_temp_dir();
    }
    else {
        if (strpos(PHP_OS, 'WIN') === 0) {
            $store_path = $_ENV['TMP'];
            if (!isset($store_path)) {
                $dir = 'C:\Windows\Temp';
            }
        }
        else {
            $store_path = @$_ENV['TMPDIR'];
            if (!isset($store_path)) {
                $store_path = '/tmp';
            }
        }
    }
    $store_path = './tmp/';
    $store_path .= DIRECTORY_SEPARATOR . '_php_consumer_test';

    if (!file_exists($store_path) &&
        !mkdir($store_path)) {
        print "Could not create the FileStore directory '$store_path'. ".
            " Please check the effective permissions.";
        exit(0);
    }
    $r = new Auth_OpenID_FileStore($store_path);

    return $r;
}

function &getConsumer() {
    /**
     * Create a consumer object using the store object created
     * earlier.
     */
    $store = getStore();
    $r = new Auth_OpenID_Consumer($store);
    return $r;
}

function getScheme() {
    $scheme = 'http';
    if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') {
        $scheme .= 's';
    }
    return $scheme;
}

function getReturnTo() {
    return sprintf("%s://%s:%s%s/oid_ax_receive.php",
                   getScheme(), $_SERVER['SERVER_NAME'],
                   $_SERVER['SERVER_PORT'],
                   dirname($_SERVER['PHP_SELF']));
}

function getTrustRoot() {
    return sprintf("%s://%s:%s%s/",
                   getScheme(), $_SERVER['SERVER_NAME'],
                   $_SERVER['SERVER_PORT'],
                   dirname($_SERVER['PHP_SELF']));
}

?>

oid_ax_send.php

<?php

require_once "oid_ax_common.php";
// Starts session (needed for YADIS)
session_start();

function getOpenIDURL() {
    // Render a default page if we got a submission without an openid
    // value.
    if (empty($_GET['openid_identifier'])) {
        $error = "Expected an OpenID URL.";
        include './index.php';
        exit(0);
    }

    return $_GET['openid_identifier'];
}

function run() {
    // https://www.google.com/accounts/o8/id
    // $openid = 'http://openid-provider.appspot.com/';
    $openid = 'https://www.google.com/accounts/o8/id';
    // $openid .= getOpenIDURL();
    $consumer = getConsumer();

    // Begin the OpenID authentication process.
    $auth_request = $consumer->begin($openid);

    // Create attribute request object
    // See http://code.google.com/apis/accounts/docs/OpenID.html#Parameters for parameters
    // Usage: make($type_uri, $count=1, $required=false, $alias=null)
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/contact/email',2,1, 'email');
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/first',1,1, 'firstname');
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/last',1,1, 'lastname');

    // Create AX fetch request
    $ax = new Auth_OpenID_AX_FetchRequest;

    // Add attributes to AX fetch request
    foreach($attribute as $attr){
        $ax->add($attr);
    }

    // Add AX fetch request to authentication request
    $auth_request->addExtension($ax);

    // No auth request means we can't begin OpenID.
    if (!$auth_request) {
        displayError("Authentication error; not a valid OpenID.");
    }

    /* $sreg_request = Auth_OpenID_SRegRequest::build(
                                     // Required
                                     array('nickname'),
                                     // Optional
                                     array('fullname', 'email'));

    if ($sreg_request) {
        $auth_request->addExtension($sreg_request);
    } */

    $policy_uris = null;
    if (isset($_GET['policies'])) {
        $policy_uris = $_GET['policies'];
    }

    $pape_request = new Auth_OpenID_PAPE_Request($policy_uris);
    if ($pape_request) {
        $auth_request->addExtension($pape_request);
    }

    // Redirect the user to the OpenID server for authentication.
    // Store the token for this authentication so we can verify the
    // response.

    // For OpenID 1, send a redirect.  For OpenID 2, use a Javascript
    // form to send a POST request to the server.
    if ($auth_request->shouldSendRedirect()) {
        $redirect_url = $auth_request->redirectURL(getTrustRoot(),
                                                   getReturnTo());

        // If the redirect URL can't be built, display an error
        // message.
        if (Auth_OpenID::isFailure($redirect_url)) {
            displayError("Could not redirect to server: " . $redirect_url->message);
        } else {
            // Send redirect.
            header("Location: ".$redirect_url);
        }
    } else {
        // Generate form markup and render it.
        $form_id = 'openid_message';
        $form_html = $auth_request->htmlMarkup(getTrustRoot(), getReturnTo(),
                                               false, array('id' => $form_id));

        // Display an error if the form markup couldn't be generated;
        // otherwise, render the HTML.
        if (Auth_OpenID::isFailure($form_html)) {
            displayError("Could not redirect to server: " . $form_html->message);
        } else {
            print $form_html;
        }
    }
}

run();

?>

oid_ax_receive.php

<?php

require_once "oid_ax_common.php";
// Starts session (needed for YADIS)
session_start();

function escape($thing) {
    return htmlentities($thing);
}

function run() {
    $consumer = getConsumer();

    // Complete the authentication process using the server's
    // response.
    $return_to = getReturnTo();
    $response = $consumer->complete($return_to);

    // Check the response status.
    if ($response->status == Auth_OpenID_CANCEL) {
        // This means the authentication was cancelled.
        $msg = 'Verification cancelled.';
    } else if ($response->status == Auth_OpenID_FAILURE) {
        // Authentication failed; display the error message.
        $msg = "OpenID authentication failed: " . $response->message;
    } else if ($response->status == Auth_OpenID_SUCCESS) {
        // Get registration informations
        $ax = new Auth_OpenID_AX_FetchResponse();
        $obj = $ax->fromSuccessResponse($response);

        // Print me raw
        echo '<pre>';
        print_r($obj->data);
        echo '</pre>';
        exit;

        $pape_resp = Auth_OpenID_PAPE_Response::fromSuccessResponse($response);

        if ($pape_resp) {
            if ($pape_resp->auth_policies) {
                $success .= "<p>The following PAPE policies affected the authentication:</p><ul>";

                foreach ($pape_resp->auth_policies as $uri) {
                    $escaped_uri = escape($uri);
                    $success .= "<li><tt>$escaped_uri</tt></li>";
                }

                $success .= "</ul>";
            } else {
                $success .= "<p>No PAPE policies affected the authentication.</p>";
            }

            if ($pape_resp->auth_age) {
                $age = escape($pape_resp->auth_age);
                $success .= "<p>The authentication age returned by the " .
                    "server is: <tt>".$age."</tt></p>";
            }

            if ($pape_resp->nist_auth_level) {
                $auth_level = escape($pape_resp->nist_auth_level);
                $success .= "<p>The NIST auth level returned by the " .
                    "server is: <tt>".$auth_level."</tt></p>";
            }

        } else {
                $success .= "<p>No PAPE response was sent by the provider.</p>";
        }

    }

    include './index.php';
}

run();

?>

Enjoy.

Dante

P.S.: to complete the opera of OpenID, although I solved my problem with user info / login data with Google, I still have one problem with Light OpenID (https://stackoverflow.com/questions/10735708/lightopenid-openid-authurl-does-not-return-any-value). If you want to help me, we will completely work out and conclude with the OpenID story.