From eb5c81dea5a60bc65d3ec607daf5ad81fd709928 Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Tue, 30 Sep 2014 23:13:49 +0200 Subject: [PATCH] store client name and last use time for tokens. show them in token management --- appinfo/database.xml | 11 +++++++ appinfo/info.xml | 2 +- appinfo/version | 2 +- controller/apicontroller.php | 32 +++----------------- controller/guicontroller.php | 4 ++- controller/oauthcontroller.php | 19 +++++++++--- lib/client.php | 55 ++++++++++++++++++++++++++++++++++ lib/oauth.php | 8 ++++- lib/token.php | 14 +++++++++ lib/tokenstorage.php | 29 ++++++++++++++++-- templates/tokens.php | 4 +-- 11 files changed, 139 insertions(+), 41 deletions(-) create mode 100644 lib/client.php diff --git a/appinfo/database.xml b/appinfo/database.xml index 176f89f..7419ee7 100755 --- a/appinfo/database.xml +++ b/appinfo/database.xml @@ -51,6 +51,17 @@ true 2048 + + token_client + text + true + 256 + + + token_lastuse + timestamp + true + diff --git a/appinfo/info.xml b/appinfo/info.xml index 2074d61..bff1ebd 100755 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -3,7 +3,7 @@ grauphel Grauphel: Tomboy note server Tomboy REST API server to sync notes between devices - 0.2.0 + 0.3.0 AGPL3 or later Christian Weiske 7 diff --git a/appinfo/version b/appinfo/version index 0ea3a94..0d91a54 100755 --- a/appinfo/version +++ b/appinfo/version @@ -1 +1 @@ -0.2.0 +0.3.0 diff --git a/controller/apicontroller.php b/controller/apicontroller.php index ee16f80..688d0b0 100644 --- a/controller/apicontroller.php +++ b/controller/apicontroller.php @@ -16,6 +16,7 @@ namespace OCA\Grauphel\Controller; use \OCP\AppFramework\Controller; use \OCP\AppFramework\Http\JSONResponse; +use \OCA\Grauphel\Lib\Client; use \OCA\Grauphel\Lib\NoteStorage; use \OCA\Grauphel\Lib\OAuth; use \OCA\Grauphel\Lib\OAuthException; @@ -105,10 +106,10 @@ class ApiController extends Controller 'api-version' => '1.0', ); - $client = $this->getClient(); + $cl = new Client(); + $client = $cl->getClient(); if ($client !== false) { - $data['oauth_authorize_url'] .= '?client=' - . urlencode($this->getNiceClientName($client)); + $data['oauth_authorize_url'] .= '?client=' . urlencode($client); } if ($authenticated) { @@ -333,31 +334,6 @@ class ApiController extends Controller return new JSONResponse($note); } - protected function getClient() - { - if (isset($_SERVER['HTTP_X_TOMBOY_CLIENT'])) { - $client = $_SERVER['HTTP_X_TOMBOY_CLIENT']; - $doublepos = strpos($client, ', org.tomdroid'); - if ($doublepos !== false) { - //https://bugs.launchpad.net/tomdroid/+bug/1375436 - //X-Tomboy-Client header is sent twice - $client = substr($client, 0, $doublepos); - } - return $client; - } - - return false; - } - - protected function getNiceClientName($client) - { - if (substr($client, 0, 12) == 'org.tomdroid') { - //org.tomdroid v0.7.5, build 14, Android v4.4.2, innotek GmbH/VirtualBox - return 'Tomdroid'; - } - return $client; - } - /** * Checks if the given user is authorized (by oauth token or normal login) * diff --git a/controller/guicontroller.php b/controller/guicontroller.php index 947e23e..6d59fd5 100644 --- a/controller/guicontroller.php +++ b/controller/guicontroller.php @@ -15,6 +15,7 @@ namespace OCA\Grauphel\Controller; use \OCP\AppFramework\Controller; use \OCP\AppFramework\Http\TemplateResponse; +use \OCA\Grauphel\Lib\Client; use \OCA\Grauphel\Lib\TokenStorage; /** @@ -108,7 +109,8 @@ class GuiController extends Controller array( 'tokens' => $tokens->loadForUser( $this->user->getUid(), 'access' - ) + ), + 'client' => new Client(), ) ); $this->addNavigation($res, null); diff --git a/controller/oauthcontroller.php b/controller/oauthcontroller.php index 6ab17d2..bc66de4 100644 --- a/controller/oauthcontroller.php +++ b/controller/oauthcontroller.php @@ -18,6 +18,7 @@ use \OCP\AppFramework\Http; use \OCP\AppFramework\Http\RedirectResponse; use \OCP\AppFramework\Http\TemplateResponse; +use \OCA\Grauphel\Lib\Client; use \OCA\Grauphel\Lib\Token; use \OCA\Grauphel\Lib\OAuth; use \OCA\Grauphel\Lib\Dependencies; @@ -87,6 +88,7 @@ class OauthController extends Controller $newToken->tokenKey = 'a' . bin2hex($provider->generateToken(8)); $newToken->secret = 's' . bin2hex($provider->generateToken(8)); $newToken->user = $token->user; + $newToken->client = $token->client; $this->deps->tokens->store($newToken); return new FormResponse( @@ -118,19 +120,22 @@ class OauthController extends Controller return $token; } - $client = 'unknown'; + $clientTitle = 'unknown'; + $clientAgent = ''; if (isset($_GET['client'])) { - $client = $_GET['client']; + $clientAgent = $_GET['client']; + $cl = new Client(); + $clientTitle = $cl->getNiceName($clientAgent); } $res = new TemplateResponse('grauphel', 'oauthAuthorize'); $res->setParams( array( 'oauth_token' => $token->tokenKey, - 'client' => $client, + 'client' => $clientTitle, 'formaction' => $this->deps->urlGen->linkToRoute( 'grauphel.oauth.confirm' - ), + ) . '?client=' . urlencode($clientAgent), ) ); return $res; @@ -172,6 +177,11 @@ class OauthController extends Controller return $res; } + $clientAgent = ''; + if (isset($_GET['client'])) { + $clientAgent = $_GET['client']; + } + //the user is logged in and authorized $provider = OAuth::getProvider(); @@ -180,6 +190,7 @@ class OauthController extends Controller $newToken->secret = $token->secret; $newToken->verifier = 'v' . bin2hex($provider->generateToken(8)); $newToken->user = $this->user->getUID(); + $newToken->client = $clientAgent; $this->deps->tokens->store($newToken); diff --git a/lib/client.php b/lib/client.php new file mode 100644 index 0000000..358e60b --- /dev/null +++ b/lib/client.php @@ -0,0 +1,55 @@ + + * @copyright 2014 Christian Weiske + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/grauphel.htm + */ +namespace OCA\Grauphel\Lib; + +/** + * Client identification helper + * + * @category Tools + * @package Grauphel + * @author Christian Weiske + * @copyright 2014 Christian Weiske + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @version Release: @package_version@ + * @link http://cweiske.de/grauphel.htm + */ +class Client +{ + public function getClient() + { + if (isset($_SERVER['HTTP_X_TOMBOY_CLIENT'])) { + $client = $_SERVER['HTTP_X_TOMBOY_CLIENT']; + $doublepos = strpos($client, ', org.tomdroid'); + if ($doublepos !== false) { + //https://bugs.launchpad.net/tomdroid/+bug/1375436 + //X-Tomboy-Client header is sent twice + $client = substr($client, 0, $doublepos); + } + return $client; + } + + return false; + } + + public function getNiceName($client) + { + if (substr($client, 0, 12) == 'org.tomdroid') { + //org.tomdroid v0.7.5, build 14, Android v4.4.2, innotek GmbH/VirtualBox + return 'Tomdroid'; + } + return $client; + } + +} +?> \ No newline at end of file diff --git a/lib/oauth.php b/lib/oauth.php index 5f84e7e..231a177 100644 --- a/lib/oauth.php +++ b/lib/oauth.php @@ -111,6 +111,12 @@ class OAuth } throw $e; } + + if (time() - $token->lastuse > 60) { + //time to update lastuse after at least a minute + $this->tokens->updateLastUse($token->tokenKey); + } + $provider->token_secret = $token->secret; return OAUTH_OK; } @@ -147,7 +153,7 @@ class OAuth /** * Get a new oauth provider instance. * Used to work around the fastcgi bug in oauthprovider. - * + * * @return \OAuthProvider */ public static function getProvider() diff --git a/lib/token.php b/lib/token.php index ebb0783..2cf6580 100644 --- a/lib/token.php +++ b/lib/token.php @@ -69,6 +69,20 @@ class Token */ public $callback; + /** + * Client name/identifier (user agent) + * + * @var string + */ + public $client; + + /** + * Unix timestamp when the token was used last + * + * @var integer + */ + public $lastuse; + public function __construct($type = null) { $this->type = $type; diff --git a/lib/tokenstorage.php b/lib/tokenstorage.php index b9689ab..cdbce11 100644 --- a/lib/tokenstorage.php +++ b/lib/tokenstorage.php @@ -37,15 +37,17 @@ class TokenStorage { \OC_DB::executeAudited( 'INSERT INTO `*PREFIX*grauphel_oauth_tokens`' - . '(`token_user`, `token_type`, `token_key`, `token_secret`, `token_verifier`, `token_callback`)' - . ' VALUES(?, ?, ?, ?, ?, ?)', + . '(`token_user`, `token_type`, `token_key`, `token_secret`, `token_verifier`, `token_callback`, `token_client`, `token_lastuse`)' + . ' VALUES(?, ?, ?, ?, ?, ?, ?, ?)', array( $token->user, $token->type, $token->tokenKey, (string) $token->secret, (string) $token->verifier, - (string) $token->callback + (string) $token->callback, + (string) $token->client, + (string) date('c'), ) ); } @@ -133,6 +135,25 @@ class TokenStorage return $tokens; } + /** + * Update the "last use" field of a token + * + * @param string $tokenKey Random token string to load + * + * @return void + */ + public function updateLastUse($tokenKey) + { + \OC_DB::executeAudited( + 'UPDATE `*PREFIX*grauphel_oauth_tokens`' + . ' SET `token_lastuse` = ? WHERE `token_key` = ?', + array( + (string) date('c'), + $tokenKey, + ) + ); + } + protected function fromDb($tokenRow) { $token = new Token(); @@ -142,6 +163,8 @@ class TokenStorage $token->user = $tokenRow['token_user']; $token->verifier = $tokenRow['token_verifier']; $token->callback = $tokenRow['token_callback']; + $token->client = $tokenRow['token_client']; + $token->lastuse = \strtotime($tokenRow['token_lastuse']); return $token; } } diff --git a/templates/tokens.php b/templates/tokens.php index 4a578f5..7707516 100644 --- a/templates/tokens.php +++ b/templates/tokens.php @@ -18,8 +18,8 @@ tokenKey); ?> - - + getNiceName($token->client)); ?> + lastuse)); ?> Disable Delete -- 2.30.2