在 Janrain 的 OpenID PHP 库登录后无法检索 Google 用户信息


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

我开始说我讨厌OpenID,因为它的实现/文档很差。

我正在尝试使用"openid-php-openid-2.2.2-24"。这里的源代码:https://github.com/openid/php-openid

当我尝试使用身份验证示例时,它会返回给我:"您已成功验证 https://www.google.com/accounts/o8/id?id=[...]作为您的身份。

提供商没有发送PAPE回复。

但是没有电子邮件,昵称或Google OpenID登录数据的全名的影子。在读取文件("/openid/examples/consumer/finish_auth.php")时,我注意到必须在"您已成功验证"和"无 PAPE 响应"消息之间打印 SREG 变量,但它们没有:

    $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>";
}

我尝试打印$sreg["电子邮件"],$sreg["昵称"]和$sreg["全名"]的内容,但它们返回所有空白内容(空/空值)。

我需要检索用户用于登录的帐户的电子邮件地址。

但丁

为了将问题从未回答的列表中删除,我在这里发布但丁的答案作为答案:


解决了我的问题。AX 在 PHP OpenID 中的用法示例:AX 在 PHP OpenID 中的用法示例经过 2 天的研究,我刚刚找到了答案("但谷歌使用 AX(属换)而不是 SReg 来获取其他数据")。为什么谷歌总是如此不同?

但是,该堆栈溢出答案页面中的代码对我不起作用(我的托管服务器返回 500 个内部服务器错误代码)。所以,我在这里发布"我的代码"(它太粗糙了):

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();
?>

享受。

但丁

PS:要完成OpenID的操作,虽然我用Google解决了用户信息/登录数据的问题,但我仍然有一个Light OpenID问题(https://stackoverflow.com/questions/10735708/lightopenid-openid-authurl-does-not-return-any-value)。如果你想帮助我,我们将完全解决并以OpenID故事结束。