http://www.mediawiki.org/wiki/Special:Code/MediaWiki/94219

Revision: 94219
Author:   neilk
Date:     2011-08-11 01:50:11 +0000 (Thu, 11 Aug 2011)
Log Message:
-----------
experimental identity api, so chat server / etherpad can authenticate a user as 
being logged into the wiki via MediaWiki api

Added Paths:
-----------
    branches/extensions-realtime/IdentityApi/
    branches/extensions-realtime/IdentityApi/IdentityApi.class.php
    branches/extensions-realtime/IdentityApi/IdentityApi.i18n.php
    branches/extensions-realtime/IdentityApi/IdentityApi.php
    branches/extensions-realtime/IdentityApi/README
    branches/extensions-realtime/IdentityApi/api/
    branches/extensions-realtime/IdentityApi/api/ApiQueryIdentity.php
    branches/extensions-realtime/IdentityApi/api/ApiQueryVerifyIdentity.php

Added: branches/extensions-realtime/IdentityApi/IdentityApi.class.php
===================================================================
--- branches/extensions-realtime/IdentityApi/IdentityApi.class.php              
                (rev 0)
+++ branches/extensions-realtime/IdentityApi/IdentityApi.class.php      
2011-08-11 01:50:11 UTC (rev 94219)
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * Static class for general functions of the IdentityApi extension.
+ *
+ * @file IdentityApi.classphp
+ *
+ * @licence GNU GPL v2 or later
+ * @author Neil Kandalgaonkar <[email protected]>
+ */
+
+class IdentityApi {
+
+       /**
+        * Return authentication parameters for currently logged in user, or 
null
+        * @return {Null|Array}  
+        */
+       public static function getAuthParams() {
+               global $wgUser, $wgServer, $wgScriptPath, $wgMemc, 
$wgIdentityApiConfig;
+
+               if ( !( $wgUser && $wgUser->isLoggedIn() ) ) {
+                       return null;
+               }
+                       
+               $data = array( 
+                       'user_id' => $wgUser->getId(), 
+                       'cookie' => $_COOKIE,
+               );
+               $token = $wgUser->generateToken();
+
+               $wgMemc->set( wfMemcKey( $token ), $data, 
$wgIdentityApiConfig['timeoutSeconds'] );
+
+               return array( 
+                       'apiurl' => $wgServer . $wgScriptPath . '/api.php',
+                       'username' => $wgUser->getName(),
+                       'token' => $token
+               );
+       }
+
+       /**
+        * Verifies that this user is logged in -- using memcached
+        * @param User
+        * @param String token, which we created in getAuth()
+        * @param Array extra queries, array of strings that represent what 
other info to return
+        * @return Array key-val, including 'verified' => boolean, and any 
other properties that may have
+        *                              been asked for in $extra
+        */
+       public static function verifyAuthParams( $user, $token, $extras ) { 
+               global $wgMemc;
+               $ret = array( 'verified' => false );
+               $data = $wgMemc->get( wfMemcKey( $token ) );
+               if ( isset( $data ) and $data !== null and $data['user_id'] ) {
+                       $ret['verified'] = ( intval( $user->getId() ) === 
intval( $data['user_id'] ) );
+               }
+               if ( $ret['verified'] ) {
+                       $ret = array_merge( $ret, IdentityApi::getExtraInfo( 
$user, $data, $extras ) );
+               }
+               return $ret;
+       }
+
+       /**
+        * Gets additional information, as specified in $extras
+        * @param User
+        * @param Array (data as was stored)
+        * @param Array (array of strings, options for what data to return);
+        */
+       public static function getExtraInfo( $user, $data, $extras ) {
+               global $wgServer, $wgArticlePath;
+               $ret = array();
+               foreach ( $extras as $extra ) { 
+                       $extraInfo = array();
+                       if ( preg_match( '/^avatarSrc=(\\d+)$/', $extra, 
$matches ) ) {
+                               if ( class_exists( 'AvatarService' ) ) {
+                                       $avatarSize = intval( $matches[1] );    
+                                       $ret['avatarSrc'] = 
AvatarService::getAvatarUrl( $user->getName(), $avatarSize );
+                               }
+                       }
+                       switch ( $extra ) {
+                               case 'chat':
+                                       if ( class_exists( 'Chat' ) ) {
+                                               $canChat = Chat::canChat( $user 
);
+                                               if ( $canChat ) {
+                                                       $ret['canChat'] = 
$canChat;
+                                                       $ret['isChatMod'] = 
$user->isAllowed( 'chatmoderator' );
+                                                       $userChangeableGroups = 
$user->changeableGroups(); // php makes us use a temp variable here, sigh
+                                                       
$ret['isCanGiveChatMode'] = in_array( 'chatmoderator', 
$userChangeableGroups['add'] ); 
+                                                       // TODO if still 
relevant, check for cross-wiki chat hack (see 
https://svn.wikia-code.com/wikia/trunk/extensions/wikia/Chat/ChatAjax.class.php 
)
+                                                       // TODO get user stats 
for chat (see 
https://svn.wikia-code.com/wikia/trunk/extensions/wikia/Chat/ChatAjax.class.php 
)
+                                               }
+                                       }
+                                       break;
+                               case 'cookie':
+                                       $ret['cookie'] = $data['cookie'];
+                                       break;
+                               case 'isLoggedIn':
+                                       $ret['isLoggedIn'] = 
$user->isLoggedIn();
+                                       break;
+                               case 'isStaff':
+                                       // Wikia-specific
+                                       $ret['isStaff'] = $user->isAllowed( 
'staff' );
+                                       break;
+                               case 'username':
+                                       $ret['username'] = $user->getName();
+                                       break;
+                               case 'wgServer':
+                                       $ret['wgServer'] = $wgServer;
+                               case 'wgArticlePath':
+                                       $ret['wgArticlePath'] = $wgArticlePath;
+                               default:
+                                       break;
+                       }       
+               }
+               return $ret;
+       }
+
+}


