Download note as XML and JSON
[grauphel.git] / controller / oauthcontroller.php
index cb20832..dfb02c5 100644 (file)
  * @link      http://cweiske.de/grauphel.htm
  */
 namespace OCA\Grauphel\Controller;
  * @link      http://cweiske.de/grauphel.htm
  */
 namespace OCA\Grauphel\Controller;
+
 use \OCP\AppFramework\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
 
 /**
  * OAuth handling
@@ -25,38 +38,67 @@ use \OCP\AppFramework\Controller;
  * @version   Release: @package_version@
  * @link      http://cweiske.de/grauphel.htm
  */
  * @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
     /**
      * 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);
     {
         $oauth = new OAuth();
         $oauth->setDeps($this->deps);
+        $urlGen = $this->deps->urlGen;
 
         try {
 
         try {
-            $provider = new \OAuthProvider();
+            $provider = OAuth::getProvider();
             $oauth->registerHandler($provider)
                 ->registerVerificationTokenHandler($provider);
             $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);
 
 
             $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->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->tokens->store($newToken);
 
-            $this->deps->renderer->sendFormData(
+            return new FormResponse(
                 array(
                     'oauth_token'        => $newToken->tokenKey,
                     'oauth_token_secret' => $newToken->secret,
                 )
             );
                 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);
         }
         } 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
     /**
      * 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 {
 
         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
         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
         }
 
         //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->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
 
         $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
     }
 
     /**
      * 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);
     {
         $oauth = new OAuth();
         $oauth->setDeps($this->deps);
+        $urlGen = $this->deps->urlGen;
 
         try {
 
         try {
-            $provider = new \OAuthProvider();
+            $provider = OAuth::getProvider();
             $oauth->registerHandler($provider);
             $provider->isRequestTokenEndpoint(true);
             $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
 
             //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);
 
             $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,
                 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);
         }
         } catch (\OAuthException $e) {
             $oauth->error($e);
         }