====== 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}}