Property changes on: 
branches/extensions-realtime/IdentityApi/IdentityApi.class.php
___________________________________________________________________
Added: svn:eol-style
   + native

Added: branches/extensions-realtime/IdentityApi/IdentityApi.i18n.php
===================================================================
--- branches/extensions-realtime/IdentityApi/IdentityApi.i18n.php               
                (rev 0)
+++ branches/extensions-realtime/IdentityApi/IdentityApi.i18n.php       
2011-08-11 01:50:11 UTC (rev 94219)
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * Internationalization file for IdentityApi extension.
+ *
+ * @file IdentityApi.i18n.php
+ *
+ * @licence GNU GPL v2 or later
+ * @author Neil Kandalgaonkar <[email protected]>
+ */
+
+$messages = array();
+
+/** English
+ * @author Neil Kandalgaonkar <[email protected]>
+ */
+$messages['en'] = array(
+       'identityapi-desc' => 'Provides API methods that help a remote service 
verify the identity of a user on this wiki'
+);     


Property changes on: 
branches/extensions-realtime/IdentityApi/IdentityApi.i18n.php
___________________________________________________________________
Added: svn:eol-style
   + native

Added: branches/extensions-realtime/IdentityApi/IdentityApi.php
===================================================================
--- branches/extensions-realtime/IdentityApi/IdentityApi.php                    
        (rev 0)
