X-Git-Url: https://git.cweiske.de/grauphel.git/blobdiff_plain/3780cf15a59c48b3d71e8ec27e3bdacd8a119460..2cb2fae10d986db73bb0ad517df8c5334cab713c:/controller/oauthcontroller.php diff --git a/controller/oauthcontroller.php b/controller/oauthcontroller.php index cb20832..dfb02c5 100644 --- a/controller/oauthcontroller.php +++ b/controller/oauthcontroller.php @@ -12,7 +12,20 @@ * @link http://cweiske.de/grauphel.htm */ namespace OCA\Grauphel\Controller; + use \OCP\AppFramework\Controller; +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; +use \OCA\Grauphel\Lib\Response\ErrorResponse; +use \OCA\Grauphel\Lib\Response\FormResponse; +use \OCA\Grauphel\Lib\OAuthException; +use \OCA\Grauphel\Lib\UrlHelper; /** * OAuth handling @@ -25,38 +38,67 @@ use \OCP\AppFramework\Controller; * @version Release: @package_version@ * @link http://cweiske.de/grauphel.htm */ -class OAuthController extends Controller +class OauthController extends Controller { + protected $user; + + /** + * constructor of the controller + * + * @param string $appName Name of the app + * @param IRequest $request Instance of the request + */ + public function __construct($appName, \OCP\IRequest $request, $user) + { + parent::__construct($appName, $request); + $this->user = $user; + $this->deps = Dependencies::get(); + + //default http header: we assume something is broken + header('HTTP/1.0 500 Internal Server Error'); + } + /** * Handle out an access token after verifying the verification token * OAuth step 3 of 3 + * + * @NoAdminRequired + * @NoCSRFRequired + * @PublicPage */ - public function accessTokenAction() + public function accessToken() { $oauth = new OAuth(); $oauth->setDeps($this->deps); + $urlGen = $this->deps->urlGen; try { - $provider = new \OAuthProvider(); + $provider = OAuth::getProvider(); $oauth->registerHandler($provider) ->registerVerificationTokenHandler($provider); - $provider->checkOAuthRequest($this->deps->urlGen->oauthAccessToken()); + $provider->checkOAuthRequest( + $urlGen->getAbsoluteURL( + $urlGen->linkToRoute('grauphel.oauth.accessToken') + ) + ); $token = $this->deps->tokens->loadAndDelete('verify', $provider->token); - $newToken = new OAuth_Token('access'); + $newToken = new Token('access'); $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); - $this->deps->renderer->sendFormData( + return new FormResponse( array( 'oauth_token' => $newToken->tokenKey, 'oauth_token_secret' => $newToken->secret, ) ); - exit(0); + } catch (OAuthException $e) { + return new ErrorResponse($e->getMessage()); } catch (\OAuthException $e) { $oauth->error($e); } @@ -65,111 +107,173 @@ class OAuthController extends Controller /** * Log the user in and let him authorize that the app may access notes * OAuth step 2 of 3 + * + * Page is not public and thus requires owncloud login + * + * @NoAdminRequired + * @NoCSRFRequired */ - public function authorizeAction() + public function authorize() { - $oauth = new OAuth(); - $oauth->setDeps($this->deps); - - if (!isset($_REQUEST['oauth_token'])) { - $this->deps->renderer->errorOut('oauth_token missing'); + $token = $this->verifyRequestToken(); + if (!$token instanceof Token) { + return $token; } - if (!$oauth->validateToken($_REQUEST['oauth_token'])) { - $this->deps->renderer->errorOut('Invalid token string'); - } - - $reqToken = $_REQUEST['oauth_token']; - try { - $token = $this->deps->tokens->load('temp', $reqToken); - } catch (OAuth_Exception $e) { - $this->deps->renderer->errorOut($e->getMessage()); + $clientTitle = 'unknown'; + $clientAgent = ''; + if (isset($_GET['client'])) { + $clientAgent = $_GET['client']; + $cl = new Client(); + $clientTitle = $cl->getNiceName($clientAgent); } - $authState = $this->deps->frontend->doAuthorize( - $this->deps->urlGen->current() + $res = new TemplateResponse('grauphel', 'oauthAuthorize'); + $res->setParams( + array( + 'oauth_token' => $token->tokenKey, + 'clientTitle' => $clientTitle, + 'clientAgent' => $clientAgent, + 'formaction' => $this->deps->urlGen->linkToRoute( + 'grauphel.oauth.confirm' + ), + ) ); - if ($authState === null) { - //this should not happen; doAuthorize() must block - exit(1); - } + return $res; + } + + /** + * User confirms or declines the authorization request + * OAuth step 2.5 of 3 + * + * @NoAdminRequired + */ + public function confirm() + { + $token = $this->verifyRequestToken(); + $oauth = new OAuth(); + $oauth->setDeps($this->deps); try { - $token = $this->deps->tokens->loadAndDelete('temp', $reqToken); - } catch (OAuth_Exception $e) { - $this->deps->renderer->errorOut($e->getMessage()); + $token = $this->deps->tokens->loadAndDelete('temp', $token->tokenKey); + } catch (OAuthException $e) { + return new ErrorResponse($e->getMessage()); } + $authState = isset($_POST['auth']) && $_POST['auth'] == 'ok'; if ($authState === false) { //user declined //http://wiki.oauth.net/w/page/12238543/ProblemReporting - $callback = $this->deps->urlGen->addParams( - $token->callback, - array( - 'oauth_token' => $token->tokenKey, - 'oauth_problem' => 'permission_denied', + $res = new RedirectResponse( + UrlHelper::addParams( + $token->callback, + array( + 'oauth_token' => $token->tokenKey, + 'oauth_problem' => 'permission_denied', + ) ) ); - header('Location: ' . $callback, true, 302); - exit(0); + $res->setStatus(Http::STATUS_SEE_OTHER); + return $res; + } + + $clientAgent = ''; + if (isset($_POST['client'])) { + $clientAgent = $_POST['client']; } //the user is logged in and authorized - $provider = new \OAuthProvider(); + $provider = OAuth::getProvider(); - $newToken = new OAuth_Token('verify'); + $newToken = new Token('verify'); $newToken->tokenKey = $token->tokenKey; $newToken->secret = $token->secret; $newToken->verifier = 'v' . bin2hex($provider->generateToken(8)); - $newToken->user = $this->deps->frontend->getUser(); + $newToken->user = $this->user->getUID(); + $newToken->client = $clientAgent; $this->deps->tokens->store($newToken); //redirect //FIXME: if no callback is given, show the token to the user - $callback = $this->deps->urlGen->addParams( - $token->callback, - array( - 'oauth_token' => $newToken->tokenKey, - 'oauth_verifier' => $newToken->verifier + $res = new RedirectResponse( + UrlHelper::addParams( + $token->callback, + array( + 'oauth_token' => $newToken->tokenKey, + 'oauth_verifier' => $newToken->verifier + ) ) ); + $res->setStatus(Http::STATUS_SEE_OTHER); + return $res; + } + + protected function verifyRequestToken() + { + if (!isset($_REQUEST['oauth_token'])) { + return new ErrorResponse('oauth_token missing'); + } + + $oauth = new OAuth(); + $oauth->setDeps($this->deps); + if (!$oauth->validateToken($_REQUEST['oauth_token'])) { + return new ErrorResponse('Invalid token string'); + } + + $reqToken = $_REQUEST['oauth_token']; - header('Location: ' . $callback, true, 302); - exit(); + try { + $token = $this->deps->tokens->load('temp', $reqToken); + } catch (OAuthException $e) { + return new ErrorResponse($e->getMessage()); + } + + return $token; } /** * Create and return a request token. * OAuth step 1 of 3 + * + * @NoAdminRequired + * @NoCSRFRequired + * @PublicPage */ - public function requestTokenAction() + public function requestToken() { $oauth = new OAuth(); $oauth->setDeps($this->deps); + $urlGen = $this->deps->urlGen; try { - $provider = new \OAuthProvider(); + $provider = OAuth::getProvider(); $oauth->registerHandler($provider); $provider->isRequestTokenEndpoint(true); - $provider->checkOAuthRequest($this->deps->urlGen->oauthRequestToken()); + $provider->checkOAuthRequest( + $urlGen->getAbsoluteURL( + $urlGen->linkToRoute('grauphel.oauth.requestToken') + ) + ); //store token + callback URI for later - $token = new OAuth_Token('temp'); + $token = new Token('temp'); $token->tokenKey = 'r' . bin2hex($provider->generateToken(8)); $token->secret = 's' . bin2hex($provider->generateToken(8)); $token->callback = $provider->callback; $this->deps->tokens->store($token); - $this->deps->renderer->sendFormData( + return new FormResponse( array( 'oauth_token' => $token->tokenKey, 'oauth_token_secret' => $token->secret, - 'oauth_callback_confirmed' => 'TRUE' + 'oauth_callback_confirmed' => 'true' ) ); + } catch (OAuthException $e) { + return new ErrorResponse($e->getMessage()); } catch (\OAuthException $e) { $oauth->error($e); }