From d2c59df3471a839a21c3cb7bfc74168013bcc15c Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Tue, 7 Dec 2021 11:38:47 +0100 Subject: [PATCH 1/2] Code cleanup - Whitespace fixes - Move FQN to `use` statements - Use PHP source functions instead of alias - Collpase multi-if statements - Inline function returns - Remove commented out code --- src/Controller/AuthorizeController.php | 2 +- src/Controller/CorsController.php | 2 +- src/Controller/OpenidController.php | 2 +- src/Controller/ResourceController.php | 2 +- src/Controller/ServerController.php | 195 +++++++++++++------------ src/Controller/TokenController.php | 21 ++- src/ServerConfig.php | 1 + web/index.php | 11 +- 8 files changed, 123 insertions(+), 113 deletions(-) diff --git a/src/Controller/AuthorizeController.php b/src/Controller/AuthorizeController.php index 5b173ba..bb0a427 100644 --- a/src/Controller/AuthorizeController.php +++ b/src/Controller/AuthorizeController.php @@ -68,4 +68,4 @@ final public function __invoke(ServerRequestInterface $request, array $args): Re $response = $this->tokenGenerator->addIdTokenToResponse($response, $clientId, $this->getProfilePage(), $_SESSION['nonce'], $this->config->getPrivateKey()); return $response; } -} \ No newline at end of file +} diff --git a/src/Controller/CorsController.php b/src/Controller/CorsController.php index 8518e60..bff7ed3 100644 --- a/src/Controller/CorsController.php +++ b/src/Controller/CorsController.php @@ -8,7 +8,7 @@ class CorsController extends ServerController { final public function __invoke(ServerRequestInterface $request, array $args): ResponseInterface - { + { return $this->getResponse()->withHeader("Access-Control-Allow-Headers", "*"); } } diff --git a/src/Controller/OpenidController.php b/src/Controller/OpenidController.php index 0ce1cad..ae34fa1 100644 --- a/src/Controller/OpenidController.php +++ b/src/Controller/OpenidController.php @@ -13,4 +13,4 @@ final public function __invoke(ServerRequestInterface $request, array $args): Re $server = new \Pdsinterop\Solid\Auth\Server($this->authServerFactory, $this->authServerConfig, $response); return $server->respondToOpenIdMetadataRequest(); } -} \ No newline at end of file +} diff --git a/src/Controller/ResourceController.php b/src/Controller/ResourceController.php index 8bc7f4c..1699029 100644 --- a/src/Controller/ResourceController.php +++ b/src/Controller/ResourceController.php @@ -62,7 +62,7 @@ final public function __invoke(Request $request, array $args) : Response return $this->WAC->addWACHeaders($request, $response, $webId); } - private function generateDefaultAcl() { + private function generateDefaultAcl() { $defaultProfile = <<< EOF # Root ACL resource for the user account @prefix acl: . diff --git a/src/Controller/ServerController.php b/src/Controller/ServerController.php index fb01850..afce921 100644 --- a/src/Controller/ServerController.php +++ b/src/Controller/ServerController.php @@ -17,9 +17,9 @@ abstract class ServerController extends AbstractController public function __construct() { $this->config = new \Pdsinterop\Solid\ServerConfig(__DIR__.'/../../config/'); - - $this->authServerConfig = $this->createAuthServerConfig(); - $this->authServerFactory = (new \Pdsinterop\Solid\Auth\Factory\AuthorizationServerFactory($this->authServerConfig))->create(); + + $this->authServerConfig = $this->createAuthServerConfig(); + $this->authServerFactory = (new \Pdsinterop\Solid\Auth\Factory\AuthorizationServerFactory($this->authServerConfig))->create(); $this->tokenGenerator = (new \Pdsinterop\Solid\Auth\TokenGenerator($this->authServerConfig)); $this->baseUrl = isset($_ENV['SERVER_ROOT']) ? $_ENV['SERVER_ROOT'] : "https://localhost"; } @@ -39,98 +39,107 @@ public function getOpenIdEndpoints() { ]; } - public function getKeys() { - $encryptionKey = $this->config->getEncryptionKey(); - $privateKey = $this->config->getPrivateKey(); - $key = openssl_pkey_get_private($privateKey); - $publicKey = openssl_pkey_get_details($key)['key']; - return [ - "encryptionKey" => $encryptionKey, - "privateKey" => $privateKey, - "publicKey" => $publicKey - ]; - } + public function getKeys() + { + $encryptionKey = $this->config->getEncryptionKey(); + $privateKey = $this->config->getPrivateKey(); + $key = openssl_pkey_get_private($privateKey); + $publicKey = openssl_pkey_get_details($key)['key']; - public function createAuthServerConfig() { - $clientId = $_GET['client_id']; // FIXME: No request object here to get the client Id from. - $client = $this->getClient($clientId); - $keys = $this->getKeys(); - try { - $config = (new \Pdsinterop\Solid\Auth\Factory\ConfigFactory( - $client, - $keys['encryptionKey'], - $keys['privateKey'], - $keys['publicKey'], - $this->getOpenIdEndpoints() - ))->create(); - } catch(\Throwable $e) { - // var_dump($e); - } - return $config; - } + return [ + "encryptionKey" => $encryptionKey, + "privateKey" => $privateKey, + "publicKey" => $publicKey, + ]; + } - public function getClient($clientId) { - $clientRegistration = $this->config->getClientRegistration($clientId); - - if ($clientId && sizeof($clientRegistration)) { - return new \Pdsinterop\Solid\Auth\Config\Client( - $clientId, - $clientRegistration['client_secret'], - $clientRegistration['redirect_uris'], - $clientRegistration['client_name'] - ); - } else { - return new \Pdsinterop\Solid\Auth\Config\Client('','',array(),''); - } - } + public function createAuthServerConfig() + { + $clientId = $_GET['client_id']; // FIXME: No request object here to get the client Id from. + $client = $this->getClient($clientId); + $keys = $this->getKeys(); + try { + $config = (new ConfigFactory( + $client, + $keys['encryptionKey'], + $keys['privateKey'], + $keys['publicKey'], + $this->getOpenIdEndpoints() + ))->create(); + } catch (Throwable $e) { + // var_dump($e); + } - public function createConfig($baseUrl) { - // if (isset($_GET['client_id'])) { - $clientId = $_GET['client_id']; - $client = $this->getClient($clientId, $baseUrl); - // } - try { - $config = (new \Pdsinterop\Solid\Auth\Factory\ConfigFactory( - $client, - $this->keys['encryptionKey'], - $this->keys['privateKey'], - $this->keys['publicKey'], - $this->openIdConfiguration - ))->create(); - } catch(\Throwable $e) { - var_dump($e); - } - return $config; - } - - public function checkApproval($clientId) { - $allowedClients = $this->config->getAllowedClients($this->userId); - if ($clientId == md5("tester")) { // FIXME: Double check that this is not a security issue; It is only here to help the test suite; - return \Pdsinterop\Solid\Auth\Enum\Authorization::APPROVED; - } - if (in_array($clientId, $allowedClients)) { - return \Pdsinterop\Solid\Auth\Enum\Authorization::APPROVED; - } else { - return \Pdsinterop\Solid\Auth\Enum\Authorization::DENIED; - } - } - - public function getProfilePage() { - return $this->baseUrl . "/profile/card#me"; // FIXME: would be better to base this on the available routes if possible. - } - - public function getResponseType() { + return $config; + } + + public function getClient($clientId) + { + $clientRegistration = $this->config->getClientRegistration($clientId); + + if ($clientId && count($clientRegistration)) { + $client = new Client( + $clientId, + $clientRegistration['client_secret'], + $clientRegistration['redirect_uris'], + $clientRegistration['client_name'] + ); + } else { + $client = new Client('', '', [], ''); + } + + return $client; + } + + public function createConfig() + { + // if (isset($_GET['client_id'])) { + $clientId = $_GET['client_id']; + $client = $this->getClient($clientId); + + // } + return (new ConfigFactory( + $client, + $this->keys['encryptionKey'], + $this->keys['privateKey'], + $this->keys['publicKey'], + $this->openIdConfiguration + ))->create(); + } + public function checkApproval($clientId) + { + $approval = Authorization::DENIED; + + $allowedClients = $this->config->getAllowedClients($this->userId); + + if ( + $clientId === md5("tester") // FIXME: Double check that this is not a security issue; It is only here to help the test suite; + || in_array($clientId, $allowedClients, true) + ) { + $approval = Authorization::APPROVED; + } + + return $approval; + } + public function getProfilePage() : string + { + return $this->baseUrl . "/profile/card#me"; // FIXME: would be better to base this on the available routes if possible. + } + + public function getResponseType() : string + { $responseTypes = explode(" ", $_GET['response_type'] ?? ''); - foreach ($responseTypes as $responseType) { - switch ($responseType) { - case "token": - return "token"; - break; - case "code": - return "code"; - break; - } - } - return "token"; // default to token response type; - } + foreach ($responseTypes as $responseType) { + switch ($responseType) { + case "token": + return "token"; + break; + case "code": + return "code"; + break; + } + } + + return "token"; // default to token response type; + } } diff --git a/src/Controller/TokenController.php b/src/Controller/TokenController.php index 5a4607e..61b783d 100644 --- a/src/Controller/TokenController.php +++ b/src/Controller/TokenController.php @@ -11,7 +11,7 @@ class TokenController extends ServerController { final public function __invoke(ServerRequestInterface $request, array $args): ResponseInterface - { + { $code = $request->getParsedBody()['code']; $clientId = $request->getParsedBody()['client_id']; $DPop = new DPop(); @@ -21,16 +21,25 @@ final public function __invoke(ServerRequestInterface $request, array $args): Re } catch(\Exception $e) { return $this->getResponse()->withStatus(409, "Invalid token"); } - - $response = new \Laminas\Diactoros\Response(); - $server = new \Pdsinterop\Solid\Auth\Server($this->authServerFactory, $this->authServerConfig, $response); + + $server = new \Pdsinterop\Solid\Auth\Server( + $this->authServerFactory, + $this->authServerConfig, + new \Laminas\Diactoros\Response() + ); + $response = $server->respondToAccessTokenRequest($request); // FIXME: not sure if decoding this here is the way to go. // FIXME: because this is a public page, the nonce from the session is not available here. $codeInfo = $this->tokenGenerator->getCodeInfo($code); - $response = $this->tokenGenerator->addIdTokenToResponse($response, $clientId, $codeInfo['user_id'], $_SESSION['nonce'], $this->config->getPrivateKey(), $dpopKey); - return $response; + return $this->tokenGenerator->addIdTokenToResponse($response, + $clientId, + $codeInfo['user_id'], + $_SESSION['nonce'], + $this->config->getPrivateKey(), + $dpopKey + ); } } diff --git a/src/ServerConfig.php b/src/ServerConfig.php index 3b249d3..d58794e 100644 --- a/src/ServerConfig.php +++ b/src/ServerConfig.php @@ -116,6 +116,7 @@ public function addAllowedClient($userId, $clientId) { $this->userConfig['allowedClients'] = array_unique($this->userConfig['allowedClients']); $this->saveUserConfig(); } + public function removeAllowedClient($userId, $clientId) { $this->userConfig['allowedClients'] = array_diff($this->userConfig['allowedClients'], array($clientId)); $this->saveUserConfig(); diff --git a/web/index.php b/web/index.php index 0792954..40feee9 100644 --- a/web/index.php +++ b/web/index.php @@ -55,14 +55,6 @@ $container->add(ServerRequestInterface::class, Request::class); $container->add(ResponseInterface::class, Response::class); -/* -$adapter = new \League\Flysystem\Adapter\Local(__DIR__ . '/../tests/fixtures'); -$filesystem = new \League\Flysystem\Filesystem($adapter); -$graph = new \EasyRdf_Graph(); -$plugin = new \Pdsinterop\Rdf\Flysystem\Plugin\ReadRdf($graph); -$filesystem->addPlugin($plugin); -*/ - $container->share(FilesystemInterface::class, function () use ($request) { // @FIXME: Filesystem root and the $adapter should be configurable. // Implement this with `$filesystem = \MJRider\FlysystemFactory\create(getenv('STORAGE_ENDPOINT'));` @@ -129,7 +121,7 @@ OpenidController::class, ProfileController::class, RegisterController::class, - StorageController::class, + StorageController::class, TokenController::class, ]; @@ -200,7 +192,6 @@ array_walk($methods, static function ($method) use (&$group) { $group->map($method, '/', AddSlashToPathController::class); -// $group->map($method, '//', StorageController::class); $group->map($method, '{path:.*}', ResourceController::class); }); }); From 396d93f7a3e92e7da3e10f9153ba1cebbcb93078 Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Wed, 8 Dec 2021 16:41:45 +0100 Subject: [PATCH 2/2] Cleanup Dockerfile - Add divider comment between generic and specific sections - Grab composer from official docker image rather than web - Use a more robust shell - Make apt-install footprint smaller - Use OpenSSL with paths rather than use WORKDIR - Make project path setable through env var for build purposes - Only install non-dev dependencies with composer. The develop shoudl consciencely install deve dependencies because of develop PHP version(s) used. - Use COPY rather than ADD as per best practices --- Dockerfile | 68 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8334deb..231b1ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,51 @@ FROM php:7.3-apache -RUN apt-get update && \ - apt-get install -y \ + +# ============================================================================== +# Set up the machine +# ------------------------------------------------------------------------------ +COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update && \ + apt-get install -y --no-install-recommends \ git \ libzip-dev \ - zlib1g-dev -WORKDIR /tls -RUN openssl req -new -x509 -days 365 -nodes \ - -out server.cert \ - -keyout server.key \ - -subj "/C=RO/ST=Bucharest/L=Bucharest/O=IT/CN=www.example.ro" -RUN docker-php-ext-install mysqli pdo pdo_mysql zip mbstring bcmath -RUN a2enmod rewrite -RUN a2enmod ssl -RUN a2enmod headers -WORKDIR /install -RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" -RUN php composer-setup.php -RUN php -r "unlink('composer-setup.php');" -ADD . /app -WORKDIR /app -RUN php /install/composer.phar require lcobucci/jwt:3.3.3 -RUN php /install/composer.phar update -RUN php /install/composer.phar install + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir /tls && openssl req -new -x509 -days 365 -nodes \ + -out /tls/server.cert \ + -keyout /tls/server.key \ + -subj "/C=NL/ST=Overijssel/L=Enschede/O=PDS Interop/OU=IT/CN=pdsinterop.org" + +RUN docker-php-ext-install \ + bcmath \ + mbstring \ + mysqli \ + pdo \ + pdo_mysql \ + zip + +RUN a2enmod headers rewrite ssl + COPY site.conf /etc/apache2/sites-enabled/site.conf -RUN chown -R www-data:www-data /app + +WORKDIR /app + EXPOSE 443 +# ============================================================================== + + +# ============================================================================== +# Add the source code +# ------------------------------------------------------------------------------ +ARG PROJECT_PATH +RUN : "${PROJECT_PATH:=$PWD}" + +COPY "${PROJECT_PATH}" /app/ + +RUN composer install --no-dev --prefer-dist +RUN chown -R www-data:www-data /app +# ==============================================================================