Issue #556380 by deekayen, ParisLiakos, cweagans: Remove OpenID from core.
parent
f150c849b2
commit
7ee44e459a
|
@ -36,6 +36,7 @@ Drupal 8.0, xxxx-xx-xx (development version)
|
|||
modules with similar functionality are available:
|
||||
* Blog
|
||||
* Dashboard
|
||||
* OpenID
|
||||
* Poll
|
||||
* Profile
|
||||
* Trigger
|
||||
|
|
|
@ -270,11 +270,6 @@ Node module
|
|||
- Moshe Weitzman 'moshe weitzman' http://drupal.org/user/23
|
||||
- David Strauss 'David Strauss' http://drupal.org/user/93254
|
||||
|
||||
OpenID module
|
||||
- Vojtech Kusy 'wojtha' http://drupal.org/user/56154
|
||||
- Christian Schmidt 'c960657' http://drupal.org/user/216078
|
||||
- Damien Tournoud 'DamZ' http://drupal.org/user/22211
|
||||
|
||||
Overlay module
|
||||
- ?
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
xri_proxy_resolver: 'http://xri.net/'
|
|
@ -1,9 +0,0 @@
|
|||
# Schema for the configuration files of the openid module.
|
||||
|
||||
openid.settings:
|
||||
type: mapping
|
||||
label: 'OpenID settings'
|
||||
mapping:
|
||||
xri_proxy_resolver:
|
||||
type: string
|
||||
label: 'Proxy resolver for XRI'
|
|
@ -1,110 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\openid\Form\UserDeleteForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\openid\Form;
|
||||
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\ControllerInterface;
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\user\UserInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a form to delete a user's Open ID identity.
|
||||
*/
|
||||
class UserDeleteForm extends ConfirmFormBase implements ControllerInterface {
|
||||
|
||||
/**
|
||||
* The user account.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* The account identity ID.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $aid;
|
||||
|
||||
/**
|
||||
* The database connection.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Connection
|
||||
*/
|
||||
protected $database;
|
||||
|
||||
/**
|
||||
* Constructs a new UserDeleteForm object.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $database
|
||||
* The database connection.
|
||||
*/
|
||||
public function __construct(Connection $database) {
|
||||
$this->database = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('database')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getQuestion() {
|
||||
$identifier = $this->database->query("SELECT identifier FROM {openid_identities} WHERE uid = :uid AND aid = :aid", array(
|
||||
':uid' => $this->account->id(),
|
||||
':aid' => $this->aid,
|
||||
))->fetchField();
|
||||
return t('Are you sure you want to delete the OpenID %identifier for %user?', array('%identifier' => $identifier, '%user' => $this->account->label()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getCancelPath() {
|
||||
return 'user/' . $this->account->id() . '/openid';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormID() {
|
||||
return 'openid_user_delete_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, array &$form_state, UserInterface $account = NULL, $aid = NULL) {
|
||||
$this->aid = $aid;
|
||||
$this->account = $account;
|
||||
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, array &$form_state) {
|
||||
$query = $this->database->delete('openid_identities')
|
||||
->condition('uid', $this->account->id())
|
||||
->condition('aid', $this->aid)
|
||||
->execute();
|
||||
if ($query) {
|
||||
drupal_set_message(t('OpenID deleted.'));
|
||||
}
|
||||
$form_state['redirect'] = 'user/' . $this->account->id() . '/openid';
|
||||
}
|
||||
|
||||
}
|
|
@ -1,404 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\openid\Tests\OpenIDFunctionalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\openid\Tests;
|
||||
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Test discovery and login using OpenID
|
||||
*/
|
||||
class OpenIDFunctionalTest extends OpenIDTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('openid_test');
|
||||
|
||||
protected $web_user;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'OpenID discovery and login',
|
||||
'description' => "Adds an identity to a user's profile and uses it to log in.",
|
||||
'group' => 'OpenID'
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// User doesn't need special permissions; only the ability to log in.
|
||||
$this->web_user = $this->drupalCreateUser(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test discovery of OpenID Provider Endpoint via Yadis and HTML.
|
||||
*/
|
||||
function testDiscovery() {
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
// The User-supplied Identifier entered by the user may indicate the URL of
|
||||
// the OpenID Provider Endpoint in various ways, as described in OpenID
|
||||
// Authentication 2.0 and Yadis Specification 1.0.
|
||||
// Note that all of the tested identifiers refer to the same endpoint, so
|
||||
// only the first will trigger an associate request in openid_association()
|
||||
// (association is only done the first time Drupal encounters a given
|
||||
// endpoint).
|
||||
|
||||
|
||||
// Yadis discovery (see Yadis Specification 1.0, section 6.2.5):
|
||||
// If the User-supplied Identifier is a URL, it may be a direct or indirect
|
||||
// reference to an XRDS document (a Yadis Resource Descriptor) that contains
|
||||
// the URL of the OpenID Provider Endpoint.
|
||||
|
||||
// Identifier is the URL of an XRDS document.
|
||||
// On HTTP test environments, the URL scheme is stripped in order to test
|
||||
// that the supplied identifier is normalized in openid_begin().
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->addIdentity(preg_replace('@^http://@', '', $identity), 2, 'http://example.com/xrds', $identity);
|
||||
|
||||
$identity = url('openid-test/yadis/xrds/delegate', array('absolute' => TRUE));
|
||||
$this->addIdentity(preg_replace('@^http://@', '', $identity), 2, 'http://example.com/xrds-delegate', $identity);
|
||||
|
||||
// Identifier is the URL of an XRDS document containing an OP Identifier
|
||||
// Element. The Relying Party sends the special value
|
||||
// "http://specs.openid.net/auth/2.0/identifier_select" as Claimed
|
||||
// Identifier. The OpenID Provider responds with the actual identifier
|
||||
// including the fragment.
|
||||
$identity = url('openid-test/yadis/xrds/dummy-user', array('absolute' => TRUE, 'fragment' => $this->randomName()));
|
||||
// Tell openid_test.module to respond with this identifier. If the fragment
|
||||
// part is present in the identifier, it should be retained.
|
||||
state()->set('openid_test.response', array('openid.claimed_id' => $identity));
|
||||
$this->addIdentity(url('openid-test/yadis/xrds/server', array('absolute' => TRUE)), 2, 'http://specs.openid.net/auth/2.0/identifier_select', $identity);
|
||||
state()->set('openid_test.response', array());
|
||||
|
||||
// Identifier is the URL of an HTML page that is sent with an HTTP header
|
||||
// that contains the URL of an XRDS document.
|
||||
$this->addIdentity(url('openid-test/yadis/x-xrds-location', array('absolute' => TRUE)), 2);
|
||||
|
||||
// Identifier is the URL of an HTML page containing a <meta http-equiv=...>
|
||||
// element that contains the URL of an XRDS document.
|
||||
$this->addIdentity(url('openid-test/yadis/http-equiv', array('absolute' => TRUE)), 2);
|
||||
|
||||
// Identifier is an XRI. Resolve using our own dummy proxy resolver.
|
||||
config('openid.settings')
|
||||
->set('xri_proxy_resolver', url('openid-test/yadis/xrds/xri', array('absolute' => TRUE)) . '/')
|
||||
->save();
|
||||
$this->addIdentity('@example*résumé;%25', 2, 'http://example.com/xrds', 'http://example.com/user');
|
||||
|
||||
// Make sure that unverified CanonicalID are not trusted.
|
||||
state()->set('openid_test.canonical_id_status', 'bad value');
|
||||
$this->addIdentity('@example*résumé;%25', 2, FALSE, FALSE);
|
||||
|
||||
// HTML-based discovery:
|
||||
// If the User-supplied Identifier is a URL of an HTML page, the page may
|
||||
// contain a <link rel=...> element containing the URL of the OpenID
|
||||
// Provider Endpoint. OpenID 1 and 2 describe slightly different formats.
|
||||
|
||||
// OpenID Authentication 1.1, section 3.1:
|
||||
$this->addIdentity(url('openid-test/html/openid1', array('absolute' => TRUE)), 1, 'http://example.com/html-openid1');
|
||||
|
||||
// OpenID Authentication 2.0, section 7.3.3:
|
||||
$this->addIdentity(url('openid-test/html/openid2', array('absolute' => TRUE)), 2, 'http://example.com/html-openid2');
|
||||
|
||||
// OpenID Authentication 2.0, section 7.2.4:
|
||||
// URL Identifiers MUST then be further normalized by both (1) following
|
||||
// redirects when retrieving their content and finally (2) applying the
|
||||
// rules in Section 6 of RFC3986 to the final destination URL. This final
|
||||
// URL MUST be noted by the Relying Party as the Claimed Identifier and be
|
||||
// used when requesting authentication.
|
||||
|
||||
// Single redirect.
|
||||
$identity = $expected_claimed_id = url('openid-test/redirected/yadis/xrds/1', array('absolute' => TRUE));
|
||||
$this->addRedirectedIdentity($identity, 2, 'http://example.com/xrds', $expected_claimed_id, 0);
|
||||
|
||||
// Exactly 5 redirects (default value for the max redirects setting).
|
||||
$identity = $expected_claimed_id = url('openid-test/redirected/yadis/xrds/2', array('absolute' => TRUE));
|
||||
$this->addRedirectedIdentity($identity, 2, 'http://example.com/xrds', $expected_claimed_id, 4);
|
||||
|
||||
// Fails because there are more than 5 redirects.
|
||||
$identity = url('openid-test/redirected/yadis/xrds/3', array('absolute' => TRUE));
|
||||
$expected_claimed_id = FALSE;
|
||||
$this->addRedirectedIdentity($identity, 2, 'http://example.com/xrds', $expected_claimed_id, 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test login using OpenID.
|
||||
*/
|
||||
function testLogin() {
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->addIdentity($identity);
|
||||
$response = state()->get('openid_test.hook_openid_response_response');
|
||||
$account = state()->get('openid_test.hook_openid_response_account');
|
||||
$this->assertEqual($response['openid.claimed_id'], $identity, 'hook_openid_response() was invoked.');
|
||||
$this->assertEqual($account->uid, $this->web_user->uid, 'Proper user object passed to hook_openid_response().');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Test logging in via the login block on the front page.
|
||||
state()->delete('openid_test.hook_openid_response_response');
|
||||
state()->delete('openid_test.hook_openid_response_account');
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
$response = state()->get('openid_test.hook_openid_response_response');
|
||||
$account = state()->get('openid_test.hook_openid_response_account');
|
||||
$this->assertEqual($response['openid.claimed_id'], $identity, 'hook_openid_response() was invoked.');
|
||||
$this->assertEqual($account->uid, $this->web_user->uid, 'Proper user object passed to hook_openid_response().');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Test logging in via the user/login/openid page.
|
||||
$edit = array('openid_identifier' => $identity);
|
||||
$this->drupalPost('user/login/openid', $edit, t('Log in'));
|
||||
|
||||
// Check we are on the OpenID redirect form.
|
||||
$this->assertTitle(t('OpenID redirect'), 'OpenID redirect page was displayed.');
|
||||
|
||||
// Submit form to the OpenID Provider Endpoint.
|
||||
$this->drupalPost(NULL, array(), t('Send'));
|
||||
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
|
||||
// Verify user was redirected away from user/login/openid to an accessible
|
||||
// page.
|
||||
$this->assertResponse(200);
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Tell openid_test.module to alter the checkid_setup request.
|
||||
$new_identity = 'http://example.com/' . $this->randomName();
|
||||
state()->set('openid_test.identity', $new_identity);
|
||||
state()->set('openid_test.request_alter', array('checkid_setup' => array('openid.identity' => $new_identity)));
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
$response = state()->get('openid_test.hook_openid_response_response');
|
||||
$this->assertEqual($response['openid.identity'], $new_identity, 'hook_openid_request_alter() were invoked.');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
// Tell the test module to add a doctype. This should fail.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE, 'query' => array('doctype' => 1)));
|
||||
// Test logging in via the login block on the front page.
|
||||
$edit = array('openid_identifier' => $identity);
|
||||
$this->drupalPost('', $edit, t('Log in'), array(), array(), 'openid-login-form');
|
||||
$this->assertRaw(t('Sorry, that is not a valid OpenID. Ensure you have spelled your ID correctly.'), 'XML with DOCTYPE was rejected.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test login using OpenID during maintenance mode.
|
||||
*/
|
||||
function testLoginMaintenanceMode() {
|
||||
$this->web_user = $this->drupalCreateUser(array('access site in maintenance mode'));
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->addIdentity($identity);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Enable maintenance mode.
|
||||
config('system.maintenance')->set('enabled', TRUE)->save();
|
||||
|
||||
// Test logging in via the user/login/openid page while the site is offline.
|
||||
$edit = array('openid_identifier' => $identity);
|
||||
$this->drupalPost('user/login/openid', $edit, t('Log in'));
|
||||
|
||||
// Check we are on the OpenID redirect form.
|
||||
$this->assertTitle(t('OpenID redirect'), 'OpenID redirect page was displayed.');
|
||||
|
||||
// Submit form to the OpenID Provider Endpoint.
|
||||
$this->drupalPost(NULL, array(), t('Send'));
|
||||
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
|
||||
// Verify user was redirected away from user/login/openid to an accessible
|
||||
// page.
|
||||
$this->assertText(t('Operating in maintenance mode.'));
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deleting an OpenID identity from a user's profile.
|
||||
*/
|
||||
function testDelete() {
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
// Add identity to user's profile.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->addIdentity($identity);
|
||||
$this->assertText($identity, 'Identity appears in list.');
|
||||
|
||||
// Delete the newly added identity.
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->drupalPost(NULL, array(), t('Confirm'));
|
||||
|
||||
$this->assertText(t('OpenID deleted.'), 'Identity deleted');
|
||||
$this->assertNoText($identity, 'Identity no longer appears in list.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a blocked user cannot log in.
|
||||
*/
|
||||
function testBlockedUserLogin() {
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
|
||||
// Log in and add an OpenID Identity to the account.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->addIdentity($identity);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Log in as an admin user and block the account.
|
||||
$admin_user = $this->drupalCreateUser(array('administer users'));
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('admin/people');
|
||||
$edit = array(
|
||||
'operation' => 'block',
|
||||
'accounts[' . $this->web_user->uid . ']' => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/people', $edit, t('Update'));
|
||||
$this->assertRaw('The update has been performed.', 'Account was blocked.');
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertRaw(t('The username %name has not been activated or is blocked.', array('%name' => $this->web_user->name)), 'User login was blocked.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add OpenID identity to user's profile.
|
||||
*
|
||||
* @param $identity
|
||||
* The User-supplied Identifier.
|
||||
* @param $version
|
||||
* The protocol version used by the service.
|
||||
* @param $local_id
|
||||
* The expected OP-Local Identifier found during discovery.
|
||||
* @param $claimed_id
|
||||
* The expected Claimed Identifier returned by the OpenID Provider, or FALSE
|
||||
* if the discovery is expected to fail.
|
||||
*/
|
||||
function addIdentity($identity, $version = 2, $local_id = 'http://example.com/xrds', $claimed_id = NULL) {
|
||||
// Tell openid_test.module to only accept this OP-Local Identifier.
|
||||
state()->set('openid_test.identity', $local_id);
|
||||
|
||||
$edit = array('openid_identifier' => $identity);
|
||||
$this->drupalPost('user/' . $this->web_user->uid . '/openid', $edit, t('Add an OpenID'));
|
||||
|
||||
if ($claimed_id === FALSE) {
|
||||
$this->assertRaw(t('Sorry, that is not a valid OpenID. Ensure you have spelled your ID correctly.'), 'Invalid identity was rejected.');
|
||||
return;
|
||||
}
|
||||
|
||||
// OpenID 1 used a HTTP redirect, OpenID 2 uses a HTML form that is submitted automatically using JavaScript.
|
||||
if ($version == 2) {
|
||||
// Check we are on the OpenID redirect form.
|
||||
$this->assertTitle(t('OpenID redirect'), 'OpenID redirect page was displayed.');
|
||||
|
||||
// Submit form to the OpenID Provider Endpoint.
|
||||
$this->drupalPost(NULL, array(), t('Send'));
|
||||
}
|
||||
|
||||
if (!isset($claimed_id)) {
|
||||
$claimed_id = $identity;
|
||||
}
|
||||
$this->assertRaw(t('Successfully added %identity', array('%identity' => $claimed_id)), format_string('Identity %identity was added.', array('%identity' => $identity)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add OpenID identity, changed by the following redirects, to user's profile.
|
||||
*
|
||||
* According to OpenID Authentication 2.0, section 7.2.4, URL Identifiers MUST
|
||||
* be further normalized by following redirects when retrieving their content
|
||||
* and this final URL MUST be noted by the Relying Party as the Claimed
|
||||
* Identifier and be used when requesting authentication.
|
||||
*
|
||||
* @param $identity
|
||||
* The User-supplied Identifier.
|
||||
* @param $version
|
||||
* The protocol version used by the service.
|
||||
* @param $local_id
|
||||
* The expected OP-Local Identifier found during discovery.
|
||||
* @param $claimed_id
|
||||
* The expected Claimed Identifier returned by the OpenID Provider, or FALSE
|
||||
* if the discovery is expected to fail.
|
||||
* @param $redirects
|
||||
* The number of redirects.
|
||||
*/
|
||||
function addRedirectedIdentity($identity, $version = 2, $local_id = 'http://example.com/xrds', $claimed_id = NULL, $redirects = 0) {
|
||||
// Set the final destination URL which is the same as the Claimed
|
||||
// Identifier, we insert the same identifier also to the provider response,
|
||||
// but provider could further change the Claimed ID actually (e.g. it could
|
||||
// add unique fragment).
|
||||
state()->set('openid_test.redirect_url', $identity);
|
||||
state()->set('openid_test.response', array('openid.claimed_id' => $identity));
|
||||
|
||||
$this->addIdentity(url('openid-test/redirect/' . $redirects, array('absolute' => TRUE)), $version, $local_id, $claimed_id);
|
||||
|
||||
// Clean up.
|
||||
state()->delete('openid_test.redirect_url');
|
||||
state()->delete('openid_test.response');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that openid.signed is verified.
|
||||
*/
|
||||
function testSignatureValidation() {
|
||||
module_load_include('inc', 'openid');
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
|
||||
// Respond with an invalid signature.
|
||||
state()->set('openid_test.response', array('openid.sig' => 'this-is-an-invalid-signature'));
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertRaw('OpenID login failed.');
|
||||
|
||||
// Do not sign the mandatory field openid.assoc_handle.
|
||||
state()->set('openid_test.response', array('openid.signed' => 'op_endpoint,claimed_id,identity,return_to,response_nonce'));
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertRaw('OpenID login failed.');
|
||||
|
||||
// Sign all mandatory fields and a custom field.
|
||||
$keys_to_sign = array('op_endpoint', 'claimed_id', 'identity', 'return_to', 'response_nonce', 'assoc_handle', 'foo');
|
||||
$association = new stdClass();
|
||||
$association->mac_key = NULL;
|
||||
$response = array(
|
||||
'openid.op_endpoint' => url('openid-test/endpoint', array('absolute' => TRUE)),
|
||||
'openid.claimed_id' => $identity,
|
||||
'openid.identity' => $identity,
|
||||
'openid.return_to' => url('openid/authenticate', array('absolute' => TRUE)),
|
||||
'openid.response_nonce' => _openid_nonce(),
|
||||
'openid.assoc_handle' => 'openid-test',
|
||||
'openid.foo' => 123,
|
||||
'openid.signed' => implode(',', $keys_to_sign),
|
||||
);
|
||||
$response['openid.sig'] = _openid_signature($association, $response, $keys_to_sign);
|
||||
state()->set('openid_test.response', $response);
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertNoRaw('OpenID login failed.');
|
||||
$this->assertFieldByName('name', '', 'No username was supplied by provider.');
|
||||
$this->assertFieldByName('mail', '', 'No e-mail address was supplied by provider.');
|
||||
|
||||
// Check that unsigned SREG fields are ignored.
|
||||
$response = array(
|
||||
'openid.signed' => 'op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle,sreg.nickname',
|
||||
'openid.sreg.nickname' => 'john',
|
||||
'openid.sreg.email' => 'john@example.com',
|
||||
);
|
||||
state()->set('openid_test.response', $response);
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertNoRaw('OpenID login failed.');
|
||||
$this->assertFieldByName('name', 'john', 'Username was supplied by provider.');
|
||||
$this->assertFieldByName('mail', '', 'E-mail address supplied by provider was ignored.');
|
||||
}
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\openid\Tests\OpenIDRegistrationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\openid\Tests;
|
||||
|
||||
use Drupal\Core\Language\Language;
|
||||
|
||||
/**
|
||||
* Test account registration using Simple Registration and Attribute Exchange.
|
||||
*/
|
||||
class OpenIDRegistrationTest extends OpenIDTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* Add language module to test with some non-built-in languages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('openid_test', 'language');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'OpenID account registration',
|
||||
'description' => 'Creates a user account using auto-registration.',
|
||||
'group' => 'OpenID'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test OpenID auto-registration with e-mail verification enabled.
|
||||
*/
|
||||
function testRegisterUserWithEmailVerification() {
|
||||
config('user.settings')->set('verify_mail', TRUE)->save();
|
||||
|
||||
config('system.timezone')
|
||||
->set('user.configurable', 1)
|
||||
->set('default', 'Europe/Brussels')
|
||||
->save();
|
||||
|
||||
// Tell openid_test.module to respond with these SREG fields.
|
||||
state()->set('openid_test.response', array(
|
||||
'openid.sreg.nickname' => 'john',
|
||||
'openid.sreg.email' => 'john@example.com',
|
||||
'openid.sreg.language' => 'pt-BR',
|
||||
'openid.sreg.timezone' => 'Europe/London',
|
||||
));
|
||||
|
||||
// Save Portuguese and Portuguese, Portugal as optional languages. The
|
||||
// process should pick 'pt' based on the sreg.language being 'pt-BR'
|
||||
// (and falling back on least specific language given no pt-br available
|
||||
// locally).
|
||||
$language = new Language(array(
|
||||
'langcode' => 'pt',
|
||||
));
|
||||
language_save($language);
|
||||
$language = new Language(array(
|
||||
'langcode' => 'pt-pt',
|
||||
));
|
||||
language_save($language);
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertRaw(t('Once you have verified your e-mail address, you may log in via OpenID.'), 'User was asked to verify e-mail address.');
|
||||
$this->assertRaw(t('A welcome message with further instructions has been sent to your e-mail address.'), 'A welcome message was sent to the user.');
|
||||
$reset_url = $this->getPasswordResetURLFromMail();
|
||||
|
||||
$user = user_load_by_name('john');
|
||||
$this->assertTrue($user, 'User was registered with right username.');
|
||||
$this->assertEqual($user->mail, 'john@example.com', 'User was registered with right email address.');
|
||||
$this->assertEqual($user->timezone, 'Europe/London', 'User was registered with right timezone.');
|
||||
$this->assertEqual($user->preferred_langcode, 'pt', 'User was registered with right language.');
|
||||
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertRaw(t('You must validate your email address for this account before logging in via OpenID.'));
|
||||
|
||||
// Follow the one-time login that was sent in the welcome e-mail.
|
||||
$this->drupalGet($reset_url);
|
||||
$this->drupalPost(NULL, array(), t('Log in'));
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Verify that the account was activated.
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test OpenID auto-registration with e-mail verification disabled.
|
||||
*/
|
||||
function testRegisterUserWithoutEmailVerification() {
|
||||
config('user.settings')->set('verify_mail', FALSE)->save();
|
||||
|
||||
config('system.timezone')
|
||||
->set('user.configurable', 1)
|
||||
->set('default', 'Europe/Brussels')
|
||||
->save();
|
||||
|
||||
// Tell openid_test.module to respond with these SREG fields.
|
||||
state()->set('openid_test.response', array(
|
||||
'openid.sreg.nickname' => 'john',
|
||||
'openid.sreg.email' => 'john@example.com',
|
||||
'openid.sreg.language' => 'pt-BR',
|
||||
'openid.sreg.timezone' => 'Europe/London',
|
||||
));
|
||||
|
||||
// Save Portuguese, Brazil as an optional language. The process should pick
|
||||
// 'pt-br' based on the sreg.language later.
|
||||
$language = new Language(array(
|
||||
'langcode' => 'pt-br',
|
||||
));
|
||||
language_save($language);
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
|
||||
$user = user_load_by_name('john');
|
||||
$this->assertTrue($user, 'User was registered with right username.');
|
||||
$this->assertEqual($user->mail, 'john@example.com', 'User was registered with right email address.');
|
||||
$this->assertEqual($user->timezone, 'Europe/London', 'User was registered with right timezone.');
|
||||
$this->assertEqual($user->preferred_langcode, 'pt-br', 'User was registered with right language.');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test OpenID auto-registration with a provider that supplies invalid SREG
|
||||
* information (a username that is already taken, and no e-mail address).
|
||||
*/
|
||||
function testRegisterUserWithInvalidSreg() {
|
||||
config('system.timezone')
|
||||
->set('user.configurable', 1)
|
||||
->set('default', 'Europe/Brussels')
|
||||
->save();
|
||||
|
||||
// Tell openid_test.module to respond with these SREG fields.
|
||||
$web_user = $this->drupalCreateUser(array());
|
||||
state()->set('openid_test.response', array(
|
||||
'openid.sreg.nickname' => $web_user->name,
|
||||
'openid.sreg.email' => 'mail@invalid#',
|
||||
'openid.sreg.timezone' => 'Foo/Bar',
|
||||
'openid.sreg.language' => 'foobar',
|
||||
));
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->submitLoginForm($identity);
|
||||
|
||||
$this->assertRaw(t('Account registration using the information provided by your OpenID provider failed due to the reasons listed below. Complete the registration by filling out the form below. If you already have an account, you can <a href="@login">log in</a> now and add your OpenID under "My account".', array('@login' => url('user/login'))), 'User was asked to complete the registration process manually.');
|
||||
$this->assertRaw(t('The name %name is already taken.', array('%name' => $web_user->name)), 'Form validation error for username was displayed.');
|
||||
$this->assertRaw(t('The e-mail address %mail is not valid.', array('%mail' => 'mail@invalid#')), 'Form validation error for e-mail address was displayed.');
|
||||
$this->assertTrue(state()->get('openid_test.hook_openid_response_response'), 'hook_openid_response() was invoked.');
|
||||
$this->assertFalse(state()->get('openid_test.hook_openid_response_account'), 'No user object passed to hook_openid_response().');
|
||||
|
||||
// Enter username and e-mail address manually.
|
||||
state()->delete('openid_test.hook_openid_response_response');
|
||||
$edit = array('name' => 'john', 'mail' => 'john@example.com');
|
||||
$this->drupalPost(NULL, $edit, t('Create new account'));
|
||||
$this->assertRaw(t('Once you have verified your e-mail address, you may log in via OpenID.'), 'User was asked to verify e-mail address.');
|
||||
$reset_url = $this->getPasswordResetURLFromMail();
|
||||
|
||||
$user = user_load_by_name('john');
|
||||
$this->assertTrue($user, 'User was registered with right username.');
|
||||
$this->assertEqual($user->preferred_langcode, language_default()->langcode, 'User language is site default.');
|
||||
|
||||
// Follow the one-time login that was sent in the welcome e-mail.
|
||||
$this->drupalGet($reset_url);
|
||||
$this->drupalPost(NULL, array(), t('Log in'));
|
||||
$this->assertFalse(state()->get('openid_test.hook_openid_response_response'), 'hook_openid_response() was not invoked.');
|
||||
|
||||
// The user is taken to user/%uid/edit.
|
||||
$this->assertFieldByName('mail', 'john@example.com', 'User was registered with right e-mail address.');
|
||||
|
||||
$this->clickLink(t('OpenID identities'));
|
||||
$this->assertRaw($identity, 'OpenID identity was registered.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test OpenID auto-registration with a provider that does not supply SREG
|
||||
* information (i.e. no username or e-mail address).
|
||||
*/
|
||||
function testRegisterUserWithoutSreg() {
|
||||
|
||||
// Load the front page to get the user login block.
|
||||
$this->drupalGet('');
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertRaw(t('Complete the registration by filling out the form below. If you already have an account, you can <a href="@login">log in</a> now and add your OpenID under "My account".', array('@login' => url('user/login'))), 'User was asked to complete the registration process manually.');
|
||||
$this->assertNoRaw(t('You must enter a username.'), 'Form validation error for username was not displayed.');
|
||||
$this->assertNoRaw(t('You must enter an e-mail address.'), 'Form validation error for e-mail address was not displayed.');
|
||||
|
||||
// Enter username and e-mail address manually.
|
||||
$edit = array('name' => 'john', 'mail' => 'john@example.com');
|
||||
$this->drupalPost(NULL, $edit, t('Create new account'));
|
||||
$this->assertRaw(t('Once you have verified your e-mail address, you may log in via OpenID.'), 'User was asked to verify e-mail address.');
|
||||
$reset_url = $this->getPasswordResetURLFromMail();
|
||||
|
||||
$user = user_load_by_name('john');
|
||||
$this->assertTrue($user, 'User was registered with right username.');
|
||||
$this->assertEqual($user->preferred_langcode, language_default()->langcode, 'User language is site default.');
|
||||
|
||||
// Follow the one-time login that was sent in the welcome e-mail.
|
||||
$this->drupalGet($reset_url);
|
||||
$this->drupalPost(NULL, array(), t('Log in'));
|
||||
|
||||
// The user is taken to user/%uid/edit.
|
||||
$this->assertFieldByName('mail', 'john@example.com', 'User was registered with right e-mail address.');
|
||||
|
||||
$this->clickLink(t('OpenID identities'));
|
||||
$this->assertRaw($identity, 'OpenID identity was registered.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test OpenID auto-registration with a provider that supplies AX information,
|
||||
* but no SREG.
|
||||
*/
|
||||
function testRegisterUserWithAXButNoSREG() {
|
||||
config('user.settings')->set('verify_mail', FALSE)->save();
|
||||
config('system.timezone')
|
||||
->set('default', 'Europe/Brussels')
|
||||
->save();
|
||||
|
||||
// Tell openid_test.module to respond with these AX fields.
|
||||
state()->set('openid_test.response', array(
|
||||
'openid.ns.ext123' => 'http://openid.net/srv/ax/1.0',
|
||||
'openid.ext123.type.mail456' => 'http://axschema.org/contact/email',
|
||||
'openid.ext123.value.mail456' => 'john@example.com',
|
||||
'openid.ext123.type.name789' => 'http://schema.openid.net/namePerson/friendly',
|
||||
'openid.ext123.count.name789' => '1',
|
||||
'openid.ext123.value.name789.1' => 'john',
|
||||
'openid.ext123.type.timezone' => 'http://axschema.org/pref/timezone',
|
||||
'openid.ext123.value.timezone' => 'Europe/London',
|
||||
'openid.ext123.type.language' => 'http://axschema.org/pref/language',
|
||||
'openid.ext123.value.language' => 'pt-PT',
|
||||
));
|
||||
|
||||
// Save Portuguese and Portuguese, Portugal as optional languages. The
|
||||
// process should pick 'pt-pt' as the more specific language.
|
||||
$language = new Language(array(
|
||||
'langcode' => 'pt',
|
||||
));
|
||||
language_save($language);
|
||||
$language = new Language(array(
|
||||
'langcode' => 'pt-pt',
|
||||
));
|
||||
language_save($language);
|
||||
|
||||
// Use a User-supplied Identity that is the URL of an XRDS document.
|
||||
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
|
||||
$this->submitLoginForm($identity);
|
||||
$this->assertLink(t('Log out'), 0, 'User was logged in.');
|
||||
|
||||
$user = user_load_by_name('john');
|
||||
$this->assertTrue($user, 'User was registered with right username.');
|
||||
$this->assertEqual($user->mail, 'john@example.com', 'User was registered with right email address.');
|
||||
$this->assertEqual($user->timezone, 'Europe/London', 'User was registered with right timezone.');
|
||||
$this->assertEqual($user->preferred_langcode, 'pt-pt', 'User was registered with right language.');
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\openid\Tests\OpenIDTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\openid\Tests;
|
||||
|
||||
use Drupal\simpletest\DrupalUnitTestBase;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Test internal helper functions.
|
||||
*/
|
||||
class OpenIDTest extends DrupalUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('openid');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'OpenID helper functions',
|
||||
'description' => 'Test OpenID helper functions.',
|
||||
'group' => 'OpenID'
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
module_load_include('inc', 'openid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _openid_dh_XXX_to_XXX() functions.
|
||||
*/
|
||||
function testConversion() {
|
||||
$this->assertEqual(_openid_dh_long_to_base64('12345678901234567890123456789012345678901234567890'), 'CHJ/Y2mq+DyhUCZ0evjH8ZbOPwrS', '_openid_dh_long_to_base64() returned expected result.');
|
||||
$this->assertEqual(_openid_dh_base64_to_long('BsH/g8Nrpn2dtBSdu/sr1y8hxwyx'), '09876543210987654321098765432109876543210987654321', '_openid_dh_base64_to_long() returned expected result.');
|
||||
|
||||
$this->assertEqual(_openid_dh_long_to_binary('12345678901234567890123456789012345678901234567890'), "\x08r\x7fci\xaa\xf8<\xa1P&tz\xf8\xc7\xf1\x96\xce?\x0a\xd2", '_openid_dh_long_to_binary() returned expected result.');
|
||||
$this->assertEqual(_openid_dh_binary_to_long("\x06\xc1\xff\x83\xc3k\xa6}\x9d\xb4\x14\x9d\xbb\xfb+\xd7/!\xc7\x0c\xb1"), '09876543210987654321098765432109876543210987654321', '_openid_dh_binary_to_long() returned expected result.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _openid_dh_xorsecret().
|
||||
*/
|
||||
function testOpenidDhXorsecret() {
|
||||
$this->assertEqual(_openid_dh_xorsecret('123456790123456790123456790', "abc123ABC\x00\xFF"), "\xa4'\x06\xbe\xf1.\x00y\xff\xc2\xc1", '_openid_dh_xorsecret() returned expected result.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _openid_get_bytes().
|
||||
*/
|
||||
function testOpenidGetBytes() {
|
||||
$this->assertEqual(strlen(_openid_get_bytes(20)), 20, '_openid_get_bytes() returned expected result.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _openid_signature().
|
||||
*/
|
||||
function testOpenidSignature() {
|
||||
// Test that signature is calculated according to OpenID Authentication 2.0,
|
||||
// section 6.1. In the following array, only the two first entries should be
|
||||
// included in the calculation, because the substring following the period
|
||||
// is mentioned in the third argument for _openid_signature(). The last
|
||||
// entry should not be included, because it does not start with "openid.".
|
||||
$response = array(
|
||||
'openid.foo' => 'abc1',
|
||||
'openid.bar' => 'abc2',
|
||||
'openid.baz' => 'abc3',
|
||||
'foobar.foo' => 'abc4',
|
||||
);
|
||||
$association = new stdClass();
|
||||
$association->mac_key = "1234567890abcdefghij\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9";
|
||||
$this->assertEqual(_openid_signature($association, $response, array('foo', 'bar')), 'QnKZQzSFstT+GNiJDFOptdcZjrc=', 'Expected signature calculated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _openid_is_xri().
|
||||
*/
|
||||
function testOpenidXRITest() {
|
||||
// Test that the XRI test is according to OpenID Authentication 2.0,
|
||||
// section 7.2. If the user-supplied string starts with xri:// it should be
|
||||
// stripped and the resulting string should be treated as an XRI when it
|
||||
// starts with "=", "@", "+", "$", "!" or "(".
|
||||
$this->assertTrue(_openid_is_xri('xri://=foo'), '_openid_is_xri() returned expected result for an xri identifier with xri scheme.');
|
||||
$this->assertTrue(_openid_is_xri('xri://@foo'), '_openid_is_xri() returned expected result for an xri identifier with xri scheme.');
|
||||
$this->assertTrue(_openid_is_xri('xri://+foo'), '_openid_is_xri() returned expected result for an xri identifier with xri scheme.');
|
||||
$this->assertTrue(_openid_is_xri('xri://$foo'), '_openid_is_xri() returned expected result for an xri identifier with xri scheme.');
|
||||
$this->assertTrue(_openid_is_xri('xri://!foo'), '_openid_is_xri() returned expected result for an xri identifier with xri scheme..');
|
||||
$this->assertTrue(_openid_is_xri('xri://(foo'), '_openid_is_xri() returned expected result for an xri identifier with xri scheme..');
|
||||
|
||||
$this->assertTrue(_openid_is_xri('=foo'), '_openid_is_xri() returned expected result for an xri identifier.');
|
||||
$this->assertTrue(_openid_is_xri('@foo'), '_openid_is_xri() returned expected result for an xri identifier.');
|
||||
$this->assertTrue(_openid_is_xri('+foo'), '_openid_is_xri() returned expected result for an xri identifier.');
|
||||
$this->assertTrue(_openid_is_xri('$foo'), '_openid_is_xri() returned expected result for an xri identifier.');
|
||||
$this->assertTrue(_openid_is_xri('!foo'), '_openid_is_xri() returned expected result for an xri identifier.');
|
||||
$this->assertTrue(_openid_is_xri('(foo'), '_openid_is_xri() returned expected result for an xri identifier.');
|
||||
|
||||
$this->assertFalse(_openid_is_xri('foo'), '_openid_is_xri() returned expected result for an http URL.');
|
||||
$this->assertFalse(_openid_is_xri('xri://foo'), '_openid_is_xri() returned expected result for an http URL.');
|
||||
$this->assertFalse(_openid_is_xri('http://foo/'), '_openid_is_xri() returned expected result for an http URL.');
|
||||
$this->assertFalse(_openid_is_xri('http://example.com/'), '_openid_is_xri() returned expected result for an http URL.');
|
||||
$this->assertFalse(_openid_is_xri('user@example.com/'), '_openid_is_xri() returned expected result for an http URL.');
|
||||
$this->assertFalse(_openid_is_xri('http://user@example.com/'), '_openid_is_xri() returned expected result for an http URL.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test openid_normalize().
|
||||
*/
|
||||
function testOpenidNormalize() {
|
||||
// Test that the normalization is according to OpenID Authentication 2.0,
|
||||
// section 7.2 and 11.5.2.
|
||||
|
||||
$this->assertEqual(openid_normalize('$foo'), '$foo', 'openid_normalize() correctly normalized an XRI.');
|
||||
$this->assertEqual(openid_normalize('xri://$foo'), '$foo', 'openid_normalize() correctly normalized an XRI with an xri:// scheme.');
|
||||
|
||||
$this->assertEqual(openid_normalize('example.com/'), 'http://example.com/', 'openid_normalize() correctly normalized a URL with a missing scheme.');
|
||||
$this->assertEqual(openid_normalize('example.com'), 'http://example.com/', 'openid_normalize() correctly normalized a URL with a missing scheme and empty path.');
|
||||
$this->assertEqual(openid_normalize('http://example.com'), 'http://example.com/', 'openid_normalize() correctly normalized a URL with an empty path.');
|
||||
|
||||
$this->assertEqual(openid_normalize('http://example.com/path'), 'http://example.com/path', 'openid_normalize() correctly normalized a URL with a path.');
|
||||
|
||||
$this->assertEqual(openid_normalize('http://example.com/path#fragment'), 'http://example.com/path', 'openid_normalize() correctly normalized a URL with a fragment.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test openid_extract_namespace().
|
||||
*/
|
||||
function testOpenidExtractNamespace() {
|
||||
$response = array(
|
||||
'openid.sreg.nickname' => 'john',
|
||||
'openid.ns.ext1' => OPENID_NS_SREG,
|
||||
'openid.ext1.nickname' => 'george',
|
||||
'openid.ext1.email' => 'george@example.com',
|
||||
'openid.ns.ext2' => 'http://example.com/ns/ext2',
|
||||
'openid.ext2.foo' => '123',
|
||||
'openid.ext2.bar' => '456',
|
||||
'openid.signed' => 'sreg.nickname,ns.ext1,ext1.email,ext2.foo',
|
||||
);
|
||||
|
||||
$values = openid_extract_namespace($response, 'http://example.com/ns/dummy', NULL, FALSE);
|
||||
$this->assertEqual($values, array(), 'Nothing found for unused namespace.');
|
||||
|
||||
$values = openid_extract_namespace($response, 'http://example.com/ns/dummy', 'sreg', FALSE);
|
||||
$this->assertEqual($values, array('nickname' => 'john'), 'Value found for fallback prefix.');
|
||||
|
||||
$values = openid_extract_namespace($response, OPENID_NS_SREG, 'sreg', FALSE);
|
||||
$this->assertEqual($values, array('nickname' => 'george', 'email' => 'george@example.com'), 'Namespace takes precedence over fallback prefix.');
|
||||
|
||||
// ext1.email is signed, but ext1.nickname is not.
|
||||
$values = openid_extract_namespace($response, OPENID_NS_SREG, 'sreg', TRUE);
|
||||
$this->assertEqual($values, array('email' => 'george@example.com'), 'Unsigned namespaced fields ignored.');
|
||||
|
||||
$values = openid_extract_namespace($response, 'http://example.com/ns/ext2', 'sreg', FALSE);
|
||||
$this->assertEqual($values, array('foo' => '123', 'bar' => '456'), 'Unsigned fields found.');
|
||||
|
||||
// ext2.foo and ext2.bar are ignored, because ns.ext2 is not signed. The
|
||||
// fallback prefix is not used, because the namespace is specified.
|
||||
$values = openid_extract_namespace($response, 'http://example.com/ns/ext2', 'sreg', TRUE);
|
||||
$this->assertEqual($values, array(), 'Unsigned fields ignored.');
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\openid\Tests\OpenIDTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\openid\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Base class for OpenID tests.
|
||||
*/
|
||||
abstract class OpenIDTestBase extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'openid', 'test_page_test');
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Enable user login block.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer blocks'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalPlaceBlock('user_login_block');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Use a different front page than login page for testing OpenID login from
|
||||
// the user login block.
|
||||
config('system.site')->set('page.front', 'test-page')->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the login procedure using the specified User-supplied Identity.
|
||||
*/
|
||||
function submitLoginForm($identity) {
|
||||
// Fill out and submit the login form.
|
||||
$edit = array('openid_identifier' => $identity);
|
||||
$this->drupalPost('', $edit, t('Log in'), array(), array(), 'openid-login-form');
|
||||
|
||||
// Check we are on the OpenID redirect form.
|
||||
$this->assertTitle(t('OpenID redirect'), 'OpenID redirect page was displayed.');
|
||||
|
||||
// Submit form to the OpenID Provider Endpoint.
|
||||
$this->drupalPost(NULL, array(), t('Send'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the last sent e-mail and returns the one-time login link URL.
|
||||
*/
|
||||
function getPasswordResetURLFromMail() {
|
||||
$mails = $this->drupalGetMails();
|
||||
$mail = end($mails);
|
||||
preg_match('@.+user/reset/.+@', $mail['body'], $matches);
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\openid\Tests\Upgrade\OpenIDUpgradePathTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\openid\Tests\Upgrade;
|
||||
|
||||
use Drupal\system\Tests\Upgrade\UpgradePathTestBase;
|
||||
|
||||
/**
|
||||
* Performs major version release upgrade tests on a populated database.
|
||||
*
|
||||
* Loads an installation of Drupal 7.x and runs the upgrade process on it.
|
||||
*
|
||||
* The install contains the minimal profile (plus openid module) modules
|
||||
* with generated users in authmap so that the upgrade path can be tested.
|
||||
*/
|
||||
class OpenIDAuthmapUpgradePathTest extends UpgradePathTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'OpenID upgrade path',
|
||||
'description' => 'Identities migration from the authmap upgrade tests.',
|
||||
'group' => 'OpenID',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
// Path to the database dump files.
|
||||
$this->databaseDumpFiles = array(
|
||||
drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.minimal.database.php.gz',
|
||||
drupal_get_path('module', 'openid') . '/tests/upgrade/drupal-7.openid.database.php',
|
||||
drupal_get_path('module', 'openid') . '/tests/upgrade/drupal-7.openid.authmap.database.php',
|
||||
);
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests expected openid identities conversion after a successful upgrade.
|
||||
*/
|
||||
public function testIdentitiesUpgrade() {
|
||||
$this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
|
||||
|
||||
// Verify that user identities was properly upgraded.
|
||||
$expected_identities = array(
|
||||
1 => (object) array(
|
||||
'aid' => 1,
|
||||
'uid' => 1,
|
||||
'identifier' => 'userA@providerA',
|
||||
),
|
||||
2 => (object) array(
|
||||
'aid' => 2,
|
||||
'uid' => 1,
|
||||
'identifier' => 'userB@providerA',
|
||||
));
|
||||
|
||||
$db_identities = db_select('openid_identities', 'oi')
|
||||
->fields('oi')
|
||||
->execute()
|
||||
->fetchAllAssoc('aid');
|
||||
|
||||
foreach ($expected_identities as $aid => $expected_identity) {
|
||||
$this->assertEqual($expected_identity, $db_identities[$aid]);
|
||||
}
|
||||
|
||||
$this->assertEqual(count($expected_identities), count($db_identities));
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 205 B |
|
@ -1,10 +0,0 @@
|
|||
#edit-openid-identifier {
|
||||
background-position: right 50%;
|
||||
padding-left: 0;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#block-user-login .openid-link {
|
||||
background-position: right top;
|
||||
padding: 0 1.5em 0 0;
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by the OpenID module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup hooks
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allow modules to modify the OpenID request parameters.
|
||||
*
|
||||
* @param $request
|
||||
* An associative array of request parameters.
|
||||
* @param $service
|
||||
* A service array as returned by openid_discovery().
|
||||
*/
|
||||
function hook_openid_request_alter(&$request, $service) {
|
||||
if ($request['openid.mode'] == 'checkid_setup') {
|
||||
$request['openid.identity'] = 'http://myname.myopenid.com/';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow modules to act upon a successful OpenID login.
|
||||
*
|
||||
* @param $response
|
||||
* Response values from the OpenID Provider.
|
||||
* @param $account
|
||||
* The Drupal user account that logged in
|
||||
*
|
||||
*/
|
||||
function hook_openid_response($response, $account) {
|
||||
if (isset($response['openid.ns.ax'])) {
|
||||
_mymodule_store_ax_fields($response, $account);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow modules to declare OpenID discovery methods.
|
||||
*
|
||||
* The discovery function callbacks will be called in turn with an unique
|
||||
* parameter, the claimed identifier. They have to return an associative array
|
||||
* with array of services and claimed identifier in the same form as returned by
|
||||
* openid_discover(). The resulting array must contain following keys:
|
||||
* - 'services' (required) an array of discovered services (including OpenID
|
||||
* version, endpoint URI, etc).
|
||||
* - 'claimed_id' (optional) new claimed identifer, found by following HTTP
|
||||
* redirects during the services discovery.
|
||||
*
|
||||
* The first discovery method that succeed (return at least one services) will
|
||||
* stop the discovery process.
|
||||
*
|
||||
* @return
|
||||
* An associative array which keys are the name of the discovery methods and
|
||||
* values are function callbacks.
|
||||
*
|
||||
* @see hook_openid_discovery_method_info_alter()
|
||||
*/
|
||||
function hook_openid_discovery_method_info() {
|
||||
return array(
|
||||
'new_discovery_idea' => '_my_discovery_method',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow modules to alter discovery methods.
|
||||
*/
|
||||
function hook_openid_discovery_method_info_alter(&$methods) {
|
||||
// Remove XRI discovery scheme.
|
||||
unset($methods['xri']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow modules to declare OpenID normalization methods.
|
||||
*
|
||||
* The discovery function callbacks will be called in turn with an unique
|
||||
* parameter, the identifier to normalize. They have to return a normalized
|
||||
* identifier, or NULL if the identifier is not in a form they can handle.
|
||||
*
|
||||
* The first normalization method that succeed (return a value that is not NULL)
|
||||
* will stop the normalization process.
|
||||
*
|
||||
* @return
|
||||
* An array with a set of function callbacks, that will be called in turn
|
||||
* when normalizing an OpenID identifier. The normalization functions have
|
||||
* to return a normalized identifier, or NULL if the identifier is not in
|
||||
* a form they can handle.
|
||||
* @see hook_openid_normalization_method_info_alter()
|
||||
*/
|
||||
function hook_openid_normalization_method_info() {
|
||||
return array(
|
||||
'new_normalization_idea' => '_my_normalization_method',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow modules to alter normalization methods.
|
||||
*/
|
||||
function hook_openid_normalization_method_info_alter(&$methods) {
|
||||
// Remove Google IDP normalization.
|
||||
unset($methods['google_idp']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup hooks".
|
||||
*/
|
|
@ -1,17 +0,0 @@
|
|||
#edit-openid-identifier {
|
||||
background-image: url("login-bg.png");
|
||||
background-position: left 50%; /* LTR */
|
||||
background-repeat: no-repeat;
|
||||
padding-left: 20px; /* LTR */
|
||||
}
|
||||
|
||||
#block-user-login #openid-login-form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#block-user-login .openid-link {
|
||||
background-image: url("login-bg.png");
|
||||
background-position: left top; /* LTR */
|
||||
background-repeat: no-repeat;
|
||||
padding: 0 0 0 1.5em; /* LTR */
|
||||
}
|
|
@ -1,822 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* OpenID utility functions.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Language\Language;
|
||||
|
||||
/**
|
||||
* Diffie-Hellman Key Exchange Default Value.
|
||||
*
|
||||
* This is used to establish an association between the Relying Party and the
|
||||
* OpenID Provider.
|
||||
*
|
||||
* See RFC 2631: http://www.ietf.org/rfc/rfc2631.txt
|
||||
*/
|
||||
define('OPENID_DH_DEFAULT_MOD', '155172898181473697471232257763715539915724801' .
|
||||
'966915404479707795314057629378541917580651227423698188993727816152646631' .
|
||||
'438561595825688188889951272158842675419950341258706556549803580104870537' .
|
||||
'681476726513255747040765857479291291572334510643245094715007229621094194' .
|
||||
'349783925984760375594985848253359305585439638443');
|
||||
|
||||
/**
|
||||
* Diffie-Hellman generator; used for Diffie-Hellman key exchange computations.
|
||||
*/
|
||||
const OPENID_DH_DEFAULT_GEN = '2';
|
||||
|
||||
/**
|
||||
* Random number generator; used for Diffie-Hellman key exchange computations.
|
||||
*/
|
||||
const OPENID_RAND_SOURCE = '/dev/urandom';
|
||||
|
||||
/**
|
||||
* OpenID Authentication 2.0 namespace URL.
|
||||
*/
|
||||
const OPENID_NS_2_0 = 'http://specs.openid.net/auth/2.0';
|
||||
|
||||
/**
|
||||
* OpenID Authentication 1.1 namespace URL; used for backwards-compatibility.
|
||||
*/
|
||||
const OPENID_NS_1_1 = 'http://openid.net/signon/1.1';
|
||||
|
||||
/**
|
||||
* OpenID Authentication 1.0 namespace URL; used for backwards-compatibility.
|
||||
*/
|
||||
const OPENID_NS_1_0 = 'http://openid.net/signon/1.0';
|
||||
|
||||
/**
|
||||
* OpenID namespace used in Yadis documents.
|
||||
*/
|
||||
const OPENID_NS_OPENID = 'http://openid.net/xmlns/1.0';
|
||||
|
||||
/**
|
||||
* OpenID Simple Registration extension.
|
||||
*/
|
||||
const OPENID_NS_SREG = 'http://openid.net/extensions/sreg/1.1';
|
||||
|
||||
/**
|
||||
* OpenID Attribute Exchange extension.
|
||||
*/
|
||||
const OPENID_NS_AX = 'http://openid.net/srv/ax/1.0';
|
||||
|
||||
/**
|
||||
* Extensible Resource Descriptor documents.
|
||||
*/
|
||||
const OPENID_NS_XRD = 'xri://$xrd*($v*2.0)';
|
||||
|
||||
/**
|
||||
* Performs an HTTP 302 redirect (for the 1.x protocol).
|
||||
*/
|
||||
function openid_redirect_http($url, $message) {
|
||||
$query = array();
|
||||
foreach ($message as $key => $val) {
|
||||
$query[] = $key . '=' . urlencode($val);
|
||||
}
|
||||
|
||||
$sep = (strpos($url, '?') === FALSE) ? '?' : '&';
|
||||
header('Location: ' . $url . $sep . implode('&', $query), TRUE, 302);
|
||||
|
||||
drupal_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a js auto-submit redirect for (for the 2.x protocol)
|
||||
*/
|
||||
function openid_redirect($url, $message) {
|
||||
$language_interface = language(Language::TYPE_INTERFACE);
|
||||
|
||||
$output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . "\n";
|
||||
$output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . $language_interface->langcode . '" lang="' . $language_interface->langcode . '">' . "\n";
|
||||
$output .= "<head>\n";
|
||||
$output .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
|
||||
$output .= "<title>" . t('OpenID redirect') . "</title>\n";
|
||||
$output .= "</head>\n";
|
||||
$output .= "<body>\n";
|
||||
$elements = drupal_get_form('openid_redirect_form', $url, $message);
|
||||
$output .= drupal_render($elements);
|
||||
$output .= '<script>document.getElementById("openid-redirect-form").submit();</script>' . "\n";
|
||||
$output .= "</body>\n";
|
||||
$output .= "</html>\n";
|
||||
print $output;
|
||||
|
||||
drupal_exit();
|
||||
}
|
||||
|
||||
function openid_redirect_form($form, &$form_state, $url, $message) {
|
||||
$form['#action'] = $url;
|
||||
$form['#method'] = "post";
|
||||
foreach ($message as $key => $value) {
|
||||
$form[$key] = array(
|
||||
'#type' => 'hidden',
|
||||
'#name' => $key,
|
||||
'#value' => $value,
|
||||
);
|
||||
}
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#prefix' => '<noscript><div>',
|
||||
'#suffix' => '</div></noscript>',
|
||||
'#value' => t('Send'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an XRDS document.
|
||||
*
|
||||
* @param $raw_xml
|
||||
* A string containing the XRDS document.
|
||||
* @return
|
||||
* An array of service entries.
|
||||
*/
|
||||
function _openid_xrds_parse($raw_xml) {
|
||||
$services = array();
|
||||
|
||||
// Protect against malicious doctype declarations and other unexpected entity
|
||||
// loading.
|
||||
$load_entities = libxml_disable_entity_loader(TRUE);
|
||||
|
||||
// Load the XML into a DOM document.
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadXML($raw_xml);
|
||||
|
||||
// Since DOCTYPE declarations from an untrusted source could be malicious, we
|
||||
// stop parsing here and treat the XML as invalid since XRDS documents do not
|
||||
// require, and are not expected to have, a DOCTYPE.
|
||||
if (isset($dom->doctype)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Parse the DOM document for the information we need.
|
||||
if ($xml = simplexml_import_dom($dom)) {
|
||||
foreach ($xml->children(OPENID_NS_XRD)->XRD as $xrd) {
|
||||
foreach ($xrd->children(OPENID_NS_XRD)->Service as $service_element) {
|
||||
$service = array(
|
||||
'priority' => $service_element->attributes()->priority ? (int)$service_element->attributes()->priority : PHP_INT_MAX,
|
||||
'types' => array(),
|
||||
'uri' => (string)$service_element->children(OPENID_NS_XRD)->URI,
|
||||
'service' => $service_element,
|
||||
'xrd' => $xrd,
|
||||
);
|
||||
foreach ($service_element->Type as $type) {
|
||||
$service['types'][] = (string)$type;
|
||||
}
|
||||
if ($service_element->children(OPENID_NS_XRD)->LocalID) {
|
||||
$service['identity'] = (string)$service_element->children(OPENID_NS_XRD)->LocalID;
|
||||
}
|
||||
elseif ($service_element->children(OPENID_NS_OPENID)->Delegate) {
|
||||
$service['identity'] = (string)$service_element->children(OPENID_NS_OPENID)->Delegate;
|
||||
}
|
||||
else {
|
||||
$service['identity'] = FALSE;
|
||||
}
|
||||
$services[] = $service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the LIBXML options to the previous state before returning.
|
||||
libxml_disable_entity_loader($load_entities);
|
||||
|
||||
return $services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a service element.
|
||||
*
|
||||
* The procedure is described in OpenID Authentication 2.0, section 7.3.2.
|
||||
*
|
||||
* A new entry is added to the returned array with the key 'version' and the
|
||||
* value 1 or 2 specifying the protocol version used by the service.
|
||||
*
|
||||
* @param $services
|
||||
* An array of service arrays as returned by openid_discovery().
|
||||
* @return
|
||||
* The selected service array, or NULL if no valid services were found.
|
||||
*/
|
||||
function _openid_select_service(array $services) {
|
||||
// Extensible Resource Identifier (XRI) Resolution Version 2.0, section 4.3.3:
|
||||
// Find the service with the highest priority (lowest integer value). If there
|
||||
// is a tie, select a random one, not just the first in the XML document.
|
||||
shuffle($services);
|
||||
$selected_service = NULL;
|
||||
$selected_type_priority = FALSE;
|
||||
|
||||
// Search for an OP Identifier Element.
|
||||
foreach ($services as $service) {
|
||||
if (!empty($service['uri'])) {
|
||||
$type_priority = FALSE;
|
||||
if (in_array('http://specs.openid.net/auth/2.0/server', $service['types'])) {
|
||||
$service['version'] = 2;
|
||||
$type_priority = 1;
|
||||
}
|
||||
elseif (in_array('http://specs.openid.net/auth/2.0/signon', $service['types'])) {
|
||||
$service['version'] = 2;
|
||||
$type_priority = 2;
|
||||
}
|
||||
elseif (in_array(OPENID_NS_1_0, $service['types']) || in_array(OPENID_NS_1_1, $service['types'])) {
|
||||
$service['version'] = 1;
|
||||
$type_priority = 3;
|
||||
}
|
||||
|
||||
if ($type_priority
|
||||
&& (!$selected_service
|
||||
|| $type_priority < $selected_type_priority
|
||||
|| ($type_priority == $selected_type_priority && $service['priority'] < $selected_service['priority']))) {
|
||||
$selected_service = $service;
|
||||
$selected_type_priority = $type_priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($selected_service) {
|
||||
// Unset SimpleXMLElement instances that cannot be saved in $_SESSION.
|
||||
unset($selected_service['xrd']);
|
||||
unset($selected_service['service']);
|
||||
}
|
||||
|
||||
return $selected_service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given identifier is an XRI ID.
|
||||
*/
|
||||
function _openid_is_xri($identifier) {
|
||||
// Strip the xri:// scheme from the identifier if present.
|
||||
if (stripos($identifier, 'xri://') === 0) {
|
||||
$identifier = substr($identifier, 6);
|
||||
}
|
||||
|
||||
// Test whether the identifier starts with an XRI global context symbol or (.
|
||||
$firstchar = substr($identifier, 0, 1);
|
||||
if (strpos("=@+$!(", $firstchar) !== FALSE) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the given identifier.
|
||||
*
|
||||
* The procedure is described in OpenID Authentication 2.0, section 7.2.
|
||||
*/
|
||||
function openid_normalize($identifier) {
|
||||
$methods = module_invoke_all('openid_normalization_method_info');
|
||||
drupal_alter('openid_normalization_method_info', $methods);
|
||||
|
||||
// Execute each method in turn, stopping after the first method accepted
|
||||
// the identifier.
|
||||
foreach ($methods as $method) {
|
||||
$result = $method($identifier);
|
||||
if ($result !== NULL) {
|
||||
$identifier = $result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenID normalization method: normalize XRI identifiers.
|
||||
*/
|
||||
function _openid_xri_normalize($identifier) {
|
||||
if (_openid_is_xri($identifier)) {
|
||||
if (stristr($identifier, 'xri://') !== FALSE) {
|
||||
$identifier = substr($identifier, 6);
|
||||
}
|
||||
return $identifier;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenID normalization method: normalize URL identifiers.
|
||||
*/
|
||||
function _openid_url_normalize($url) {
|
||||
$normalized_url = $url;
|
||||
|
||||
if (stristr($url, '://') === FALSE) {
|
||||
$normalized_url = 'http://' . $url;
|
||||
}
|
||||
|
||||
// Strip the fragment and fragment delimiter if present.
|
||||
$normalized_url = strtok($normalized_url, '#');
|
||||
|
||||
if (substr_count($normalized_url, '/') < 3) {
|
||||
$normalized_url .= '/';
|
||||
}
|
||||
|
||||
return $normalized_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a serialized message packet as per spec: $key:$value\n .
|
||||
*/
|
||||
function _openid_create_message($data) {
|
||||
$serialized = '';
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if ((strpos($key, ':') !== FALSE) || (strpos($key, "\n") !== FALSE) || (strpos($value, "\n") !== FALSE)) {
|
||||
return NULL;
|
||||
}
|
||||
$serialized .= "$key:$value\n";
|
||||
}
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a message from _openid_create_message for HTTP Post
|
||||
*/
|
||||
function _openid_encode_message($message) {
|
||||
$encoded_message = '';
|
||||
|
||||
$items = explode("\n", $message);
|
||||
foreach ($items as $item) {
|
||||
$parts = explode(':', $item, 2);
|
||||
|
||||
if (count($parts) == 2) {
|
||||
if ($encoded_message != '') {
|
||||
$encoded_message .= '&';
|
||||
}
|
||||
$encoded_message .= rawurlencode(trim($parts[0])) . '=' . rawurlencode(trim($parts[1]));
|
||||
}
|
||||
}
|
||||
|
||||
return $encoded_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a direct communication message
|
||||
* into an associative array.
|
||||
*/
|
||||
function _openid_parse_message($message) {
|
||||
$parsed_message = array();
|
||||
|
||||
$items = explode("\n", $message);
|
||||
foreach ($items as $item) {
|
||||
$parts = explode(':', $item, 2);
|
||||
|
||||
if (count($parts) == 2) {
|
||||
$parsed_message[$parts[0]] = $parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $parsed_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a nonce value - formatted per OpenID spec.
|
||||
*/
|
||||
function _openid_nonce() {
|
||||
// YYYY-MM-DDThh:mm:ssZ, plus some optional extra unique characters.
|
||||
return gmdate('Y-m-d\TH:i:s\Z') .
|
||||
chr(mt_rand(0, 25) + 65) .
|
||||
chr(mt_rand(0, 25) + 65) .
|
||||
chr(mt_rand(0, 25) + 65) .
|
||||
chr(mt_rand(0, 25) + 65);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the href attribute out of an html link element.
|
||||
*/
|
||||
function _openid_link_href($rel, $html) {
|
||||
$html_dom = new DOMDocument();
|
||||
if (@$html_dom->loadHTML($html)) {
|
||||
$html_element = simplexml_import_dom($html_dom);
|
||||
if (isset($html_element->head->link)) {
|
||||
foreach ($html_element->head->link as $link) {
|
||||
// The rel attribute contains a space-separated list of case-insensitive
|
||||
// link types.
|
||||
if (preg_match('@(?:\s|^)' . preg_quote($rel, '@') . '(?:\s|$)@i', $link['rel'])) {
|
||||
return trim($link['href']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the content attribute out of an X-XRDS-Location meta http-equiv element.
|
||||
*/
|
||||
function _openid_meta_httpequiv($html) {
|
||||
$html_dom = new DOMDocument();
|
||||
if (@$html_dom->loadHTML($html)) {
|
||||
$html_element = simplexml_import_dom($html_dom);
|
||||
if (isset($html_element->head->meta)) {
|
||||
foreach ($html_element->head->meta as $meta) {
|
||||
// The http-equiv attribute is case-insensitive.
|
||||
if (strtolower(trim($meta['http-equiv'])) == 'x-xrds-location') {
|
||||
return trim($meta['content']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign certain keys in a message
|
||||
* @param $association - object loaded from openid_association or openid_server_association table
|
||||
* - important fields are ->assoc_type and ->mac_key
|
||||
* @param $message_array - array of entire message about to be sent
|
||||
* @param $keys_to_sign - keys in the message to include in signature (without
|
||||
* 'openid.' appended)
|
||||
*/
|
||||
function _openid_signature($association, $message_array, $keys_to_sign) {
|
||||
$signature = '';
|
||||
$sign_data = array();
|
||||
|
||||
foreach ($keys_to_sign as $key) {
|
||||
if (isset($message_array['openid.' . $key])) {
|
||||
$sign_data[$key] = $message_array['openid.' . $key];
|
||||
}
|
||||
}
|
||||
|
||||
$message = _openid_create_message($sign_data);
|
||||
$secret = base64_decode($association->mac_key);
|
||||
$signature = hash_hmac('sha1', $message, $secret, TRUE);
|
||||
|
||||
return base64_encode($signature);
|
||||
}
|
||||
|
||||
function _openid_dh_base64_to_long($str) {
|
||||
$b64 = base64_decode($str);
|
||||
|
||||
return _openid_dh_binary_to_long($b64);
|
||||
}
|
||||
|
||||
function _openid_dh_long_to_base64($str) {
|
||||
return base64_encode(_openid_dh_long_to_binary($str));
|
||||
}
|
||||
|
||||
function _openid_dh_binary_to_long($str) {
|
||||
$bytes = array_merge(unpack('C*', $str));
|
||||
|
||||
$n = 0;
|
||||
foreach ($bytes as $byte) {
|
||||
$n = _openid_math_mul($n, pow(2, 8));
|
||||
$n = _openid_math_add($n, $byte);
|
||||
}
|
||||
|
||||
return $n;
|
||||
}
|
||||
|
||||
function _openid_dh_long_to_binary($long) {
|
||||
$cmp = _openid_math_cmp($long, 0);
|
||||
if ($cmp < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($cmp == 0) {
|
||||
return "\x00";
|
||||
}
|
||||
|
||||
$bytes = array();
|
||||
|
||||
while (_openid_math_cmp($long, 0) > 0) {
|
||||
array_unshift($bytes, _openid_math_mod($long, 256));
|
||||
$long = _openid_math_div($long, pow(2, 8));
|
||||
}
|
||||
|
||||
if ($bytes && ($bytes[0] > 127)) {
|
||||
array_unshift($bytes, 0);
|
||||
}
|
||||
|
||||
$string = '';
|
||||
foreach ($bytes as $byte) {
|
||||
$string .= pack('C', $byte);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
function _openid_dh_xorsecret($shared, $secret) {
|
||||
$dh_shared_str = _openid_dh_long_to_binary($shared);
|
||||
$sha1_dh_shared = sha1($dh_shared_str, TRUE);
|
||||
$xsecret = "";
|
||||
for ($i = 0; $i < strlen($secret); $i++) {
|
||||
$xsecret .= chr(ord($secret[$i]) ^ ord($sha1_dh_shared[$i]));
|
||||
}
|
||||
|
||||
return $xsecret;
|
||||
}
|
||||
|
||||
function _openid_dh_rand($stop) {
|
||||
$duplicate_cache = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
// Used as the key for the duplicate cache
|
||||
$rbytes = _openid_dh_long_to_binary($stop);
|
||||
|
||||
if (isset($duplicate_cache[$rbytes])) {
|
||||
list($duplicate, $nbytes) = $duplicate_cache[$rbytes];
|
||||
}
|
||||
else {
|
||||
if ($rbytes[0] == "\x00") {
|
||||
$nbytes = strlen($rbytes) - 1;
|
||||
}
|
||||
else {
|
||||
$nbytes = strlen($rbytes);
|
||||
}
|
||||
|
||||
$mxrand = _openid_math_pow(256, $nbytes);
|
||||
|
||||
// If we get a number less than this, then it is in the
|
||||
// duplicated range.
|
||||
$duplicate = _openid_math_mod($mxrand, $stop);
|
||||
|
||||
if (count($duplicate_cache) > 10) {
|
||||
$duplicate_cache = array();
|
||||
}
|
||||
|
||||
$duplicate_cache[$rbytes] = array($duplicate, $nbytes);
|
||||
}
|
||||
|
||||
do {
|
||||
$bytes = "\x00" . _openid_get_bytes($nbytes);
|
||||
$n = _openid_dh_binary_to_long($bytes);
|
||||
// Keep looping if this value is in the low duplicated range.
|
||||
} while (_openid_math_cmp($n, $duplicate) < 0);
|
||||
|
||||
return _openid_math_mod($n, $stop);
|
||||
}
|
||||
|
||||
function _openid_get_bytes($num_bytes) {
|
||||
$f = &drupal_static(__FUNCTION__);
|
||||
$bytes = '';
|
||||
if (!isset($f)) {
|
||||
$f = @fopen(OPENID_RAND_SOURCE, "r");
|
||||
}
|
||||
if (!$f) {
|
||||
// pseudorandom used
|
||||
$bytes = '';
|
||||
for ($i = 0; $i < $num_bytes; $i += 4) {
|
||||
$bytes .= pack('L', mt_rand());
|
||||
}
|
||||
$bytes = substr($bytes, 0, $num_bytes);
|
||||
}
|
||||
else {
|
||||
$bytes = fread($f, $num_bytes);
|
||||
}
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
function _openid_response($str = NULL) {
|
||||
$data = array();
|
||||
|
||||
if (isset($_SERVER['REQUEST_METHOD'])) {
|
||||
$data = _openid_get_params($_SERVER['QUERY_STRING']);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$str = file_get_contents('php://input');
|
||||
|
||||
$post = array();
|
||||
if ($str !== FALSE) {
|
||||
$post = _openid_get_params($str);
|
||||
}
|
||||
|
||||
$data = array_merge($data, $post);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function _openid_get_params($str) {
|
||||
$chunks = explode("&", $str);
|
||||
|
||||
$data = array();
|
||||
foreach ($chunks as $chunk) {
|
||||
$parts = explode("=", $chunk, 2);
|
||||
|
||||
if (count($parts) == 2) {
|
||||
list($k, $v) = $parts;
|
||||
$data[$k] = urldecode($v);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all the parameters belonging to an extension in a response message.
|
||||
*
|
||||
* OpenID 2.0 defines a simple extension mechanism, based on a namespace prefix.
|
||||
*
|
||||
* Each request or response can define a prefix using:
|
||||
* @code
|
||||
* openid.ns.[prefix] = [extension_namespace]
|
||||
* openid.[prefix].[key1] = [value1]
|
||||
* openid.[prefix].[key2] = [value2]
|
||||
* ...
|
||||
* @endcode
|
||||
*
|
||||
* This function extracts all the keys belonging to an extension namespace in a
|
||||
* response, optionally using a fallback prefix if none is provided in the response.
|
||||
*
|
||||
* Note that you cannot assume that a given extension namespace will use the same
|
||||
* prefix on the response and the request: each party may use a different prefix
|
||||
* to refer to the same namespace.
|
||||
*
|
||||
* @param $response
|
||||
* The response array.
|
||||
* @param $extension_namespace
|
||||
* The namespace of the extension.
|
||||
* @param $fallback_prefix
|
||||
* An optional prefix that will be used in case no prefix is found for the
|
||||
* target extension namespace.
|
||||
* @param $only_signed
|
||||
* Return only keys that are included in the message signature in openid.sig.
|
||||
* Unsigned fields may have been modified or added by other parties than the
|
||||
* OpenID Provider.
|
||||
*
|
||||
* @return
|
||||
* An associative array containing all the parameters in the response message
|
||||
* that belong to the extension. The keys are stripped from their namespace
|
||||
* prefix.
|
||||
*
|
||||
* @see http://openid.net/specs/openid-authentication-2_0.html#extensions
|
||||
*/
|
||||
function openid_extract_namespace($response, $extension_namespace, $fallback_prefix = NULL, $only_signed = FALSE) {
|
||||
$signed_keys = explode(',', $response['openid.signed']);
|
||||
|
||||
// Find the namespace prefix.
|
||||
$prefix = $fallback_prefix;
|
||||
foreach ($response as $key => $value) {
|
||||
if ($value == $extension_namespace && preg_match('/^openid\.ns\.([^.]+)$/', $key, $matches)) {
|
||||
$prefix = $matches[1];
|
||||
if ($only_signed && !in_array('ns.' . $matches[1], $signed_keys)) {
|
||||
// The namespace was defined but was not signed as required. In this
|
||||
// case we do not fall back to $fallback_prefix.
|
||||
$prefix = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now extract the namespace keys from the response.
|
||||
$output = array();
|
||||
if (!isset($prefix)) {
|
||||
return $output;
|
||||
}
|
||||
foreach ($response as $key => $value) {
|
||||
if (preg_match('/^openid\.' . $prefix . '\.(.+)$/', $key, $matches)) {
|
||||
$local_key = $matches[1];
|
||||
if (!$only_signed || in_array($prefix . '.' . $local_key, $signed_keys)) {
|
||||
$output[$local_key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts values from an OpenID AX Response.
|
||||
*
|
||||
* The values can be returned in two forms:
|
||||
* - only openid.ax.value.<alias> (for single-valued answers)
|
||||
* - both openid.ax.count.<alias> and openid.ax.value.<alias>.<count> (for both
|
||||
* single and multiple-valued answers)
|
||||
*
|
||||
* @param $values
|
||||
* An array as returned by openid_extract_namespace(..., OPENID_NS_AX).
|
||||
* @param $uris
|
||||
* An array of identifier URIs.
|
||||
* @return
|
||||
* An array of values.
|
||||
* @see http://openid.net/specs/openid-attribute-exchange-1_0.html#fetch_response
|
||||
*/
|
||||
function openid_extract_ax_values($values, $uris) {
|
||||
$output = array();
|
||||
foreach ($values as $key => $value) {
|
||||
if (in_array($value, $uris) && preg_match('/^type\.([^.]+)$/', $key, $matches)) {
|
||||
$alias = $matches[1];
|
||||
if (isset($values['count.' . $alias])) {
|
||||
for ($i = 1; $i <= $values['count.' . $alias]; $i++) {
|
||||
$output[] = $values['value.' . $alias . '.' . $i];
|
||||
}
|
||||
}
|
||||
elseif (isset($values['value.' . $alias])) {
|
||||
$output[] = $values['value.' . $alias];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the available math library GMP vs. BCMath, favouring GMP for performance.
|
||||
*/
|
||||
function _openid_get_math_library() {
|
||||
// Not drupal_static(), because a function is not going to disappear and
|
||||
// change the output of this under any circumstances.
|
||||
static $library;
|
||||
|
||||
if (empty($library)) {
|
||||
if (function_exists('gmp_add')) {
|
||||
$library = 'gmp';
|
||||
}
|
||||
elseif (function_exists('bcadd')) {
|
||||
$library = 'bcmath';
|
||||
}
|
||||
}
|
||||
|
||||
return $library;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the add function from the available math library for OpenID.
|
||||
*/
|
||||
function _openid_math_add($x, $y) {
|
||||
$library = _openid_get_math_library();
|
||||
switch ($library) {
|
||||
case 'gmp':
|
||||
return gmp_strval(gmp_add($x, $y));
|
||||
case 'bcmath':
|
||||
return bcadd($x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the mul function from the available math library for OpenID.
|
||||
*/
|
||||
function _openid_math_mul($x, $y) {
|
||||
$library = _openid_get_math_library();
|
||||
switch ($library) {
|
||||
case 'gmp':
|
||||
return gmp_mul($x, $y);
|
||||
case 'bcmath':
|
||||
return bcmul($x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the div function from the available math library for OpenID.
|
||||
*/
|
||||
function _openid_math_div($x, $y) {
|
||||
$library = _openid_get_math_library();
|
||||
switch ($library) {
|
||||
case 'gmp':
|
||||
return gmp_div($x, $y);
|
||||
case 'bcmath':
|
||||
return bcdiv($x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the cmp function from the available math library for OpenID.
|
||||
*/
|
||||
function _openid_math_cmp($x, $y) {
|
||||
$library = _openid_get_math_library();
|
||||
switch ($library) {
|
||||
case 'gmp':
|
||||
return gmp_cmp($x, $y);
|
||||
case 'bcmath':
|
||||
return bccomp($x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the mod function from the available math library for OpenID.
|
||||
*/
|
||||
function _openid_math_mod($x, $y) {
|
||||
$library = _openid_get_math_library();
|
||||
switch ($library) {
|
||||
case 'gmp':
|
||||
return gmp_mod($x, $y);
|
||||
case 'bcmath':
|
||||
return bcmod($x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the pow function from the available math library for OpenID.
|
||||
*/
|
||||
function _openid_math_pow($x, $y) {
|
||||
$library = _openid_get_math_library();
|
||||
switch ($library) {
|
||||
case 'gmp':
|
||||
return gmp_pow($x, $y);
|
||||
case 'bcmath':
|
||||
return bcpow($x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the mul function from the available math library for OpenID.
|
||||
*/
|
||||
function _openid_math_powmod($x, $y, $z) {
|
||||
$library = _openid_get_math_library();
|
||||
switch ($library) {
|
||||
case 'gmp':
|
||||
return gmp_powm($x, $y, $z);
|
||||
case 'bcmath':
|
||||
return bcpowmod($x, $y, $z);
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
name: OpenID
|
||||
type: module
|
||||
description: 'Allows users to log into your site using OpenID.'
|
||||
version: VERSION
|
||||
package: Core
|
||||
core: 8.x
|
|
@ -1,234 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the openid module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function openid_schema() {
|
||||
$schema['openid_association'] = array(
|
||||
'description' => 'Stores temporary shared key association information for OpenID authentication.',
|
||||
'fields' => array(
|
||||
'idp_endpoint_uri' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'description' => 'URI of the OpenID Provider endpoint.',
|
||||
),
|
||||
'assoc_handle' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'description' => 'Primary Key: Used to refer to this association in subsequent messages.',
|
||||
),
|
||||
'assoc_type' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'description' => 'The signature algorithm used: one of HMAC-SHA1 or HMAC-SHA256.',
|
||||
),
|
||||
'session_type' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'description' => 'Valid association session types: "no-encryption", "DH-SHA1", and "DH-SHA256".',
|
||||
),
|
||||
'mac_key' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'description' => 'The MAC key (shared secret) for this association.',
|
||||
),
|
||||
'created' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => 'UNIX timestamp for when the association was created.',
|
||||
),
|
||||
'expires_in' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => 'The lifetime, in seconds, of this association.',
|
||||
),
|
||||
),
|
||||
'primary key' => array('assoc_handle'),
|
||||
);
|
||||
|
||||
$schema['openid_identities'] = array(
|
||||
'description' => 'Stores OpenID authentication mapping.',
|
||||
'fields' => array(
|
||||
'aid' => array(
|
||||
'description' => 'Primary Key: Unique authmap ID.',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'uid' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => "User's {users}.uid.",
|
||||
),
|
||||
'identifier' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'Unique OpenID identifier.',
|
||||
),
|
||||
),
|
||||
'unique keys' => array(
|
||||
'identifier' => array('identifier'),
|
||||
),
|
||||
'primary key' => array('aid'),
|
||||
'foreign keys' => array(
|
||||
'user' => array(
|
||||
'table' => 'users',
|
||||
'columns' => array('uid' => 'uid'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$schema['openid_nonce'] = array(
|
||||
'description' => 'Stores received openid.response_nonce per OpenID endpoint URL to prevent replay attacks.',
|
||||
'fields' => array(
|
||||
'idp_endpoint_uri' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'description' => 'URI of the OpenID Provider endpoint.',
|
||||
),
|
||||
'nonce' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'description' => 'The value of openid.response_nonce.',
|
||||
),
|
||||
'expires' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => 'A Unix timestamp indicating when the entry should expire.',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'nonce' => array('nonce'),
|
||||
'expires' => array('expires'),
|
||||
),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_requirements().
|
||||
*/
|
||||
function openid_requirements($phase) {
|
||||
$requirements = array();
|
||||
|
||||
if ($phase == 'runtime') {
|
||||
// Check for the PHP BC Math library.
|
||||
if (!function_exists('bcadd') && !function_exists('gmp_add')) {
|
||||
$requirements['openid_math'] = array(
|
||||
'value' => t('Not installed'),
|
||||
'severity' => REQUIREMENT_ERROR,
|
||||
'description' => t('OpenID suggests the use of either the <a href="@gmp">GMP Math</a> (recommended for performance) or <a href="@bc">BC Math</a> libraries to enable OpenID associations.', array('@gmp' => 'http://php.net/manual/book.gmp.php', '@bc' => 'http://www.php.net/manual/book.bc.php')),
|
||||
);
|
||||
}
|
||||
elseif (!function_exists('gmp_add')) {
|
||||
$requirements['openid_math'] = array(
|
||||
'value' => t('Not optimized'),
|
||||
'severity' => REQUIREMENT_WARNING,
|
||||
'description' => t('OpenID suggests the use of the GMP Math library for PHP for optimal performance. Check the <a href="@url">GMP Math Library documentation</a> for installation instructions.', array('@url' => 'http://www.php.net/manual/book.gmp.php')),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$requirements['openid_math'] = array(
|
||||
'value' => t('Installed'),
|
||||
);
|
||||
}
|
||||
$requirements['openid_math']['title'] = t('OpenID Math library');
|
||||
}
|
||||
|
||||
return $requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_update_last_removed().
|
||||
*/
|
||||
function openid_update_last_removed() {
|
||||
return 6000;
|
||||
}
|
||||
|
||||
/**
|
||||
* @addtogroup updates-7.x-to-8.x
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Moves xri_proxy_resolver settings from variable to config.
|
||||
*
|
||||
* @ingroup config_upgrade
|
||||
*/
|
||||
function openid_update_8001() {
|
||||
update_variables_to_config('openid.settings', array(
|
||||
'xri_proxy_resolver' => 'xri_proxy_resolver',
|
||||
));
|
||||
}
|
||||
/**
|
||||
* Move authentication mapping to an OpenID managed table.
|
||||
*/
|
||||
function openid_update_8002() {
|
||||
$schema['openid_identities'] = array(
|
||||
'description' => 'Stores OpenID authentication mapping.',
|
||||
'fields' => array(
|
||||
'aid' => array(
|
||||
'description' => 'Primary Key: Unique authmap ID.',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'uid' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => "User's {users}.uid.",
|
||||
),
|
||||
'identifier' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'Unique OpenID identifier.',
|
||||
),
|
||||
),
|
||||
'unique keys' => array(
|
||||
'identifier' => array('identifier'),
|
||||
),
|
||||
'primary key' => array('aid'),
|
||||
'foreign keys' => array(
|
||||
'user' => array(
|
||||
'table' => 'users',
|
||||
'columns' => array('uid' => 'uid'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
db_create_table('openid_identities', $schema['openid_identities']);
|
||||
|
||||
// Migrate entries from {authmap} to {openid_identities}.
|
||||
$query = db_select('authmap', 'a')
|
||||
->condition('module', 'openid');
|
||||
$query->addField('a', 'uid');
|
||||
$query->addField('a', 'authname', 'identifier');
|
||||
db_insert('openid_identities')
|
||||
->from($query)
|
||||
->execute();
|
||||
|
||||
// Remove old entries in {authmap}.
|
||||
db_delete('authmap')
|
||||
->condition('module', 'openid')
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-to-8.x".
|
||||
*/
|
|
@ -1,46 +0,0 @@
|
|||
(function ($) {
|
||||
|
||||
"use strict";
|
||||
|
||||
Drupal.behaviors.openid = {
|
||||
attach: function (context) {
|
||||
function clearStatus ($form) {
|
||||
$form.find('input:first').focus();
|
||||
// Clear input fields and reset any validation errors.
|
||||
$form[0].reset();
|
||||
|
||||
// Reset error state.
|
||||
$form.find('.error').removeClass('error');
|
||||
|
||||
// Forget saved identifier.
|
||||
$.cookie('Drupal.visitor.openid_identifier', null);
|
||||
}
|
||||
|
||||
if ($('#block-user-login').length) {
|
||||
var $login_form = $('#user-login-form');
|
||||
var $openid_form = $('#openid-login-form');
|
||||
|
||||
// Change link text and triggers loginchange event.
|
||||
var toggleClick = true;
|
||||
$('#block-user-login .openid-link').on('click', function() {
|
||||
if (toggleClick) {
|
||||
$(this).html(Drupal.t('Cancel OpenID login'));
|
||||
$login_form.hide();
|
||||
$openid_form.show();
|
||||
clearStatus($login_form);
|
||||
// Move focus to OpenID input.
|
||||
$('#edit-openid-identifier').focus();
|
||||
}
|
||||
else {
|
||||
$(this).html(Drupal.t('Log in using OpenID'));
|
||||
$login_form.show();
|
||||
$openid_form.hide();
|
||||
clearStatus($openid_form);
|
||||
}
|
||||
toggleClick = !toggleClick;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
})(jQuery, Drupal);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* User page callbacks for the openid module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback; Process an OpenID authentication.
|
||||
*/
|
||||
function openid_authentication_page() {
|
||||
$result = openid_complete();
|
||||
switch ($result['status']) {
|
||||
case 'success':
|
||||
return openid_authentication($result);
|
||||
case 'failed':
|
||||
drupal_set_message(t('OpenID login failed.'), 'error');
|
||||
break;
|
||||
case 'cancel':
|
||||
drupal_set_message(t('OpenID login cancelled.'));
|
||||
break;
|
||||
}
|
||||
drupal_goto();
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; Manage OpenID identities for the specified user.
|
||||
*/
|
||||
function openid_user_identities($account) {
|
||||
drupal_set_title(user_format_name($account));
|
||||
drupal_add_css(drupal_get_path('module', 'openid') . '/openid.css');
|
||||
|
||||
// Check to see if we got a response
|
||||
$response = openid_complete();
|
||||
if ($response['status'] == 'success') {
|
||||
$identity = $response['openid.claimed_id'];
|
||||
$query = db_insert('openid_identities')
|
||||
->fields(array(
|
||||
'uid' => $account->uid,
|
||||
'identifier' => $identity,
|
||||
))
|
||||
->execute();
|
||||
drupal_set_message(t('Successfully added %identity', array('%identity' => $identity)));
|
||||
// Let other modules act on OpenID authentication.
|
||||
module_invoke_all('openid_response', $response, $account);
|
||||
}
|
||||
|
||||
$header = array(t('OpenID'), t('Operations'));
|
||||
$rows = array();
|
||||
|
||||
$result = db_query("SELECT * FROM {openid_identities} WHERE uid=:uid", array(':uid' => $account->uid));
|
||||
foreach ($result as $identity) {
|
||||
$row = array();
|
||||
$row[] = check_plain($identity->identifier);
|
||||
$links = array();
|
||||
$links['delete'] = array(
|
||||
'title' => t('Delete'),
|
||||
'href' => 'user/' . $account->uid . '/openid/delete/' . $identity->aid,
|
||||
);
|
||||
$row[] = array(
|
||||
'data' => array(
|
||||
'#type' => 'operations',
|
||||
'#links' => $links,
|
||||
),
|
||||
);
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
$build['openid_table'] = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => t('No OpenID identities available for this account.'),
|
||||
);
|
||||
$build['openid_user_add'] = drupal_get_form('openid_user_add');
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form builder; Add an OpenID identity.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see openid_user_add_validate()
|
||||
*/
|
||||
function openid_user_add() {
|
||||
$form['openid_identifier'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('OpenID'),
|
||||
);
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Add an OpenID'));
|
||||
return $form;
|
||||
}
|
||||
|
||||
function openid_user_add_validate($form, &$form_state) {
|
||||
// Check for existing entries.
|
||||
$claimed_id = openid_normalize($form_state['values']['openid_identifier']);
|
||||
if (db_query("SELECT identifier FROM {openid_identities} WHERE identifier = :identifier", array(':identifier' => $claimed_id))->fetchField()) {
|
||||
form_set_error('openid_identifier', t('That OpenID is already in use on this site.'));
|
||||
}
|
||||
}
|
||||
|
||||
function openid_user_add_submit($form, &$form_state) {
|
||||
$return_to = url('user/' . arg(1) . '/openid', array('absolute' => TRUE));
|
||||
openid_begin($form_state['values']['openid_identifier'], $return_to);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
openid_user_delete_form:
|
||||
pattern: '/user/{account}/openid/delete/{aid}'
|
||||
options:
|
||||
converters:
|
||||
account: 'user'
|
||||
defaults:
|
||||
_form: 'Drupal\openid\Form\UserDeleteForm'
|
||||
requirements:
|
||||
_entity_access: 'account.update'
|
|
@ -1,9 +0,0 @@
|
|||
name: 'OpenID dummy provider'
|
||||
type: module
|
||||
description: 'OpenID provider used for testing.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- openid
|
||||
hidden: true
|
|
@ -1,374 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Dummy OpenID Provider used with SimpleTest.
|
||||
*
|
||||
* The provider simply responds positively to all authentication requests. In
|
||||
* addition to a Provider Endpoint (a URL used for Drupal to communicate with
|
||||
* the provider using the OpenID Authentication protocol) the module provides
|
||||
* URLs used by the various discovery mechanisms.
|
||||
*
|
||||
* When a user enters an OpenID identity, the Relying Party (in the testing
|
||||
* scenario, this is the OpenID module) looks up the URL of the Provider
|
||||
* Endpoint using one of several discovery mechanisms. The Relying Party then
|
||||
* redirects the user to Provider Endpoint. The provider verifies the user's
|
||||
* identity and redirects the user back to the Relying Party accompanied by a
|
||||
* signed message confirming the identity. Before redirecting to a provider for
|
||||
* the first time, the Relying Party fetches a secret MAC key from the provider
|
||||
* by doing a direct "associate" HTTP request to the Provider Endpoint. This
|
||||
* key is used for verifying the signed messages from the provider.
|
||||
*/
|
||||
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function openid_test_menu() {
|
||||
$items['openid-test/yadis/xrds'] = array(
|
||||
'title' => 'XRDS service document',
|
||||
'page callback' => 'openid_test_yadis_xrds',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['openid-test/yadis/x-xrds-location'] = array(
|
||||
'title' => 'Yadis discovery using X-XRDS-Location header',
|
||||
'page callback' => 'openid_test_yadis_x_xrds_location',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['openid-test/yadis/http-equiv'] = array(
|
||||
'title' => 'Yadis discovery using <meta http-equiv="X-XRDS-Location" ...>',
|
||||
'page callback' => 'openid_test_yadis_http_equiv',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['openid-test/html/openid1'] = array(
|
||||
'title' => 'HTML-based discovery using <link rel="openid.server" ...>',
|
||||
'page callback' => 'openid_test_html_openid1',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['openid-test/html/openid2'] = array(
|
||||
'title' => 'HTML-based discovery using <link rel="openid2.provider" ...>',
|
||||
'page callback' => 'openid_test_html_openid2',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['openid-test/endpoint'] = array(
|
||||
'title' => 'OpenID Provider Endpoint',
|
||||
'page callback' => 'openid_test_endpoint',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['openid-test/redirect'] = array(
|
||||
'title' => 'OpenID Provider Redirection Point',
|
||||
'page callback' => 'openid_test_redirect',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['openid-test/redirected/%/%'] = array(
|
||||
'title' => 'OpenID Provider Final URL',
|
||||
'page callback' => 'openid_test_redirected_method',
|
||||
'page arguments' => array(2, 3),
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_site_status_alter().
|
||||
*/
|
||||
function openid_test_menu_site_status_alter(&$menu_site_status, $path) {
|
||||
// Allow access to openid endpoint and identity even in offline mode.
|
||||
if ($menu_site_status == MENU_SITE_OFFLINE && user_is_anonymous() && in_array($path, array('openid-test/yadis/xrds', 'openid-test/endpoint'))) {
|
||||
$menu_site_status = MENU_SITE_ONLINE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; XRDS document that references the OP Endpoint URL.
|
||||
*/
|
||||
function openid_test_yadis_xrds() {
|
||||
if ($_SERVER['HTTP_ACCEPT'] == 'application/xrds+xml') {
|
||||
// Only respond to XRI requests for one specific XRI. The is used to verify
|
||||
// that the XRI has been properly encoded. The "+" sign in the _xrd_r query
|
||||
// parameter is decoded to a space by PHP.
|
||||
if (arg(3) == 'xri' && (arg(4) != '@example*résumé;%25' || $_GET['_xrd_r'] != 'application/xrds xml')) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$output = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
if (!empty($_GET['doctype'])) {
|
||||
$output .= "\n<!DOCTYPE dct [ <!ELEMENT blue (#PCDATA)> ]>\n";
|
||||
}
|
||||
$output .= '
|
||||
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)" xmlns:openid="http://openid.net/xmlns/1.0">
|
||||
<XRD>
|
||||
<Status cid="' . check_plain(state()->get('openid_test.canonical_id_status') ?: 'verified') . '"/>
|
||||
<ProviderID>xri://@</ProviderID>
|
||||
<CanonicalID>http://example.com/user</CanonicalID>
|
||||
<Service>
|
||||
<Type>http://example.com/this-is-ignored</Type>
|
||||
</Service>
|
||||
<Service priority="5">
|
||||
<Type>http://openid.net/signon/1.0</Type>
|
||||
<URI>http://example.com/this-is-only-openid-1.0</URI>
|
||||
</Service>
|
||||
<Service priority="10">
|
||||
<Type>http://specs.openid.net/auth/2.0/signon</Type>
|
||||
<Type>http://openid.net/srv/ax/1.0</Type>
|
||||
<URI>' . url('openid-test/endpoint', array('absolute' => TRUE)) . '</URI>
|
||||
<LocalID>http://example.com/xrds</LocalID>
|
||||
</Service>
|
||||
<Service priority="15">
|
||||
<Type>http://specs.openid.net/auth/2.0/signon</Type>
|
||||
<URI>http://example.com/this-has-too-low-priority</URI>
|
||||
</Service>
|
||||
<Service>
|
||||
<Type>http://specs.openid.net/auth/2.0/signon</Type>
|
||||
<URI>http://example.com/this-has-too-low-priority</URI>
|
||||
</Service>
|
||||
';
|
||||
if (arg(3) == 'server') {
|
||||
$output .= '
|
||||
<Service>
|
||||
<Type>http://specs.openid.net/auth/2.0/server</Type>
|
||||
<URI>http://example.com/this-has-too-low-priority</URI>
|
||||
</Service>
|
||||
<Service priority="20">
|
||||
<Type>http://specs.openid.net/auth/2.0/server</Type>
|
||||
<URI>' . url('openid-test/endpoint', array('absolute' => TRUE)) . '</URI>
|
||||
</Service>';
|
||||
}
|
||||
elseif (arg(3) == 'delegate') {
|
||||
$output .= '
|
||||
<Service priority="0">
|
||||
<Type>http://specs.openid.net/auth/2.0/signon</Type>
|
||||
<Type>http://openid.net/srv/ax/1.0</Type>
|
||||
<URI>' . url('openid-test/endpoint', array('absolute' => TRUE)) . '</URI>
|
||||
<openid:Delegate>http://example.com/xrds-delegate</openid:Delegate>
|
||||
</Service>';
|
||||
}
|
||||
$output .= '
|
||||
</XRD>
|
||||
</xrds:XRDS>';
|
||||
return new Response($output, 200, array('Content-type' => 'application/xrds+xml; charset=utf-8'));
|
||||
}
|
||||
else {
|
||||
return t('This is a regular HTML page. If the client sends an Accept: application/xrds+xml header when requesting this URL, an XRDS document is returned.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; regular HTML page with an X-XRDS-Location HTTP header.
|
||||
*/
|
||||
function openid_test_yadis_x_xrds_location() {
|
||||
drupal_add_http_header('X-XRDS-Location', url('openid-test/yadis/xrds', array('absolute' => TRUE)));
|
||||
return t('This page includes an X-RDS-Location HTTP header containing the URL of an XRDS document.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; regular HTML page with <meta> element.
|
||||
*/
|
||||
function openid_test_yadis_http_equiv() {
|
||||
$element = array(
|
||||
'#tag' => 'meta',
|
||||
'#attributes' => array(
|
||||
'http-equiv' => "X-XRDS-Location\n",
|
||||
'content' => url('openid-test/yadis/xrds', array('absolute' => TRUE)),
|
||||
),
|
||||
);
|
||||
drupal_add_html_head($element, 'openid_test_yadis_http_equiv');
|
||||
return t('This page includes a <meta equiv=...> element containing the URL of an XRDS document.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; regular HTML page with OpenID 1.0 <link> element.
|
||||
*/
|
||||
function openid_test_html_openid1() {
|
||||
drupal_add_html_head_link(array('rel' => 'openid.server', 'href' => url('openid-test/endpoint', array('absolute' => TRUE))));
|
||||
drupal_add_html_head_link(array('rel' => 'openid.delegate', 'href' => 'http://example.com/html-openid1'));
|
||||
return t('This page includes a <link rel=...> element containing the URL of an OpenID Provider Endpoint.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; regular HTML page with OpenID 2.0 <link> element.
|
||||
*/
|
||||
function openid_test_html_openid2() {
|
||||
// Use unusual values in order to test proper parsing of HTML attributes.
|
||||
drupal_add_html_head_link(array('rel' => "foo\nopenid2.PROVIDER\tbar", 'href' => "\n" . url('openid-test/endpoint', array('absolute' => TRUE))));
|
||||
drupal_add_html_head_link(array('rel' => 'openid2.local_id', 'href' => 'http://example.com/html-openid2'));
|
||||
return t('This page includes a <link rel=...> element containing the URL of an OpenID Provider Endpoint.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; OpenID Provider Endpoint.
|
||||
*
|
||||
* It accepts "associate" requests directly from the Relying Party, and
|
||||
* "checkid_setup" requests made by the user's browser based on HTTP redirects
|
||||
* (in OpenID 1) or HTML forms (in OpenID 2) generated by the Relying Party.
|
||||
*/
|
||||
function openid_test_endpoint() {
|
||||
switch ($_REQUEST['openid_mode']) {
|
||||
case 'associate':
|
||||
return _openid_test_endpoint_associate();
|
||||
case 'checkid_setup':
|
||||
return _openid_test_endpoint_authenticate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; redirect during Normalization/Discovery.
|
||||
*/
|
||||
function openid_test_redirect($count = 0) {
|
||||
if ($count == 0) {
|
||||
$url = state()->get('openid_test.redirect_url');
|
||||
}
|
||||
else {
|
||||
$url = url('openid-test/redirect/' . --$count, array('absolute' => TRUE));
|
||||
}
|
||||
$http_response_code = state()->get('openid_test.redirect_http_response_code') ?: 301;
|
||||
return new RedirectResponse($url, $http_response_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; respond with appropriate callback.
|
||||
*/
|
||||
function openid_test_redirected_method($method1, $method2) {
|
||||
return call_user_func('openid_test_' . $method1 . '_' . $method2);
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenID endpoint; handle "associate" requests (see OpenID Authentication 2.0,
|
||||
* section 8).
|
||||
*
|
||||
* The purpose of association is to send the secret MAC key to the Relying Party
|
||||
* using Diffie-Hellman key exchange. The MAC key is used in subsequent
|
||||
* "authenticate" requests. The "associate" request is made by the Relying Party
|
||||
* (in the testing scenario, this is the OpenID module that communicates with
|
||||
* the endpoint).
|
||||
*/
|
||||
function _openid_test_endpoint_associate() {
|
||||
module_load_include('inc', 'openid');
|
||||
|
||||
// Use default parameters for Diffie-Helmann key exchange.
|
||||
$mod = OPENID_DH_DEFAULT_MOD;
|
||||
$gen = OPENID_DH_DEFAULT_GEN;
|
||||
|
||||
// Generate private Diffie-Helmann key.
|
||||
$r = _openid_dh_rand($mod);
|
||||
$private = _openid_math_add($r, 1);
|
||||
|
||||
// Calculate public Diffie-Helmann key.
|
||||
$public = _openid_math_powmod($gen, $private, $mod);
|
||||
|
||||
// Calculate shared secret based on Relying Party's public key.
|
||||
$cpub = _openid_dh_base64_to_long($_REQUEST['openid_dh_consumer_public']);
|
||||
$shared = _openid_math_powmod($cpub, $private, $mod);
|
||||
|
||||
// Encrypt the MAC key using the shared secret.
|
||||
$enc_mac_key = base64_encode(_openid_dh_xorsecret($shared, NULL));
|
||||
|
||||
// Generate response including our public key and the MAC key. Using our
|
||||
// public key and its own private key, the Relying Party can calculate the
|
||||
// shared secret, and with this it can decrypt the encrypted MAC key.
|
||||
$response = array(
|
||||
'ns' => 'http://specs.openid.net/auth/2.0',
|
||||
'assoc_handle' => 'openid-test',
|
||||
'session_type' => $_REQUEST['openid_session_type'],
|
||||
'assoc_type' => $_REQUEST['openid_assoc_type'],
|
||||
'expires_in' => '3600',
|
||||
'dh_server_public' => _openid_dh_long_to_base64($public),
|
||||
'enc_mac_key' => $enc_mac_key,
|
||||
);
|
||||
|
||||
// Respond to Relying Party in the special Key-Value Form Encoding (see OpenID
|
||||
// Authentication 1.0, section 4.1.1).
|
||||
return new Response(_openid_create_message($response), 200, array('Content-Type' => 'text/plain'));
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenID endpoint; handle "authenticate" requests.
|
||||
*
|
||||
* All requests result in a successful response. The request is a GET or POST
|
||||
* made by the user's browser based on an HTML form or HTTP redirect generated
|
||||
* by the Relying Party. The user is redirected back to the Relying Party using
|
||||
* a URL containing a signed message in the query string confirming the user's
|
||||
* identity.
|
||||
*/
|
||||
function _openid_test_endpoint_authenticate() {
|
||||
module_load_include('inc', 'openid');
|
||||
|
||||
$expected_identity = state()->get('openid_test.identity');
|
||||
if ($expected_identity && $_REQUEST['openid_identity'] != $expected_identity) {
|
||||
$response = state()->get('openid_test.response') ?: array();
|
||||
$response += array(
|
||||
'openid.ns' => OPENID_NS_2_0,
|
||||
'openid.mode' => 'error',
|
||||
'openid.error' => 'Unexpted identity',
|
||||
);
|
||||
return new RedirectResponse(url($_REQUEST['openid_return_to'], array('query' => $response, 'external' => TRUE)));
|
||||
}
|
||||
|
||||
// Generate unique identifier for this authentication.
|
||||
$nonce = _openid_nonce();
|
||||
|
||||
// Generate response containing the user's identity.
|
||||
$response = state()->get('openid_test.response') ?: array();
|
||||
$response += array(
|
||||
'openid.ns' => OPENID_NS_2_0,
|
||||
'openid.mode' => 'id_res',
|
||||
'openid.op_endpoint' => url('openid-test/endpoint', array('absolute' => TRUE)),
|
||||
'openid.claimed_id' => !empty($_REQUEST['openid_claimed_id']) ? $_REQUEST['openid_claimed_id'] : '',
|
||||
'openid.identity' => $_REQUEST['openid_identity'],
|
||||
'openid.return_to' => $_REQUEST['openid_return_to'],
|
||||
'openid.response_nonce' => $nonce,
|
||||
'openid.assoc_handle' => 'openid-test',
|
||||
);
|
||||
|
||||
if (isset($response['openid.signed'])) {
|
||||
$keys_to_sign = explode(',', $response['openid.signed']);
|
||||
}
|
||||
else {
|
||||
// Unless openid.signed is explicitly defined, all keys are signed.
|
||||
$keys_to_sign = array();
|
||||
foreach ($response as $key => $value) {
|
||||
// Strip off the "openid." prefix.
|
||||
$keys_to_sign[] = substr($key, 7);
|
||||
}
|
||||
$response['openid.signed'] = implode(',', $keys_to_sign);
|
||||
}
|
||||
|
||||
// Sign the message using the MAC key that was exchanged during association.
|
||||
$association = new stdClass();
|
||||
$association->mac_key = NULL;
|
||||
if (!isset($response['openid.sig'])) {
|
||||
$response['openid.sig'] = _openid_signature($association, $response, $keys_to_sign);
|
||||
}
|
||||
|
||||
// Put the signed message into the query string of a URL supplied by the
|
||||
// Relying Party, and redirect the user.
|
||||
return new RedirectResponse(url($_REQUEST['openid_return_to'], array('query' => $response, 'external', TRUE)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_openid_request_alter().
|
||||
*/
|
||||
function openid_test_openid_request_alter(&$request, $service) {
|
||||
$parameters = state()->get('openid_test.request_alter');
|
||||
if (isset($parameters[$request['openid.mode']])) {
|
||||
$request = $parameters[$request['openid.mode']] + $request;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_openid_response().
|
||||
*/
|
||||
function openid_test_openid_response($response, $account) {
|
||||
state()->set('openid_test.hook_openid_response_response', $response);
|
||||
state()->set('openid_test.hook_openid_response_account', $account ? $account : FALSE);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Database additions for authmap tests. Used in
|
||||
* \Drupal\openid\Tests\Upgrade\OpenIDAuthmapUpgradePathTest.
|
||||
*
|
||||
* This dump only contains data and schema components relevant for user authmap
|
||||
* upgrade tests.
|
||||
*/
|
||||
|
||||
db_insert('authmap')->fields(array(
|
||||
'aid',
|
||||
'uid',
|
||||
'authname',
|
||||
'module',
|
||||
))
|
||||
->values(array(
|
||||
'aid' => 1,
|
||||
'uid' => 1,
|
||||
'authname' => 'userA@providerA',
|
||||
'module' => 'openid',
|
||||
))
|
||||
->values(array(
|
||||
'aid' => 2,
|
||||
'uid' => 1,
|
||||
'authname' => 'userB@providerA',
|
||||
'module' => 'openid',
|
||||
))
|
||||
->values(array(
|
||||
'aid' => 3,
|
||||
'uid' => 1,
|
||||
'authname' => 'userA@providerB',
|
||||
'module' => 'fancy',
|
||||
))
|
||||
->execute();
|
|
@ -1,94 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Database additions for openid tests.
|
||||
*
|
||||
* This dump enables openid module, the drupal-7.bare.minimal.database.php.gz
|
||||
* file is imported before this dump, so the two form the database structure
|
||||
* expected in tests altogether.
|
||||
*/
|
||||
|
||||
db_create_table('openid_association', array(
|
||||
'fields' => array(
|
||||
'idp_endpoint_uri' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
),
|
||||
'assoc_handle' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'assoc_type' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
),
|
||||
'session_type' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
),
|
||||
'mac_key' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
),
|
||||
'created' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'expires_in' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
),
|
||||
'primary key' => array(
|
||||
'assoc_handle',
|
||||
),
|
||||
'module' => 'openid',
|
||||
'name' => 'openid_association',
|
||||
));
|
||||
|
||||
db_create_table('openid_nonce', array(
|
||||
'fields' => array(
|
||||
'idp_endpoint_uri' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
),
|
||||
'nonce' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
),
|
||||
'expires' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'nonce' => array(
|
||||
'nonce',
|
||||
),
|
||||
'expires' => array(
|
||||
'expires',
|
||||
),
|
||||
),
|
||||
'module' => 'openid',
|
||||
'name' => 'openid_nonce',
|
||||
));
|
||||
|
||||
db_update('system')
|
||||
->fields(array(
|
||||
'filename' => 'modules/openid/openid.module',
|
||||
'name' => 'openid',
|
||||
'type' => 'module',
|
||||
'owner' => '',
|
||||
'status' => '1',
|
||||
'bootstrap' => '0',
|
||||
'schema_version' => '6000',
|
||||
'weight' => '0',
|
||||
'info' => 'a:11:{s:4:"name";s:6:"OpenID";s:11:"description";s:48:"Allows users to log into your site using OpenID.";s:7:"version";s:11:"7.14+29-dev";s:7:"package";s:4:"Core";s:4:"core";s:3:"7.x";s:5:"files";a:1:{i:0;s:11:"openid.test";}s:7:"project";s:6:"drupal";s:9:"datestamp";s:10:"1338768537";s:12:"dependencies";a:0:{}s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}',
|
||||
))
|
||||
->condition('filename', 'modules/openid/openid.module')
|
||||
->execute();
|
|
@ -58,15 +58,6 @@ ul.tips {
|
|||
padding-left: 0;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
.region-header #block-user-login ul.openid-links li.last {
|
||||
padding-right: 0;
|
||||
}
|
||||
.region-header #user-login-form li.openid-link a,
|
||||
.region-header #user-login li.openid-link a {
|
||||
background-position: right -3px;
|
||||
padding-left: 0;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
/* --------------- Main Menu ------------ */
|
||||
|
||||
|
|
|
@ -441,13 +441,6 @@ h1#site-name {
|
|||
.region-header #block-user-login .item-list li.last {
|
||||
padding-left: 0.5em; /* LTR */
|
||||
}
|
||||
.region-header #block-user-login ul.openid-links li.last {
|
||||
padding-left: 0; /* LTR */
|
||||
}
|
||||
.region-header #user-login-form li.openid-link a,
|
||||
.region-header #user-login li.openid-link a {
|
||||
padding-left: 20px; /* LTR */
|
||||
}
|
||||
.region-header #block-user-login .form-actions {
|
||||
margin: 4px 0 0;
|
||||
padding: 0;
|
||||
|
|
|
@ -150,14 +150,6 @@ ol.task-list li.active {
|
|||
padding: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
/* User login block */
|
||||
#user-login-form .openid-links {
|
||||
margin-right: 0;
|
||||
}
|
||||
#user-login-form .openid-links .user-link {
|
||||
margin-right: 1.5em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve spacing of cancel link.
|
||||
*/
|
||||
|
|
|
@ -1108,14 +1108,6 @@ h1#overlay-title {
|
|||
padding: 0 5px 5px 0; /* LTR */
|
||||
}
|
||||
|
||||
/* User login block */
|
||||
#user-login-form .openid-links {
|
||||
margin-left: 0; /* LTR */
|
||||
}
|
||||
#user-login-form .openid-links .user-link {
|
||||
margin-left: 1.5em; /* LTR */
|
||||
}
|
||||
|
||||
/* Dropbutton */
|
||||
.js .dropbutton-widget {
|
||||
background-color: #fff;
|
||||
|
|
Loading…
Reference in New Issue