summaryrefslogtreecommitdiff
path: root/plugins/OpenID
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/OpenID')
-rw-r--r--plugins/OpenID/OpenIDPlugin.php75
-rw-r--r--plugins/OpenID/User_openid_trustroot.php29
-rw-r--r--plugins/OpenID/finishopenidlogin.php2
-rw-r--r--plugins/OpenID/openid.php10
-rw-r--r--plugins/OpenID/openidserver.php151
-rw-r--r--plugins/OpenID/openidtrust.php142
-rw-r--r--plugins/OpenID/publicxrds.php122
7 files changed, 400 insertions, 131 deletions
diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php
index a933a1155..2309eea9d 100644
--- a/plugins/OpenID/OpenIDPlugin.php
+++ b/plugins/OpenID/OpenIDPlugin.php
@@ -62,17 +62,59 @@ class OpenIDPlugin extends Plugin
* @return boolean hook return
*/
- function onRouterInitialized(&$m)
+ function onStartInitializeRouter($m)
{
$m->connect('main/openid', array('action' => 'openidlogin'));
+ $m->connect('main/openidtrust', array('action' => 'openidtrust'));
$m->connect('settings/openid', array('action' => 'openidsettings'));
- $m->connect('xrds', array('action' => 'publicxrds'));
$m->connect('index.php?action=finishopenidlogin', array('action' => 'finishopenidlogin'));
$m->connect('index.php?action=finishaddopenid', array('action' => 'finishaddopenid'));
-
+ $m->connect('main/openidserver', array('action' => 'openidserver'));
+
return true;
}
+ function onEndPublicXRDS($action, &$xrdsOutputter)
+ {
+ $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
+ 'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
+ 'version' => '2.0'));
+ $xrdsOutputter->element('Type', null, 'xri://$xrds*simple');
+ //consumer
+ foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) {
+ $xrdsOutputter->showXrdsService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
+ common_local_url($finish));
+ }
+ //provider
+ $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/server',
+ common_local_url('openidserver'),
+ null,
+ null,
+ 'http://specs.openid.net/auth/2.0/identifier_select');
+ $xrdsOutputter->elementEnd('XRD');
+ }
+
+ function onEndUserXRDS($action, &$xrdsOutputter)
+ {
+ $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
+ 'xml:id' => 'openid',
+ 'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
+ 'version' => '2.0'));
+ $xrdsOutputter->element('Type', null, 'xri://$xrds*simple');
+
+ //consumer
+ $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/return_to',
+ common_local_url('finishopenidlogin'));
+
+ //provider
+ $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/signon',
+ common_local_url('openidserver'),
+ null,
+ null,
+ common_profile_url($action->user->nickname));
+ $xrdsOutputter->elementEnd('XRD');
+ }
+
function onEndLoginGroupNav(&$action)
{
$action_name = $action->trimmed('action');
@@ -107,6 +149,8 @@ class OpenIDPlugin extends Plugin
case 'XrdsAction':
case 'PublicxrdsAction':
case 'OpenidsettingsAction':
+ case 'OpenidserverAction':
+ case 'OpenidtrustAction':
require_once(INSTALLDIR.'/plugins/OpenID/' . strtolower(mb_substr($cls, 0, -6)) . '.php');
return false;
case 'User_openid':
@@ -136,6 +180,7 @@ class OpenIDPlugin extends Plugin
{
case 'openidlogin':
case 'finishopenidlogin':
+ case 'openidserver':
$login = true;
return false;
default:
@@ -150,11 +195,19 @@ class OpenIDPlugin extends Plugin
* @return void
*/
- function onEndHeadChildren($action)
+ function onEndShowHeadElements($action)
{
- // for client side of OpenID authentication
- $action->element('meta', array('http-equiv' => 'X-XRDS-Location',
- 'content' => common_local_url('publicxrds')));
+ if($action instanceof ShowstreamAction){
+ $action->element('link', array('rel' => 'openid2.provider',
+ 'href' => common_local_url('openidserver')));
+ $action->element('link', array('rel' => 'openid2.local_id',
+ 'href' => $action->profile->profileurl));
+ $action->element('link', array('rel' => 'openid.server',
+ 'href' => common_local_url('openidserver')));
+ $action->element('link', array('rel' => 'openid.delegate',
+ 'href' => $action->profile->profileurl));
+ }
+ return true;
}
/**
@@ -235,6 +288,14 @@ class OpenIDPlugin extends Plugin
new ColumnDef('created', 'datetime',
null, false),
new ColumnDef('modified', 'timestamp')));
+ $schema->ensureTable('user_openid_trustroot',
+ array(new ColumnDef('trustroot', 'varchar',
+ '255', false, 'PRI'),
+ new ColumnDef('user_id', 'integer',
+ null, false, 'PRI'),
+ new ColumnDef('created', 'datetime',
+ null, false),
+ new ColumnDef('modified', 'timestamp')));
return true;
}
}
diff --git a/plugins/OpenID/User_openid_trustroot.php b/plugins/OpenID/User_openid_trustroot.php
new file mode 100644
index 000000000..4654b72df
--- /dev/null
+++ b/plugins/OpenID/User_openid_trustroot.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Table Definition for user_openid_trustroot
+ */
+require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
+
+class User_openid_trustroot extends Memcached_DataObject
+{
+ ###START_AUTOCODE
+ /* the code below is auto generated do not remove the above tag */
+
+ public $__table = 'user_openid_trustroot'; // table name
+ public $trustroot; // varchar(255) primary_key not_null
+ public $user_id; // int(4) primary_key not_null
+ public $created; // datetime() not_null
+ public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
+
+ /* Static get */
+ function staticGet($k,$v=null)
+ { return Memcached_DataObject::staticGet('User_openid_trustroot',$k,$v); }
+
+ /* the code above is auto generated do not remove the tag below */
+ ###END_AUTOCODE
+
+ function &pkeyGet($kv)
+ {
+ return Memcached_DataObject::pkeyGet('User_openid_trustroot', $kv);
+ }
+}
diff --git a/plugins/OpenID/finishopenidlogin.php b/plugins/OpenID/finishopenidlogin.php
index 50a9c15c8..ff0b451d3 100644
--- a/plugins/OpenID/finishopenidlogin.php
+++ b/plugins/OpenID/finishopenidlogin.php
@@ -265,7 +265,7 @@ class FinishopenidloginAction extends Action
$fullname = '';
}
- if (!empty($sreg['email']) && Validate::email($sreg['email'], true)) {
+ if (!empty($sreg['email']) && Validate::email($sreg['email'], common_config('email', 'check_domain'))) {
$email = $sreg['email'];
} else {
$email = '';
diff --git a/plugins/OpenID/openid.php b/plugins/OpenID/openid.php
index 0944117c0..ff7a93899 100644
--- a/plugins/OpenID/openid.php
+++ b/plugins/OpenID/openid.php
@@ -23,6 +23,7 @@ require_once(INSTALLDIR.'/plugins/OpenID/User_openid.php');
require_once('Auth/OpenID.php');
require_once('Auth/OpenID/Consumer.php');
+require_once('Auth/OpenID/Server.php');
require_once('Auth/OpenID/SReg.php');
require_once('Auth/OpenID/MySQLStore.php');
@@ -50,6 +51,13 @@ function oid_consumer()
return $consumer;
}
+function oid_server()
+{
+ $store = oid_store();
+ $server = new Auth_OpenID_Server($store, common_local_url('openidserver'));
+ return $server;
+}
+
function oid_clear_last()
{
oid_set_last('');
@@ -241,7 +249,7 @@ function oid_update_user(&$user, &$sreg)
$orig_user = clone($user);
- if ($sreg['email'] && Validate::email($sreg['email'], true)) {
+ if ($sreg['email'] && Validate::email($sreg['email'], common_config('email', 'check_domain'))) {
$user->email = $sreg['email'];
}
diff --git a/plugins/OpenID/openidserver.php b/plugins/OpenID/openidserver.php
new file mode 100644
index 000000000..dab97c93e
--- /dev/null
+++ b/plugins/OpenID/openidserver.php
@@ -0,0 +1,151 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Settings for OpenID
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Settings
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/action.php';
+require_once INSTALLDIR.'/plugins/OpenID/openid.php';
+require_once(INSTALLDIR.'/plugins/OpenID/User_openid_trustroot.php');
+
+/**
+ * Settings for OpenID
+ *
+ * Lets users add, edit and delete OpenIDs from their account
+ *
+ * @category Settings
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+class OpenidserverAction extends Action
+{
+ var $oserver;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->oserver = oid_server();
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $request = $this->oserver->decodeRequest();
+ if (in_array($request->mode, array('checkid_immediate',
+ 'checkid_setup'))) {
+ $user = common_current_user();
+ if(!$user){
+ if($request->immediate){
+ //cannot prompt the user to login in immediate mode, so answer false
+ $response = $this->generateDenyResponse($request);
+ }else{
+ /* Go log in, and then come back. */
+ common_set_returnto($_SERVER['REQUEST_URI']);
+ common_redirect(common_local_url('login'));
+ return;
+ }
+ }else if(common_profile_url($user->nickname) == $request->identity || $request->idSelect()){
+ $user_openid_trustroot = User_openid_trustroot::pkeyGet(
+ array('user_id'=>$user->id, 'trustroot'=>$request->trust_root));
+ if(empty($user_openid_trustroot)){
+ if($request->immediate){
+ //cannot prompt the user to trust this trust root in immediate mode, so answer false
+ $response = $this->generateDenyResponse($request);
+ }else{
+ common_ensure_session();
+ $_SESSION['openid_trust_root'] = $request->trust_root;
+ $allowResponse = $this->generateAllowResponse($request, $user);
+ $this->oserver->encodeResponse($allowResponse); //sign the response
+ $denyResponse = $this->generateDenyResponse($request);
+ $this->oserver->encodeResponse($denyResponse); //sign the response
+ $_SESSION['openid_allow_url'] = $allowResponse->encodeToUrl();
+ $_SESSION['openid_deny_url'] = $denyResponse->encodeToUrl();
+ //ask the user to trust this trust root
+ common_redirect(common_local_url('openidtrust'));
+ return;
+ }
+ }else{
+ //user has previously authorized this trust root
+ $response = $this->generateAllowResponse($request, $user);
+ //$response = $request->answer(true, null, common_profile_url($user->nickname));
+ }
+ } else if ($request->immediate) {
+ $response = $this->generateDenyResponse($request);
+ } else {
+ //invalid
+ $this->clientError(sprintf(_('You are not authorized to use the identity %s'),$request->identity),$code=403);
+ }
+ } else {
+ $response = $this->oserver->handleRequest($request);
+ }
+
+ if($response){
+ $response = $this->oserver->encodeResponse($response);
+ if ($response->code != AUTH_OPENID_HTTP_OK) {
+ header(sprintf("HTTP/1.1 %d ", $response->code),
+ true, $response->code);
+ }
+
+ if($response->headers){
+ foreach ($response->headers as $k => $v) {
+ header("$k: $v");
+ }
+ }
+ $this->raw($response->body);
+ }else{
+ $this->clientError(_('Just an OpenID provider. Nothing to see here, move along...'),$code=500);
+ }
+ }
+
+ function generateAllowResponse($request, $user){
+ $response = $request->answer(true, null, common_profile_url($user->nickname));
+
+ $profile = $user->getProfile();
+ $sreg_data = array(
+ 'fullname' => $profile->fullname,
+ 'nickname' => $user->nickname,
+ 'email' => $user->email,
+ 'language' => $user->language,
+ 'timezone' => $user->timezone);
+ $sreg_request = Auth_OpenID_SRegRequest::fromOpenIDRequest($request);
+ $sreg_response = Auth_OpenID_SRegResponse::extractResponse(
+ $sreg_request, $sreg_data);
+ $sreg_response->toMessage($response->fields);
+ return $response;
+ }
+
+ function generateDenyResponse($request){
+ $response = $request->answer(false);
+ return $response;
+ }
+}
diff --git a/plugins/OpenID/openidtrust.php b/plugins/OpenID/openidtrust.php
new file mode 100644
index 000000000..29c7bdc23
--- /dev/null
+++ b/plugins/OpenID/openidtrust.php
@@ -0,0 +1,142 @@
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+
+require_once INSTALLDIR.'/plugins/OpenID/openid.php';
+require_once(INSTALLDIR.'/plugins/OpenID/User_openid_trustroot.php');
+
+class OpenidtrustAction extends Action
+{
+ var $trust_root;
+ var $allowUrl;
+ var $denyUrl;
+ var $user;
+
+ /**
+ * Is this a read-only action?
+ *
+ * @return boolean false
+ */
+
+ function isReadOnly($args)
+ {
+ return false;
+ }
+
+ /**
+ * Title of the page
+ *
+ * @return string title of the page
+ */
+
+ function title()
+ {
+ return _('OpenID Identity Verification');
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ common_ensure_session();
+ $this->user = common_current_user();
+ if(empty($this->user)){
+ /* Go log in, and then come back. */
+ common_set_returnto($_SERVER['REQUEST_URI']);
+ common_redirect(common_local_url('login'));
+ return;
+ }
+ $this->trust_root = $_SESSION['openid_trust_root'];
+ $this->allowUrl = $_SESSION['openid_allow_url'];
+ $this->denyUrl = $_SESSION['openid_deny_url'];
+ if(empty($this->trust_root) || empty($this->allowUrl) || empty($this->denyUrl)){
+ $this->clientError(_('This page should only be reached during OpenID processing, not directly.'));
+ return;
+ }
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ if($_SERVER['REQUEST_METHOD'] == 'POST'){
+ $this->handleSubmit();
+ }else{
+ $this->showPage();
+ }
+ }
+
+ function handleSubmit()
+ {
+ unset($_SESSION['openid_trust_root']);
+ unset($_SESSION['openid_allow_url']);
+ unset($_SESSION['openid_deny_url']);
+ if($this->arg('allow'))
+ {
+ //save to database
+ $user_openid_trustroot = new User_openid_trustroot();
+ $user_openid_trustroot->user_id = $this->user->id;
+ $user_openid_trustroot->trustroot = $this->trust_root;
+ $user_openid_trustroot->created = DB_DataObject_Cast::dateTime();
+ if (!$user_openid_trustroot->insert()) {
+ $err = PEAR::getStaticProperty('DB_DataObject','lastError');
+ common_debug('DB error ' . $err->code . ': ' . $err->message, __FILE__);
+ }
+ common_redirect($this->allowUrl, $code=302);
+ }else{
+ common_redirect($this->denyUrl, $code=302);
+ }
+ }
+
+ /**
+ * Show page notice
+ *
+ * Display a notice for how to use the page, or the
+ * error if it exists.
+ *
+ * @return void
+ */
+
+ function showPageNotice()
+ {
+ $this->element('p',null,sprintf(_('%s has asked to verify your identity. Click Continue to verify your identity and login without creating a new password.'),$this->trust_root));
+ }
+
+ /**
+ * Core of the display code
+ *
+ * Shows the login form.
+ *
+ * @return void
+ */
+
+ function showContent()
+ {
+ $this->elementStart('form', array('method' => 'post',
+ 'id' => 'form_openidtrust',
+ 'class' => 'form_settings',
+ 'action' => common_local_url('openidtrust')));
+ $this->elementStart('fieldset');
+ $this->submit('allow', _('Continue'));
+ $this->submit('deny', _('Cancel'));
+
+ $this->elementEnd('fieldset');
+ $this->elementEnd('form');
+ }
+}
diff --git a/plugins/OpenID/publicxrds.php b/plugins/OpenID/publicxrds.php
deleted file mode 100644
index 1b2b359ca..000000000
--- a/plugins/OpenID/publicxrds.php
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-
-/**
- * Public XRDS for OpenID
- *
- * PHP version 5
- *
- * @category Action
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Robin Millette <millette@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link http://status.net/
- *
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, StatusNet, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/plugins/OpenID/openid.php';
-
-/**
- * Public XRDS for OpenID
- *
- * @category Action
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Robin Millette <millette@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link http://status.net/
- *
- * @todo factor out similarities with XrdsAction
- */
-class PublicxrdsAction extends Action
-{
- /**
- * Is read only?
- *
- * @return boolean true
- */
- function isReadOnly($args)
- {
- return true;
- }
-
- /**
- * Class handler.
- *
- * @param array $args array of arguments
- *
- * @return nothing
- */
- function handle($args)
- {
- parent::handle($args);
- header('Content-Type: application/xrds+xml');
- $this->startXML();
- $this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
- $this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
- 'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
- 'version' => '2.0'));
- $this->element('Type', null, 'xri://$xrds*simple');
- foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) {
- $this->showService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
- common_local_url($finish));
- }
- $this->elementEnd('XRD');
- $this->elementEnd('XRDS');
- $this->endXML();
- }
-
- /**
- * Show service.
- *
- * @param string $type XRDS type
- * @param string $uri URI
- * @param array $params type parameters, null by default
- * @param array $sigs type signatures, null by default
- * @param string $localId local ID, null by default
- *
- * @return void
- */
- function showService($type, $uri, $params=null, $sigs=null, $localId=null)
- {
- $this->elementStart('Service');
- if ($uri) {
- $this->element('URI', null, $uri);
- }
- $this->element('Type', null, $type);
- if ($params) {
- foreach ($params as $param) {
- $this->element('Type', null, $param);
- }
- }
- if ($sigs) {
- foreach ($sigs as $sig) {
- $this->element('Type', null, $sig);
- }
- }
- if ($localId) {
- $this->element('LocalID', null, $localId);
- }
- $this->elementEnd('Service');
- }
-}
-