+++ branches/extensions-realtime/IdentityApi/IdentityApi.php    2011-08-11 
01:50:11 UTC (rev 94219)
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * Provides a means for users to verify their identity on this wiki to a 
remote service.
+ * 
+ * For example: imagine if you wanted to associate a chat service with your 
wiki, and users should have the same names on 
+ * the chat service as they do on the wiki. This isn't as complicated of a 
case as OpenID or oAuth, we just want two well-known services
+ * run by the same organization to verify identity. 
+ * 
+ * This could also be done with a shared secret, but this way we can avoid 
having to distribute that secret or keep it up to date, and there
+ * aren't any consequences if the secret is discovered.
+ * 
+ * Documentation:                      
http://www.mediawiki.org/wiki/Extension:IdentityApi
+ * Source code:             
http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/IdentityApi
+ *
+ * @author Neil Kandalgaonkar <[email protected]>
+ * @license GPL v2 or later
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+       die( 'Not an entry point.' );
+}
+
+if ( version_compare( $wgVersion, '1.17', '<' ) ) {
+       die( 'This extension requires MediaWiki 1.17 or above.' );
+}
+
+if ( ! $wgSessionsInMemcached ) {
+       die( 'This extension requires you to be storing sessions in Memcached 
(for now)' );
+}
+
+
+define( 'IdentityApi_VERSION', '0.1' );
+
+$wgExtensionCredits['other'][] = array(
+       'path' => __FILE__,
+       'name' => 'IdentityApi',
+       'version' => IdentityApi_VERSION,
+       'author' => array(
+               '[http://www.mediawiki.org/wiki/User:NeilK NeilK]',
+       ),
+       'url' => 'http://www.mediawiki.org/wiki/Extension:IdentityApi',
+       'descriptionmsg' => 'identityapi-desc'
+);
+
+$wgExtensionMessagesFiles['IdentityApi'] = dirname( __FILE__ ) . 
'/IdentityApi.i18n.php';
+
+$wgAutoloadClasses['IdentityApi'] = dirname( __FILE__ ) . 
'/IdentityApi.class.php';
+
+$wgAutoloadClasses['ApiQueryVerifyIdentity'] = dirname( __FILE__ ) . 
'/api/ApiQueryVerifyIdentity.php';
+$wgAPIModules['verifyidentity'] = 'ApiQueryVerifyIdentity';
+$wgAutoloadClasses['ApiQueryIdentity'] = dirname( __FILE__ ) . 
'/api/ApiQueryIdentity.php';
+$wgAPIModules['identity'] = 'ApiQueryIdentity';
+
+
+$wgIdentityApiConfig = array(
+       'timeoutSeconds' => 60 * 60 * 24  // one day
+);


Property changes on: branches/extensions-realtime/IdentityApi/IdentityApi.php
___________________________________________________________________
Added: svn:eol-style
   + native

Added: branches/extensions-realtime/IdentityApi/README
===================================================================
--- branches/extensions-realtime/IdentityApi/README                             
(rev 0)
+++ branches/extensions-realtime/IdentityApi/README     2011-08-11 01:50:11 UTC 
(rev 94219)
@@ -0,0 +1,12 @@
+This extension is experimental. It should not be used by anyone in a 
production environment.
+
+The purpose of this extension is to act as a sort of identity helper for other 
non-MediaWiki services that might be
+run in the same hosting environment. An example might be a chat server, where 
it is desirable that users have the same
+user name on the chat as they do on the wiki (and that users cannot 
impersonate one another).
+
+This implementation is based on Wikia's Chat module AJAX functions[1], but 
tries to be more general.
+
+-- Neil Kandalgaonkar <[email protected]> 10 Aug 2011
+
+
+[1] See 
https://svn.wikia-code.com/wikia/trunk/extensions/wikia/Chat/ChatAjax.class.php

Added: branches/extensions-realtime/IdentityApi/api/ApiQueryIdentity.php
===================================================================
--- branches/extensions-realtime/IdentityApi/api/ApiQueryIdentity.php           
                (rev 0)
+++ branches/extensions-realtime/IdentityApi/api/ApiQueryIdentity.php   
2011-08-11 01:50:11 UTC (rev 94219)
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * API module to allow a non-mediawiki service to know that a certain user is 
who s/he claims to be on this wiki.
+ * See the README for what this extension is and isn't.
+ *
+ * @file ApiQueryIdentity.php
+ *
+ * @licence GNU GPL v2 or later
+ * @author Neil Kandalgaonkar <[email protected]>
+ */
+class ApiQueryIdentity extends ApiQueryBase {
+       public function __construct( $main, $action ) {
+               parent::__construct( $main, $action, 'vi' );
+       }
+
+       /**
+        * Obtain data we can pass for the purposes of verifying a user later
+        */
+       public function execute() {
+               $auth = IdentityApi::getAuthParams( $user );
+
+               if ( $auth === null ) {
+                       $this->dieUsage( 'Could not obtain auth credentials - 
are you logged in?', 'mustbeloggedin' );
+               }
+
+               // a wiki is identified by the root URL of the API -- 
everything else about a wiki is 
+               // dependent on Apache configuration
+               foreach ( $auth as $key => $val ) {
+                       $this->getResult()->addValue( 'authentication', $key, 
$val );
+               }
+               
+       }
+
+       /**
+        * ???? do we need this? XSRF? TODO
+        * Indicates whether this module must be called with a POST request
+        * @return bool
+        */
+       public function mustBePosted() {
+               return false;
+       }
+
+       /**
+        * Probably needed to avoid XSRF -- TODO 
+        * Returns whether this module requires a Token to execute
+        * @return bool
+        */
+       public function needsToken() {
+               return false;
+       }
+
+       public function getAllowedParams() {
+               return array();
+       }
+
+       public function getParamDescription() {
+               return array();
+       }
+
+       public function getDescription() {
+               return 'API module to allow a non-mediawiki service to know 
that a certain user is who s/he claims to be on this wiki';
+       }
+       
+       public function getPossibleErrors() {
+               return array();
+       }       
+       
+       protected function getExamples() {
+               return array (
+                       'api.php?action=identity'
+               );
+       }
+
+       public function getVersion() {
+               return __CLASS__ . ': $Id: $';
+       }       
+       
+}


Property changes on: 
branches/extensions-realtime/IdentityApi/api/ApiQueryIdentity.php
___________________________________________________________________
Added: svn:eol-style
   + native

Added: branches/extensions-realtime/IdentityApi/api/ApiQueryVerifyIdentity.php
===================================================================
--- branches/extensions-realtime/IdentityApi/api/ApiQueryVerifyIdentity.php     
                        (rev 0)
+++ branches/extensions-realtime/IdentityApi/api/ApiQueryVerifyIdentity.php     
2011-08-11 01:50:11 UTC (rev 94219)
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * API module to allow a non-mediawiki service to know that a certain user is 
who s/he claims to be on this wiki.
+ * See the README for what this extension is and isn't.
+ *
+ * @file ApiQueryVerifyIdentity.php
+ *
+ * @licence GNU GPL v2 or later
+ * @author Neil Kandalgaonkar <[email protected]>
+ */
+class ApiQueryVerifyIdentity extends ApiQueryBase {
+       public function __construct( $main, $action ) {
+               parent::__construct( $main, $action, 'vi' );
+       }
+
+       /**
+        * Verify that a user has a certain active login session.
+        */
+       public function execute() {
+               $params = $this->extractRequestParams();
+               $result = array( 'verified' => false );
+       
+               // check if this user is a user who can login
+               if ( User::isUsableName( $params['user'] ) ) {
+                       // and even exists
+                       $userId = User::idFromName( $params['user'] );
+                       if ( $userId !== null ) {
+                               $user = User::newFromId( $userId );
+                               $token = $params['token'];
+                               $extras = preg_split( '/\|/', $params['extras'] 
);
+                               $result = IdentityApi::verifyAuthParams( $user, 
$token, $extras );
+                       }
+               }
+
+               foreach ( $result as $key => $val ) { 
+                       $this->getResult()->addValue( 'authentication', $key, 
$val );
+               }
+       }
+       
+       public function getAllowedParams() {
+               return array (
+                       'user' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true,
+                       ),
+                       'token' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true,
+                       ),
+                       'extras' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => false,
+                               ApiBase::PARAM_DFLT => '',
+                       )
+               );
+       }
+
+       public function getParamDescription() {
+               return array (
+                       'token' => 'The token that the user offers as proof of 
their identity; obtained through an identity API query',
+                       'user' => 'The username the user claims to have on this 
wiki',
+                       'extras' => 'If verified, extra information to return 
about the user or the wiki, delimited by pipe (|) characters.'
+                               . ' Possible values: avatarSrc, chat, cookie, 
isLoggedIn, isStaff, username, wgServer, wgArticlePath',
+               );
+       }
+
+       public function getDescription() {
+               return 'API module to allow a non-mediawiki service to know 
that a certain user is who s/he claims to be on this wiki';
+       }
+       
+       public function getPossibleErrors() {
+               return array_merge( parent::getPossibleErrors(), array(
+                       array( 'missingparam', 'token' ), 
+                       array( 'missingparam', 'user' )
+               ) );
+       }       
+       
+       protected function getExamples() {
+               return array (
+                       
'api.php?action=verifyidentity&viuser=NeilK&vitoken=abcdef123456&viextras=avatarSrc|chat|cookie|isStaff|username',
+               );
+       }
+
+       public function getVersion() {
+               return __CLASS__ . ': $Id: $';
+       }       
+       
+}


Property changes on: 
branches/extensions-realtime/IdentityApi/api/ApiQueryVerifyIdentity.php
___________________________________________________________________
Added: svn:eol-style
   + native


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to