====== OAuth for Dokuwiki ======
Towards [[http://oauth.net|oAuth]] support for [[http://dokuwiki.org|DokuWiki]].
The use-case are manifold: oAuth allows to perform //secure authenticated// requests (eg. over HTTP) without requiring a user to disclose credentials. Dokuwiki can make use of this for instance with XML-RPC, [[wiki:dokupubsub]], batch media-upload (client-applications) or even feed subscription, etc. Simply: any DokuWiki request.
You may still want to run a HTTPS server to authenticate users by plaintext-password against DokuWiki or require digest-auth (which still requires the user to know the password). Combined with openID, oAuth is a prerequisite for distributed client-server and server-to-server communication such as feed/media aggregation or DokuWiki-farms over insecure connections.
===== Authentication Patch =====
Patch DokuWiki's ''inc/auth.php'' to provide a trigger that allows to //hook into// the authentication mechanism.
--- a/inc/auth.php
+++ b/inc/auth.php
@@ -72,7 +72,13 @@
// external trust mechanism in place
$auth->trustExternal($_REQUEST['u'],$_REQUEST['p'],$_REQUEST['r']);
}else{
- auth_login($_REQUEST['u'],$_REQUEST['p'],$_REQUEST['r']);
+ $evt = new Doku_Event('ACTION_ON_AUTH',$ACT);
+ $evt->advise_before();
+ if(empty($_SERVER['REMOTE_USER'])) {
+ auth_login($_REQUEST['u'],$_REQUEST['p'],$_REQUEST['r']);
+ }
+ $evt->advise_after();
+ unset($evt);
}
}
\\
\\
**Example** //action-plugin// to provide authentication on a per HTTP-request basis:
if(!defined('DOKU_INC')) die();
class action_plugin_oauth extends DokuWiki_Action_Plugin {
function register(&$contr){
$contr->register_hook('ACTION_ON_AUTH',
'BEFORE',
$this,
'handle_act_authhook');
$contr->register_hook('ACTION_ACT_PREPROCESS',
'BEFORE',
$this,
'handle_act_preprocess');
}
function handle_act_authhook(&$event, $param){
if (is_array($_REQUEST['do']) && !empty($_REQUEST['do']['oauth'])) return; // skip requests to oauth-API itself
if (!empty($_REQUEST['oauth_signature'])) {
// verify signature
// check consumer and access token
// -> bail out if signature mismatch
// -> set username for this session
// dokuwiki - set user
$user='root';
$_SERVER['REMOTE_USER'] = $user;
global $USERINFO;
global $auth;
$USERINFO = $auth->getUserData($user);
if (!is_array($USERINFO)) {
$_SERVER['REMOTE_USER'] = "";
// or bail out..
}
}
}
function handle_act_preprocess(&$event, $param){
$handled=false;
if (!empty($event->data['oauth'])) {
// ...
// token-exchange, admin, etc.
//
}
if ($handled) {
$event->stopPropagation();
$event->preventDefault();
$event->data="show";
}
}
}
//Setup VIM: ex: et sw=4 ts=4 enc=utf-8 :
\\
\\
**Discussion**
Adding the ''ACTION_ON_AUTH'' event to [[http://www.dokuwiki.org/devel:events_list|existing events]] does not seem to be too far out; however it raises a some concerns:
- it makes it easier to write a exploiting-plugin
- may slow down the system - the Auth Event plugin is called for each request!
- it's somewhat //parallel// to ''inc/auth/*.php'' structure.
The first is not really true, //any// plugin can be used to perform malicious actions; it's just that ''ACTION_ON_AUTH'' should never be used carelessly. This ties into the second issue: pay strict attention to optimize performance of the callback handler - On a wiki with ACLs those will be called for **each** request!
Last but not least: oAuth is not a [[http://www.dokuwiki.org/devel:authentication_backends|DokuWiki authentication backend]], it **uses** the ''getUserData()'' from the backend. Instead of adding a hook, the auth-backends could be nested: oAuth could wrap the default auth-backend overriding the ''checkPass()'' function. Adding an Event seems to be a much cleaner way to implement this.
===== OAuth Plugin =====
work in progress - see [[http://gareus.org/gitweb/?p=dokuoauth.git|devel repository]]\\
or download a [[http://gareus.org/gitweb/?p=dokuoauth.git;a=snapshot;h=HEAD|devel snapshot]] (don't use this link with the DokuWiki plugin manager.)
The plugin implements an oAuth-Service Provider consisting of several parts:
* a handler for the oAuth protocol: request and exchange tokens
* a handler for token/user-admin: authorize, admin keys & secrets
* a handler for transparent authentication: any request with a valid oauth-signature and authorized access-token bypasses ''checkPass()'' and authenticates a DokuWiki-user on the fly.
==== Config ====
None needed. There's a few Options in //Configuration Settings// most of which are related to debugging or development.
After installing the Plugin, visit ''http://example.org/doku.php?do=oauth'' to administrate tokens or simply run the example script on the next page which
adds a test consumer for you.
==== Info ====
The OAuthDataStore is kept in ''DOKU_CONF/oauth.inidb'' as dba.ini text data; the config-folder (or at least latter file) needs to be writable for the web-sever.
//Note//: Apache rewrite-rules modify the base-string! (This is to be fixed or worked-around) The query-parameters and URL must not be modified before they are passed to the PHP script (using ''DirectoryIndex doku.php'' works, redirecting from index.php does not.) - This is a minor issue since in general oAuth requests always use a full absolute URL ending with ''/doku.php'' (or ''/lib/lib/exe/xmlrpc.php'') to access the DokuWiki API.
**ToDo**
* implement Token expiry
* add RSA-KEY admin.
* redo/style Admin/User interface (''helper.php'')
* oAuth-Disovery (both client & server)
* oauth-Consumer (sign outgoing requests): per user eg. image-aggregate, save-edit ; per-page(or page owner) eg. feed
===== Test & Examples =====
You can access the DokuWiki OAuth API by making requests to ''doku.php?do[oauth]=XXX'' or simply by making //any// request adding the ''oauth_signature'' request-parameter.
Visit ''?do=oauth'' for the oauth plugin information page. For test-requests see [[dokuoauth_examples]].
{{tag>FLOSS WWW dokuplugin}}