From acaf07f6e8c873e0069e84dac74bac3c7da98a97 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 30 Oct 2009 13:21:11 -0400 Subject: Added an "Verify Your Identity" page to the OpenID provider --- classes/statusnet.ini | 10 +++ plugins/OpenID/OpenIDPlugin.php | 9 ++ plugins/OpenID/User_openid_trustroot.php | 29 +++++++ plugins/OpenID/openidserver.php | 24 +++++- plugins/OpenID/openidtrust.php | 142 +++++++++++++++++++++++++++++++ 5 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 plugins/OpenID/User_openid_trustroot.php create mode 100644 plugins/OpenID/openidtrust.php diff --git a/classes/statusnet.ini b/classes/statusnet.ini index 7931c7bcd..623790b10 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -537,6 +537,16 @@ modified = 384 canonical = K display = U +[user_openid_trustroot] +trustroot = 130 +user_id = 129 +created = 142 +modified = 384 + +[user_openid__keys] +trustroot = K +user_id = K + [user_role] user_id = 129 role = 130 diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php index 5ebee2cbe..02fc79b04 100644 --- a/plugins/OpenID/OpenIDPlugin.php +++ b/plugins/OpenID/OpenIDPlugin.php @@ -150,6 +150,7 @@ class OpenIDPlugin extends Plugin 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': @@ -286,6 +287,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 @@ +mode, array('checkid_immediate', 'checkid_setup'))) { $cur = common_current_user(); - error_log("Request identity: " . $request->identity); if(!$cur){ /* 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($cur->nickname) == $request->identity || $request->idSelect()){ - $response = &$request->answer(true, null, common_profile_url($cur->nickname)); + $user_openid_trustroot = User_openid_trustroot::pkeyGet( + array('user_id'=>$cur->id, 'trustroot'=>$request->trustroot)); + if(empty($user_openid_trustroot)){ + if($request->immediate){ + //cannot prompt the user to trust this trust root in immediate mode, so answer false + $response = &$request->answer(false); + }else{ + //ask the user to trust this trust root + $_SESSION['openid_trust_root'] = $request->trust_root; + $allowResponse = $request->answer(true, null, common_profile_url($cur->nickname)); + $denyResponse = $request->answer(false); + common_ensure_session(); + $_SESSION['openid_allow_url'] = $allowResponse->encodeToUrl(); + $_SESSION['openid_deny_url'] = $denyResponse->encodeToUrl(); + common_redirect(common_local_url('openidtrust')); + return; + } + }else{ + //user has previously authorized this trust root + $response = &$request->answer(true, null, common_profile_url($cur->nickname)); + } } else if ($request->immediate) { $response = &$request->answer(false); } else { 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 @@ +. + */ + +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'); + } +} -- cgit v1.2.3-54-g00ecf From 204eb5b0c42e5e90f8f03e89953239b4d2fc738c Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 30 Oct 2009 13:42:54 -0400 Subject: made openidserver a login action so it can be seen when the site is in "private" mode --- plugins/OpenID/OpenIDPlugin.php | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php index 02fc79b04..2309eea9d 100644 --- a/plugins/OpenID/OpenIDPlugin.php +++ b/plugins/OpenID/OpenIDPlugin.php @@ -180,6 +180,7 @@ class OpenIDPlugin extends Plugin { case 'openidlogin': case 'finishopenidlogin': + case 'openidserver': $login = true; return false; default: -- cgit v1.2.3-54-g00ecf From cdbf7b1da522ea42c0cdc62b59e07a8499bf7972 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 30 Oct 2009 13:48:18 -0400 Subject: Allow non-users to view the site's xrds when the site is private. Getting to closer to allow OpenID login on private sites. --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 644812bd5..3acdba375 100644 --- a/index.php +++ b/index.php @@ -143,7 +143,7 @@ function checkMirror($action_obj, $args) function isLoginAction($action) { - static $loginActions = array('login', 'recoverpassword', 'api', 'doc', 'register'); + static $loginActions = array('login', 'recoverpassword', 'api', 'doc', 'register', 'publicxrds'); $login = null; -- cgit v1.2.3-54-g00ecf From 982850c9c75eb2eb9821ae1e3ce76594ffdf4b7e Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 30 Oct 2009 15:33:04 -0400 Subject: Added simple registration (sreg) support to the OpenID provider --- plugins/OpenID/openidserver.php | 88 +++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/plugins/OpenID/openidserver.php b/plugins/OpenID/openidserver.php index 8ffe979b0..dab97c93e 100644 --- a/plugins/OpenID/openidserver.php +++ b/plugins/OpenID/openidserver.php @@ -48,68 +48,104 @@ require_once(INSTALLDIR.'/plugins/OpenID/User_openid_trustroot.php'); */ class OpenidserverAction extends Action { + var $oserver; + + function prepare($args) + { + parent::prepare($args); + $this->oserver = oid_server(); + return true; + } function handle($args) { parent::handle($args); - $oserver = oid_server(); - $request = $oserver->decodeRequest(); + $request = $this->oserver->decodeRequest(); if (in_array($request->mode, array('checkid_immediate', 'checkid_setup'))) { - $cur = common_current_user(); - if(!$cur){ - /* 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($cur->nickname) == $request->identity || $request->idSelect()){ + $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'=>$cur->id, 'trustroot'=>$request->trustroot)); + 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 = &$request->answer(false); + $response = $this->generateDenyResponse($request); }else{ - //ask the user to trust this trust root - $_SESSION['openid_trust_root'] = $request->trust_root; - $allowResponse = $request->answer(true, null, common_profile_url($cur->nickname)); - $denyResponse = $request->answer(false); 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 = &$request->answer(true, null, common_profile_url($cur->nickname)); + $response = $this->generateAllowResponse($request, $user); + //$response = $request->answer(true, null, common_profile_url($user->nickname)); } } else if ($request->immediate) { - $response = &$request->answer(false); + $response = $this->generateDenyResponse($request); } else { //invalid $this->clientError(sprintf(_('You are not authorized to use the identity %s'),$request->identity),$code=403); } } else { - $response = &$oserver->handleRequest($request); + $response = $this->oserver->handleRequest($request); } if($response){ - $webresponse = $oserver->encodeResponse($response); - - if ($webresponse->code != AUTH_OPENID_HTTP_OK) { - header(sprintf("HTTP/1.1 %d ", $webresponse->code), - true, $webresponse->code); + $response = $this->oserver->encodeResponse($response); + if ($response->code != AUTH_OPENID_HTTP_OK) { + header(sprintf("HTTP/1.1 %d ", $response->code), + true, $response->code); } - if($webresponse->headers){ - foreach ($webresponse->headers as $k => $v) { + if($response->headers){ + foreach ($response->headers as $k => $v) { header("$k: $v"); } } - $this->raw($webresponse->body); + $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; + } } -- cgit v1.2.3-54-g00ecf From fc22bde67cd9a92ffb27bd8ce9258035fb25e582 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 30 Oct 2009 16:01:20 -0400 Subject: Redirect to login when trying to send a direct message while not logged in. http://status.net/trac/ticket/1359 --- actions/newmessage.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/actions/newmessage.php b/actions/newmessage.php index a0b17fc18..eac4ab210 100644 --- a/actions/newmessage.php +++ b/actions/newmessage.php @@ -99,7 +99,9 @@ class NewmessageAction extends Action $user = common_current_user(); if (!$user) { - $this->clientError(_('Only logged-in users can send direct messages.'), 403); + /* Go log in, and then come back. */ + common_set_returnto($_SERVER['REQUEST_URI']); + common_redirect(common_local_url('login')); return false; } -- cgit v1.2.3-54-g00ecf From b7ed31c27bc883b7b7b6a9af6391aacd8d897d78 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 30 Oct 2009 16:53:23 -0400 Subject: Use nickname from profile, not user object, to avoid barfing warnings on Twitter messages imported into the timeline. --- actions/shownotice.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/shownotice.php b/actions/shownotice.php index 41408c23c..5d16fdad9 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -172,9 +172,9 @@ class ShownoticeAction extends OwnerDesignAction function title() { if (!empty($this->profile->fullname)) { - $base = $this->profile->fullname . ' (' . $this->user->nickname . ') '; + $base = $this->profile->fullname . ' (' . $this->profile->nickname . ') '; } else { - $base = $this->user->nickname; + $base = $this->profile->nickname; } return sprintf(_('%1$s\'s status on %2$s'), -- cgit v1.2.3-54-g00ecf