From 602ceda9eacff5027f0566e793cb1b52d5a2ee5c Mon Sep 17 00:00:00 2001 From: kiy0taka Date: Thu, 31 Oct 2019 11:25:09 +0900 Subject: [PATCH 01/15] =?UTF-8?q?GraphQL=E3=81=AE=E6=9C=80=E5=88=9D?= =?UTF-8?q?=E3=81=AE=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 3 +- composer.lock | 58 ++++++++++- src/Eccube/Controller/ApiController.php | 129 ++++++++++++++++++++++++ src/Eccube/GraphQL/Types.php | 109 ++++++++++++++++++++ symfony.lock | 3 + 5 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 src/Eccube/Controller/ApiController.php create mode 100644 src/Eccube/GraphQL/Types.php diff --git a/composer.json b/composer.json index c6ae58806da..bcc1bdb982b 100644 --- a/composer.json +++ b/composer.json @@ -103,7 +103,8 @@ "tecnickcom/tcpdf": "^6.2", "twig/extensions": "^1.5", "twig/twig": "^2.4", - "vlucas/phpdotenv": "v2.4.0" + "vlucas/phpdotenv": "v2.4.0", + "webonyx/graphql-php": "^0.13.8" }, "require-dev": { "bheller/images-generator": "^1.0", diff --git a/composer.lock b/composer.lock index b179d5cf69a..d948ed0ca29 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "54f828784a479f284e3802f7e7ddfab1", + "content-hash": "82a4175bc888de0349643339fae72f48", "packages": [ { "name": "composer/ca-bundle", @@ -7420,6 +7420,58 @@ ], "time": "2016-09-01T10:05:43+00:00" }, + { + "name": "webonyx/graphql-php", + "version": "v0.13.8", + "source": { + "type": "git", + "url": "https://github.com/webonyx/graphql-php.git", + "reference": "6829ae58f4c59121df1f86915fb9917a2ec595e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/6829ae58f4c59121df1f86915fb9917a2ec595e8", + "reference": "6829ae58f4c59121df1f86915fb9917a2ec595e8", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^7.1||^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpbench/phpbench": "^0.14.0", + "phpstan/phpstan": "^0.11.4", + "phpstan/phpstan-phpunit": "^0.11.0", + "phpstan/phpstan-strict-rules": "^0.11.0", + "phpunit/phpcov": "^5.0", + "phpunit/phpunit": "^7.2", + "psr/http-message": "^1.0", + "react/promise": "2.*" + }, + "suggest": { + "psr/http-message": "To use standard GraphQL server", + "react/promise": "To leverage async resolving on React PHP platform" + }, + "type": "library", + "autoload": { + "psr-4": { + "GraphQL\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP port of GraphQL reference implementation", + "homepage": "https://github.com/webonyx/graphql-php", + "keywords": [ + "api", + "graphql" + ], + "time": "2019-08-25T10:32:47+00:00" + }, { "name": "zendframework/zend-code", "version": "3.3.1", @@ -7471,6 +7523,7 @@ "code", "zf2" ], + "abandoned": "laminas/laminas-code", "time": "2018-08-13T20:36:59+00:00" }, { @@ -7525,6 +7578,7 @@ "events", "zf2" ], + "abandoned": "laminas/laminas-eventmanager", "time": "2018-04-25T15:33:34+00:00" } ], @@ -8006,7 +8060,7 @@ "time": "2018-07-12T10:23:15+00:00" }, { - "name": "mikey179/vfsstream", + "name": "mikey179/vfsStream", "version": "v1.6.6", "source": { "type": "git", diff --git a/src/Eccube/Controller/ApiController.php b/src/Eccube/Controller/ApiController.php new file mode 100644 index 00000000000..2b531a23c0e --- /dev/null +++ b/src/Eccube/Controller/ApiController.php @@ -0,0 +1,129 @@ +types = $types; + $this->productRepository = $productRepository; + $this->orderRepository = $orderRepository; + $this->customerRepository = $customerRepository; + } + + /** + * @Route("/api", name="api") + */ + public function index(Request $request) + { + $body = json_decode($request->getContent(), true); + $schema = $this->getSchema(); + $result = GraphQL::executeQuery($schema, $body['query']); + + return $this->json($result); + } + + private function getSchema() + { + return new Schema([ + 'query' => new ObjectType([ + 'name' => 'Query', + 'fields' => [ + 'products' => $this->createQuery(Product::class, SearchProductType::class, function ($searchData) { + return $this->productRepository->getQueryBuilderBySearchDataForAdmin($searchData)->getQuery()->getResult(); + }), + 'orders' => $this->createQuery(Order::class, SearchOrderType::class, function ($searchData) { + return $this->orderRepository->getQueryBuilderBySearchDataForAdmin($searchData)->getQuery()->getResult(); + }), + 'customers' => $this->createQuery(Customer::class, SearchCustomerType::class, function ($searchData) { + return $this->customerRepository->getQueryBuilderBySearchData($searchData)->getQuery()->getResult(); + }), + ], + 'typeLoader' => function ($name) { + return $this->types->get($name); + }, + ]), + ]); + } + + private function createQuery($entityClass, $searchFormType, $resolver) + { + $builder = $this->formFactory->createBuilder($searchFormType, null, ['csrf_protection' => false]); + $args = array_reduce($builder->getForm()->all(), function ($acc, $form) { + /* @var FormInterface $form */ + $formConfig = $form->getConfig(); + $type = Type::string(); + if ($formConfig->getOption('multiple')) { + $type = Type::listOf($type); + } + if ($formConfig->getOption('required') && !$formConfig->getOption('multiple')) { + $type = Type::nonNull($type); + } + $acc[$form->getName()] = [ + 'type' => $type, + 'description' => $formConfig->getOption('label') ? trans($formConfig->getOption('label')) : null, + ]; + + return $acc; + }, []); + + return [ + 'type' => Type::listOf($this->types->get($entityClass)), + 'args' => $args, + 'resolve' => function ($root, $args) use ($builder, $resolver) { + $form = $builder->getForm(); + FormUtil::submitAndGetData($form, $args); + + return $resolver($form->getData()); + }, + ]; + } +} diff --git a/src/Eccube/GraphQL/Types.php b/src/Eccube/GraphQL/Types.php new file mode 100644 index 00000000000..352373f440e --- /dev/null +++ b/src/Eccube/GraphQL/Types.php @@ -0,0 +1,109 @@ +entityManager = $entityManager; + } + + /** + * Entityに対応するObjectTypeを返す. + * + * @param $className string Entityクラス名 + * @return ObjectType + */ + public function get($className) + { + if (!isset($this->types[$className])) { + $this->types[$className] = $this->createObjectType($className); + } + + return $this->types[$className]; + } + + private function createObjectType($className) + { + return new ObjectType([ + 'name' => (new \ReflectionClass($className))->getShortName(), + 'fields' => function () use ($className) { + $classMetadata = $this->entityManager->getClassMetadata($className); + $fields = array_reduce($classMetadata->fieldMappings, function ($acc, $mapping) { + $type = $this->convertFieldMappingToType($mapping); + + if ($type) { + $acc[$mapping['fieldName']] = $type; + } + + return $acc; + }, []); + + $fields = array_reduce($classMetadata->associationMappings, function ($acc, $mapping) { + $acc[$mapping['fieldName']] = [ + 'type' => $this->convertAssociationMappingToType($mapping), + ]; + return $acc; + }, $fields); + + return $fields; + }, + ]); + } + + private function convertFieldMappingToType($fieldMapping) + { + $type = $fieldMapping['id'] ? Type::id() : [ + 'string' => Type::string(), + 'text' => Type::string(), + 'integer' => Type::int(), + 'decimal' => Type::float(), + ][$fieldMapping['type']]; + + if ($type) { + return $fieldMapping['nullable'] ? $type : Type::nonNull($type); + } + + return null; + } + + private function convertAssociationMappingToType($mapping) + { + return $this->isToManyAssociation($mapping) ? Type::listOf($this->get($mapping['targetEntity'])) : $this->get($mapping['targetEntity']); + } + + private function isToManyAssociation($mapping) + { + return $mapping['type'] & ClassMetadata::TO_MANY; + } +} diff --git a/symfony.lock b/symfony.lock index 46ad0b6ca0c..0ff7907cc81 100644 --- a/symfony.lock +++ b/symfony.lock @@ -629,6 +629,9 @@ "webmozart/assert": { "version": "1.3.0" }, + "webonyx/graphql-php": { + "version": "v0.13.8" + }, "zendframework/zend-code": { "version": "3.3.0" }, From b612ef878985f6f60eecd3034129c2f9fad50022 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 30 Jan 2020 15:42:58 +0900 Subject: [PATCH 02/15] =?UTF-8?q?Postgres=E3=81=AE=E3=83=87=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E5=9E=8B=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Eccube/GraphQL/Types.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Eccube/GraphQL/Types.php b/src/Eccube/GraphQL/Types.php index 352373f440e..5839603e6e4 100644 --- a/src/Eccube/GraphQL/Types.php +++ b/src/Eccube/GraphQL/Types.php @@ -83,11 +83,14 @@ private function createObjectType($className) private function convertFieldMappingToType($fieldMapping) { - $type = $fieldMapping['id'] ? Type::id() : [ + $type = isset($fieldMapping['id']) ? Type::id() : [ 'string' => Type::string(), 'text' => Type::string(), 'integer' => Type::int(), 'decimal' => Type::float(), + 'datetimetz' => Type::int(), + 'smallint' => Type::int(), + 'boolean' => Type::boolean(), ][$fieldMapping['type']]; if ($type) { From df5e86d18bc883ae9d19b97db1f09243921fa7ab Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 6 Feb 2020 18:03:29 +0900 Subject: [PATCH 03/15] =?UTF-8?q?=E3=83=97=E3=83=A9=E3=82=B0=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=81=AE=E6=9C=89=E5=8A=B9=E7=84=A1=E5=8A=B9=E5=88=A4?= =?UTF-8?q?=E5=AE=9A=E6=99=82=E3=81=ABDBAL=E3=81=AE=E5=AE=9A=E7=BE=A9?= =?UTF-8?q?=E3=82=92=E4=BD=9C=E6=88=90=E3=81=97=E3=81=AA=E3=81=84=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3=20refs=20#4461?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Eccube/DependencyInjection/EccubeExtension.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Eccube/DependencyInjection/EccubeExtension.php b/src/Eccube/DependencyInjection/EccubeExtension.php index 8bfb1027fa0..5772592a093 100644 --- a/src/Eccube/DependencyInjection/EccubeExtension.php +++ b/src/Eccube/DependencyInjection/EccubeExtension.php @@ -196,15 +196,9 @@ protected function isConnected(Connection $conn) return false; } - $sm = $conn->getSchemaManager(); - $tables = array_filter( - $sm->listTables(), - function ($table) { - return $table->getName() === 'dtb_plugin'; - } - ); + $tableNames = $conn->getSchemaManager()->listTableNames(); - return empty($tables) ? false : true; + return in_array('dtb_plugin', $tableNames); } /** From a8f462ab894ca3ba42956dea28a6910886d1fdb1 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 13 Feb 2020 13:35:27 +0900 Subject: [PATCH 04/15] =?UTF-8?q?trikoder/oauth2-bundle=20=E3=81=AE?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=82=B9=E3=83=88=E3=83=BC=E3=83=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.dist | 6 + README.md | 9 + app/config/eccube/bundles.php | 12 +- app/config/eccube/packages/nyholm_psr7.yaml | 21 + .../eccube/packages/trikoder_oauth2.yaml | 13 + app/config/eccube/routes/trikoder_oauth2.yaml | 2 + composer.json | 6 +- composer.lock | 558 +++++++++++++++++- phpunit.xml.dist | 6 + symfony.lock | 46 ++ 10 files changed, 662 insertions(+), 17 deletions(-) create mode 100644 app/config/eccube/packages/nyholm_psr7.yaml create mode 100644 app/config/eccube/packages/trikoder_oauth2.yaml create mode 100644 app/config/eccube/routes/trikoder_oauth2.yaml diff --git a/.env.dist b/.env.dist index 6adb894b3b8..0b125add72e 100644 --- a/.env.dist +++ b/.env.dist @@ -48,3 +48,9 @@ MAILER_URL=null://localhost #ECCUBE_GC_MAXLIFETIME=1440 ###< APPLICATION CONFIG ### + +###> trikoder/oauth2-bundle ### +# Fallback OAuth2 encryption key +# Please override this with a secure value: https://oauth2.thephpleague.com/installation/#string-password +OAUTH2_ENCRYPTION_KEY=c6f06eb702cd2e49dd4912a904dae6ea +###< trikoder/oauth2-bundle ### diff --git a/README.md b/README.md index 1f73abc71ae..3a4cd79d098 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,15 @@ npm ci # 初回およびpackage-lock.jsonに変更があったとき npm run build # Sass のビルド ``` +### OAuth2の設定 + +```shell +mkdir var/oauth +cd var/oauth +openssl genrsa -out private.key 2048 +openssl rsa -in private.key -pubout -out public.key +``` + ### 動作確認環境 * Apache/2.4.x (mod_rewrite / mod_ssl 必須) diff --git a/app/config/eccube/bundles.php b/app/config/eccube/bundles.php index 6a3ba63f6f8..4814f04c6ef 100644 --- a/app/config/eccube/bundles.php +++ b/app/config/eccube/bundles.php @@ -1,16 +1,5 @@ ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], @@ -29,4 +18,5 @@ Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], SunCat\MobileDetectBundle\MobileDetectBundle::class => ['all' => true], Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], + Trikoder\Bundle\OAuth2Bundle\TrikoderOAuth2Bundle::class => ['all' => true], ]; diff --git a/app/config/eccube/packages/nyholm_psr7.yaml b/app/config/eccube/packages/nyholm_psr7.yaml new file mode 100644 index 00000000000..f1357233b34 --- /dev/null +++ b/app/config/eccube/packages/nyholm_psr7.yaml @@ -0,0 +1,21 @@ +services: + # Register nyholm/psr7 services for autowiring with PSR-17 (HTTP factories) + Psr\Http\Message\RequestFactoryInterface: '@nyholm.psr7.psr17_factory' + Psr\Http\Message\ResponseFactoryInterface: '@nyholm.psr7.psr17_factory' + Psr\Http\Message\ServerRequestFactoryInterface: '@nyholm.psr7.psr17_factory' + Psr\Http\Message\StreamFactoryInterface: '@nyholm.psr7.psr17_factory' + Psr\Http\Message\UploadedFileFactoryInterface: '@nyholm.psr7.psr17_factory' + Psr\Http\Message\UriFactoryInterface: '@nyholm.psr7.psr17_factory' + + # Register nyholm/psr7 services for autowiring with HTTPlug factories + Http\Message\MessageFactory: '@nyholm.psr7.httplug_factory' + Http\Message\RequestFactory: '@nyholm.psr7.httplug_factory' + Http\Message\ResponseFactory: '@nyholm.psr7.httplug_factory' + Http\Message\StreamFactory: '@nyholm.psr7.httplug_factory' + Http\Message\UriFactory: '@nyholm.psr7.httplug_factory' + + nyholm.psr7.psr17_factory: + class: Nyholm\Psr7\Factory\Psr17Factory + + nyholm.psr7.httplug_factory: + class: Nyholm\Psr7\Factory\HttplugFactory diff --git a/app/config/eccube/packages/trikoder_oauth2.yaml b/app/config/eccube/packages/trikoder_oauth2.yaml new file mode 100644 index 00000000000..a1085f077f3 --- /dev/null +++ b/app/config/eccube/packages/trikoder_oauth2.yaml @@ -0,0 +1,13 @@ +trikoder_oauth2: + + authorization_server: + private_key: '%kernel.project_dir%/var/oauth/private.key' + private_key_passphrase: null + + encryption_key: '%env(string:OAUTH2_ENCRYPTION_KEY)%' + + resource_server: + public_key: '%kernel.project_dir%/var/oauth/public.key' + + persistence: + doctrine: null diff --git a/app/config/eccube/routes/trikoder_oauth2.yaml b/app/config/eccube/routes/trikoder_oauth2.yaml new file mode 100644 index 00000000000..f51d0aa629e --- /dev/null +++ b/app/config/eccube/routes/trikoder_oauth2.yaml @@ -0,0 +1,2 @@ +oauth2: + resource: '@TrikoderOAuth2Bundle/Resources/config/routes.xml' diff --git a/composer.json b/composer.json index bcc1bdb982b..302ce254cff 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ }, "minimum-stability": "stable", "require": { - "php": "^7.1.3", + "php": "^7.2.0", "ext-intl": "*", "ext-mbstring": "*", "composer/ca-bundle": "^1.1", @@ -40,6 +40,7 @@ "mobiledetect/mobiledetectlib": "^2.8", "monolog/monolog": "^1.23", "nesbot/carbon": "^1.22", + "nyholm/psr7": "^1.2", "pimple/pimple": "^1.1", "psr/cache": "^1.0", "psr/container": "^1.0", @@ -101,6 +102,7 @@ "symfony/workflow": "^3.4", "symfony/yaml": "^3.4", "tecnickcom/tcpdf": "^6.2", + "trikoder/oauth2-bundle": "^2.1", "twig/extensions": "^1.5", "twig/twig": "^2.4", "vlucas/phpdotenv": "v2.4.0", @@ -182,7 +184,7 @@ }, "config": { "platform": { - "php": "7.1.3" + "php": "7.2.0" }, "preferred-install": { "*": "dist" diff --git a/composer.lock b/composer.lock index d948ed0ca29..182bac567de 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "82a4175bc888de0349643339fae72f48", + "content-hash": "487f6b261fb9c50899b8e7bb34f7eb95", "packages": [ { "name": "composer/ca-bundle", @@ -308,6 +308,69 @@ ], "time": "2019-01-28T20:25:53+00:00" }, + { + "name": "defuse/php-encryption", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/defuse/php-encryption.git", + "reference": "0f407c43b953d571421e0020ba92082ed5fb7620" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/defuse/php-encryption/zipball/0f407c43b953d571421e0020ba92082ed5fb7620", + "reference": "0f407c43b953d571421e0020ba92082ed5fb7620", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "paragonie/random_compat": ">= 2", + "php": ">=5.4.0" + }, + "require-dev": { + "nikic/php-parser": "^2.0|^3.0|^4.0", + "phpunit/phpunit": "^4|^5" + }, + "bin": [ + "bin/generate-defuse-key" + ], + "type": "library", + "autoload": { + "psr-4": { + "Defuse\\Crypto\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Hornby", + "email": "taylor@defuse.ca", + "homepage": "https://defuse.ca/" + }, + { + "name": "Scott Arciszewski", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "Secure PHP Encryption Library", + "keywords": [ + "aes", + "authenticated encryption", + "cipher", + "crypto", + "cryptography", + "encrypt", + "encryption", + "openssl", + "security", + "symmetric key cryptography" + ], + "time": "2018-07-24T23:27:56+00:00" + }, { "name": "doctrine/annotations", "version": "v1.6.1", @@ -2263,6 +2326,188 @@ ], "time": "2018-05-16T12:15:58+00:00" }, + { + "name": "lcobucci/jwt", + "version": "3.3.1", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a11ec5f4b4d75d1fcd04e133dede4c317aac9e18", + "reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-openssl": "*", + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "mikey179/vfsstream": "~1.5", + "phpmd/phpmd": "~2.2", + "phpunit/php-invoker": "~1.1", + "phpunit/phpunit": "^5.7 || ^7.3", + "squizlabs/php_codesniffer": "~2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Otávio Cobucci Oblonczyk", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "time": "2019-05-24T18:30:49+00:00" + }, + { + "name": "league/event", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/event.git", + "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/event/zipball/d2cc124cf9a3fab2bb4ff963307f60361ce4d119", + "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Event\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Event package", + "keywords": [ + "emitter", + "event", + "listener" + ], + "time": "2018-11-26T11:52:41+00:00" + }, + { + "name": "league/oauth2-server", + "version": "7.4.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-server.git", + "reference": "2eb1cf79e59d807d89c256e7ac5e2bf8bdbd4acf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/2eb1cf79e59d807d89c256e7ac5e2bf8bdbd4acf", + "reference": "2eb1cf79e59d807d89c256e7ac5e2bf8bdbd4acf", + "shasum": "" + }, + "require": { + "defuse/php-encryption": "^2.1", + "ext-openssl": "*", + "lcobucci/jwt": "^3.2.2", + "league/event": "^2.1", + "php": ">=7.0.0", + "psr/http-message": "^1.0.1" + }, + "replace": { + "league/oauth2server": "*", + "lncd/oauth2": "*" + }, + "require-dev": { + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpstan/phpstan-strict-rules": "^0.9.0", + "phpunit/phpunit": "^6.3 || ^7.0", + "roave/security-advisories": "dev-master", + "zendframework/zend-diactoros": "^1.3.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\OAuth2\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Bilbie", + "email": "hello@alexbilbie.com", + "homepage": "http://www.alexbilbie.com", + "role": "Developer" + }, + { + "name": "Andy Millington", + "email": "andrew@noexceptions.io", + "homepage": "https://www.noexceptions.io", + "role": "Developer" + } + ], + "description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.", + "homepage": "https://oauth2.thephpleague.com/", + "keywords": [ + "Authentication", + "api", + "auth", + "authorisation", + "authorization", + "oauth", + "oauth 2", + "oauth 2.0", + "oauth2", + "protect", + "resource", + "secure", + "server" + ], + "time": "2019-05-05T09:22:01+00:00" + }, { "name": "mobiledetect/mobiledetectlib", "version": "2.8.33", @@ -2502,6 +2747,68 @@ ], "time": "2019-02-16T20:54:15+00:00" }, + { + "name": "nyholm/psr7", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "55ff6b76573f5b242554c9775792bd59fb52e11c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/55ff6b76573f5b242554c9775792bd59fb52e11c", + "reference": "55ff6b76573f5b242554c9775792bd59fb52e11c", + "shasum": "" + }, + "require": { + "php": "^7.1", + "php-http/message-factory": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "dev-master", + "php-http/psr7-integration-tests": "dev-master", + "phpunit/phpunit": "^7.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "http://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "time": "2019-09-05T13:24:16+00:00" + }, { "name": "ocramius/package-versions", "version": "1.4.0", @@ -2717,6 +3024,56 @@ ], "time": "2018-02-15T16:58:55+00:00" }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "time": "2015-12-19T14:08:53+00:00" + }, { "name": "pimple/pimple", "version": "v1.1.1", @@ -2858,6 +3215,58 @@ ], "time": "2017-02-14T16:28:37+00:00" }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2019-04-30T12:38:16+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -3261,6 +3670,7 @@ } ], "description": "This bundle generates code for you", + "abandoned": true, "time": "2017-12-07T15:36:41+00:00" }, { @@ -6056,6 +6466,71 @@ "homepage": "https://symfony.com", "time": "2019-04-16T11:13:42+00:00" }, + { + "name": "symfony/psr-http-message-bridge", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "9ab9d71f97d5c7d35a121a7fb69f74fee95cd0ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/9ab9d71f97d5c7d35a121a7fb69f74fee95cd0ad", + "reference": "9ab9d71f97d5c7d35a121a7fb69f74fee95cd0ad", + "shasum": "" + }, + "require": { + "php": "^7.1", + "psr/http-message": "^1.0", + "symfony/http-foundation": "^3.4 || ^4.0" + }, + "require-dev": { + "nyholm/psr7": "^1.1", + "symfony/phpunit-bridge": "^3.4.20 || ^4.0", + "zendframework/zend-diactoros": "^1.4.1 || ^2.0" + }, + "suggest": { + "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\PsrHttpMessage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "PSR HTTP message bridge", + "homepage": "http://symfony.com", + "keywords": [ + "http", + "http-message", + "psr-17", + "psr-7" + ], + "time": "2019-03-11T18:22:33+00:00" + }, { "name": "symfony/routing", "version": "v3.4.26", @@ -7248,6 +7723,80 @@ ], "time": "2018-10-16T17:24:05+00:00" }, + { + "name": "trikoder/oauth2-bundle", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/trikoder/oauth2-bundle.git", + "reference": "fbaa1f68b9272ebeb129915e6fb79f7a3e76bae8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/trikoder/oauth2-bundle/zipball/fbaa1f68b9272ebeb129915e6fb79f7a3e76bae8", + "reference": "fbaa1f68b9272ebeb129915e6fb79f7a3e76bae8", + "shasum": "" + }, + "require": { + "doctrine/doctrine-bundle": "^1.8|^2.0", + "doctrine/orm": "^2.6", + "league/oauth2-server": "^7.2", + "php": ">=7.2", + "psr/http-factory": "^1.0", + "sensio/framework-extra-bundle": "^5.3", + "symfony/framework-bundle": "^3.4|^4.2", + "symfony/psr-http-message-bridge": "^1.2", + "symfony/security-bundle": "^3.4|^4.2" + }, + "require-dev": { + "ext-timecop": "*", + "ext-xdebug": "*", + "friendsofphp/php-cs-fixer": "2.16.0", + "nyholm/psr7": "^1.1", + "phpunit/phpunit": "^8.4", + "symfony/browser-kit": "^3.4|^4.2", + "symfony/phpunit-bridge": "^3.4|^4.4", + "zendframework/zend-diactoros": "^2.1" + }, + "suggest": { + "defuse/php-encryption": "For better performance when doing encryption", + "nelmio/cors-bundle": "For handling CORS requests", + "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, + "symfony": { + "require": "4.4.*" + } + }, + "autoload": { + "psr-4": { + "Trikoder\\Bundle\\OAuth2Bundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Petar Obradović", + "email": "petar.obradovic@trikoder.net" + } + ], + "description": "Symfony bundle which provides OAuth 2.0 authorization/resource server capabilities.", + "homepage": "http://www.trikoder.net/", + "keywords": [ + "oauth2" + ], + "time": "2019-12-09T09:34:35+00:00" + }, { "name": "twig/extensions", "version": "v1.5.4", @@ -8007,6 +8556,7 @@ "selenium", "webdriver" ], + "abandoned": "php-webdriver/webdriver", "time": "2018-05-16T17:37:13+00:00" }, { @@ -8060,7 +8610,7 @@ "time": "2018-07-12T10:23:15+00:00" }, { - "name": "mikey179/vfsStream", + "name": "mikey179/vfsstream", "version": "v1.6.6", "source": { "type": "git", @@ -9725,12 +10275,12 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.1.3", + "php": "^7.2.0", "ext-intl": "*", "ext-mbstring": "*" }, "platform-dev": [], "platform-overrides": { - "php": "7.1.3" + "php": "7.2.0" } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c710c36748f..47d1a1f89bb 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -15,6 +15,12 @@ + + + + + + diff --git a/symfony.lock b/symfony.lock index 0ff7907cc81..30b93ce9c8c 100644 --- a/symfony.lock +++ b/symfony.lock @@ -41,6 +41,9 @@ "ref": "56eaa387b5e48ebcc7c95a893b47dfa1ad51449c" } }, + "defuse/php-encryption": { + "version": "v2.2.1" + }, "doctrine/annotations": { "version": "1.0", "recipe": { @@ -164,6 +167,15 @@ "knplabs/knp-paginator-bundle": { "version": "v2.7.1" }, + "lcobucci/jwt": { + "version": "3.3.1" + }, + "league/event": { + "version": "2.2.0" + }, + "league/oauth2-server": { + "version": "7.4.0" + }, "mikey179/vfsstream": { "version": "v1.6.5" }, @@ -182,6 +194,18 @@ "nikic/php-parser": { "version": "v4.0.3" }, + "nyholm/psr7": { + "version": "1.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.0", + "ref": "7c0a9352a57376f04f5444e74565102c3a23d0c7" + }, + "files": [ + "app/config/eccube/packages/nyholm_psr7.yaml" + ] + }, "ocramius/package-versions": { "version": "1.2.0" }, @@ -203,6 +227,9 @@ "php-cs-fixer/diff": { "version": "v1.2.0" }, + "php-http/message-factory": { + "version": "v1.0.2" + }, "phpdocumentor/reflection-common": { "version": "1.0.1" }, @@ -251,6 +278,9 @@ "psr/container": { "version": "1.0.0" }, + "psr/http-factory": { + "version": "1.0.1" + }, "psr/http-message": { "version": "1.0.1" }, @@ -506,6 +536,9 @@ "symfony/proxy-manager-bridge": { "version": "v3.4.4" }, + "symfony/psr-http-message-bridge": { + "version": "v1.2.0" + }, "symfony/routing": { "version": "3.3", "recipe": { @@ -611,6 +644,19 @@ "theseer/tokenizer": { "version": "1.1.0" }, + "trikoder/oauth2-bundle": { + "version": "2.0", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "2.0", + "ref": "f9437559d3494fa0189811ff84ab97e51cb58772" + }, + "files": [ + "app/config/eccube/packages/trikoder_oauth2.yaml", + "app/config/eccube/routes/trikoder_oauth2.yaml" + ] + }, "twig/extensions": { "version": "1.0", "recipe": { From 26dfaba4a267f634250c8eb017ad364b216fa9b8 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 13 Feb 2020 14:47:26 +0900 Subject: [PATCH 05/15] =?UTF-8?q?Client=20credentials=20grant=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 +++++++++++++++++++ .../eccube/packages/trikoder_oauth2.yaml | 2 ++ 2 files changed, 25 insertions(+) diff --git a/README.md b/README.md index 3a4cd79d098..785ac6df5bf 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,29 @@ openssl genrsa -out private.key 2048 openssl rsa -in private.key -pubout -out public.key ``` +[詳しくはこちら](https://oauth2.thephpleague.com/installation/#generating-public-and-private-keys) + +[クライアントの作成コマンドはこちら](https://github.com/trikoder/oauth2-bundle/blob/v2.x/docs/basic-setup.md) +[grant-type](https://github.com/trikoder/oauth2-bundle/blob/v2.x/OAuth2Grants.php) + +```クライアント作成例 +bin/console trikoder:oauth2:create-client --redirect-uri=http://127.0.0.1:8000/ --grant-type=authorization_code --grant-type=client_credentials --grant-type=implicit --grant-type=password --grant-type=refresh_token --scope=read --scope=write +bin/console trikoder:oauth2:list-clients +``` + +#### Client credentials grant + +``` +curl -X POST \ + http://127.0.0.1:8000/token \ + -H 'cache-control: no-cache' \ + -H 'content-type: application/x-www-form-urlencoded' \ + -d 'grant_type=client_credentials&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read' +``` + + + + ### 動作確認環境 * Apache/2.4.x (mod_rewrite / mod_ssl 必須) diff --git a/app/config/eccube/packages/trikoder_oauth2.yaml b/app/config/eccube/packages/trikoder_oauth2.yaml index a1085f077f3..5d3216e82f2 100644 --- a/app/config/eccube/packages/trikoder_oauth2.yaml +++ b/app/config/eccube/packages/trikoder_oauth2.yaml @@ -9,5 +9,7 @@ trikoder_oauth2: resource_server: public_key: '%kernel.project_dir%/var/oauth/public.key' + scopes: ['read', 'write'] + persistence: doctrine: null From 5139ce42ffb0ffd13c6643a047dc8b238b0c0e71 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 13 Feb 2020 16:08:51 +0900 Subject: [PATCH 06/15] =?UTF-8?q?Resource=20owner=20password=20credentials?= =?UTF-8?q?=20grant=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 ++++-- app/config/eccube/services.yaml | 7 +++ .../EventListener/UserResolveListener.php | 49 ++++++++++++++++++ .../Core/Encoder/UserPasswordEncoder.php | 51 +++++++++++++++++++ 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 src/Eccube/EventListener/UserResolveListener.php create mode 100644 src/Eccube/Security/Core/Encoder/UserPasswordEncoder.php diff --git a/README.md b/README.md index 785ac6df5bf..732bb831565 100644 --- a/README.md +++ b/README.md @@ -50,14 +50,16 @@ openssl rsa -in private.key -pubout -out public.key [クライアントの作成コマンドはこちら](https://github.com/trikoder/oauth2-bundle/blob/v2.x/docs/basic-setup.md) [grant-type](https://github.com/trikoder/oauth2-bundle/blob/v2.x/OAuth2Grants.php) -```クライアント作成例 +クライアント作成例 + +```shell bin/console trikoder:oauth2:create-client --redirect-uri=http://127.0.0.1:8000/ --grant-type=authorization_code --grant-type=client_credentials --grant-type=implicit --grant-type=password --grant-type=refresh_token --scope=read --scope=write bin/console trikoder:oauth2:list-clients ``` #### Client credentials grant -``` +```shell curl -X POST \ http://127.0.0.1:8000/token \ -H 'cache-control: no-cache' \ @@ -65,8 +67,15 @@ curl -X POST \ -d 'grant_type=client_credentials&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read' ``` +#### Resource owner password credentials grant - +```shell +curl -X POST \ + http://127.0.0.1:8000/token \ + -H 'cache-control: no-cache' \ + -H 'content-type: application/x-www-form-urlencoded' \ + -d 'grant_type=password&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read&username=admin&password=password' +``` ### 動作確認環境 diff --git a/app/config/eccube/services.yaml b/app/config/eccube/services.yaml index 9d6a5e34c83..ac1c4ea2dfa 100644 --- a/app/config/eccube/services.yaml +++ b/app/config/eccube/services.yaml @@ -171,3 +171,10 @@ services: # Symfony\Bridge\Twig\Extension\RoutingExtensionの後に登録するため, # autoconfigureはfalseにし, CompilerPassで追加する. autoconfigure: false + + Eccube\EventListener\UserResolveListener: + arguments: + - '@Eccube\Security\Core\User\MemberProvider' + - '@Eccube\Security\Core\Encoder\UserPasswordEncoder' + tags: + - { name: kernel.event_listener, event: trikoder.oauth2.user_resolve, method: onUserResolve } \ No newline at end of file diff --git a/src/Eccube/EventListener/UserResolveListener.php b/src/Eccube/EventListener/UserResolveListener.php new file mode 100644 index 00000000000..d868c2436f0 --- /dev/null +++ b/src/Eccube/EventListener/UserResolveListener.php @@ -0,0 +1,49 @@ +userProvider = $userProvider; + $this->userPasswordEncoder = $userPasswordEncoder; + } + + /** + * @param UserResolveEvent $event + */ + public function onUserResolve(UserResolveEvent $event): void + { + $user = $this->userProvider->loadUserByUsername($event->getUsername()); + + if (null === $user) { + return; + } + + if (!$this->userPasswordEncoder->isPasswordValid($user, $event->getPassword())) { + return; + } + + $event->setUser($user); + } +} diff --git a/src/Eccube/Security/Core/Encoder/UserPasswordEncoder.php b/src/Eccube/Security/Core/Encoder/UserPasswordEncoder.php new file mode 100644 index 00000000000..0e56aacf870 --- /dev/null +++ b/src/Eccube/Security/Core/Encoder/UserPasswordEncoder.php @@ -0,0 +1,51 @@ +passwordEncoder = $passwordEncoder; + } + + /** + * {@inheritdoc} + */ + public function encodePassword(UserInterface $user, $plainPassword) + { + return $this->passwordEncoder->encodePassword($plainPassword, $user->getSalt()); + } + + /** + * {@inheritdoc} + */ + public function isPasswordValid(UserInterface $user, $raw) + { + return $this->passwordEncoder->isPasswordValid($user->getPassword(), $raw, $user->getSalt()); + + } +} From 3d9dbd44d7ffa13b3337e7bb3fb9e006aba99d15 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 13 Feb 2020 22:03:27 +0900 Subject: [PATCH 07/15] =?UTF-8?q?Implicit=20grant=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++ app/config/eccube/packages/security.yaml | 2 +- .../DependencyInjection/EccubeExtension.php | 12 ++++---- .../AuthorizationRequestResolveListener.php | 29 +++++++++++++++++++ 4 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 src/Eccube/EventListener/AuthorizationRequestResolveListener.php diff --git a/README.md b/README.md index 732bb831565..3d0b9418272 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,12 @@ curl -X POST \ -d 'grant_type=password&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read&username=admin&password=password' ``` +#### Implicit grant + +``` +http://127.0.0.1:8000/authorize?response_type=token&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read +``` + ### 動作確認環境 * Apache/2.4.x (mod_rewrite / mod_ssl 必須) diff --git a/app/config/eccube/packages/security.yaml b/app/config/eccube/packages/security.yaml index efb8df1e3cb..bc3868ee3cb 100644 --- a/app/config/eccube/packages/security.yaml +++ b/app/config/eccube/packages/security.yaml @@ -21,7 +21,7 @@ security: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false admin: - pattern: '^/%eccube_admin_route%/' + pattern: '^(/%eccube_admin_route%/|/authorize)' anonymous: true provider: member_provider form_login: diff --git a/src/Eccube/DependencyInjection/EccubeExtension.php b/src/Eccube/DependencyInjection/EccubeExtension.php index 5772592a093..4a354cbb0e8 100644 --- a/src/Eccube/DependencyInjection/EccubeExtension.php +++ b/src/Eccube/DependencyInjection/EccubeExtension.php @@ -64,12 +64,12 @@ protected function configureFramework(ContainerBuilder $container) // SSL強制時は, httpsのみにアクセス制限する $accessControl = [ - ['path' => '^/%eccube_admin_route%/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/%eccube_admin_route%/', 'roles' => 'ROLE_ADMIN'], - ['path' => '^/mypage/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/mypage/withdraw_complete', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/mypage/change', 'roles' => 'IS_AUTHENTICATED_FULLY'], - ['path' => '^/mypage/', 'roles' => 'ROLE_USER'], + ['path' => '^/%eccube_admin_route%/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^(/%eccube_admin_route%/|/authorize)', 'roles' => 'ROLE_ADMIN'], + ['path' => '^/mypage/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/mypage/withdraw_complete', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/mypage/change', 'roles' => 'IS_AUTHENTICATED_FULLY'], + ['path' => '^/mypage/', 'roles' => 'ROLE_USER'], ]; if ($forceSSL) { foreach ($accessControl as &$control) { diff --git a/src/Eccube/EventListener/AuthorizationRequestResolveListener.php b/src/Eccube/EventListener/AuthorizationRequestResolveListener.php new file mode 100644 index 00000000000..0895cf98078 --- /dev/null +++ b/src/Eccube/EventListener/AuthorizationRequestResolveListener.php @@ -0,0 +1,29 @@ + 'onAuthorizationRequestResolve', + ]; + } + + public function onAuthorizationRequestResolve(AuthorizationRequestResolveEvent $event): void + { + $user = $event->getUser(); + + if (null === $user) { + return; + } + + $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED); + } +} From 6b4e4e4620ce99d027a964c92984a58de8aada8e Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 13 Feb 2020 22:32:30 +0900 Subject: [PATCH 08/15] =?UTF-8?q?Authorization=20code=20grant=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=EF=BC=88=E9=80=94=E4=B8=AD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3d0b9418272..89e3beb2be0 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ curl -X POST \ http://127.0.0.1:8000/token \ -H 'cache-control: no-cache' \ -H 'content-type: application/x-www-form-urlencoded' \ - -d 'grant_type=client_credentials&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read' + -d 'grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}&scope=read' ``` #### Resource owner password credentials grant @@ -74,13 +74,27 @@ curl -X POST \ http://127.0.0.1:8000/token \ -H 'cache-control: no-cache' \ -H 'content-type: application/x-www-form-urlencoded' \ - -d 'grant_type=password&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read&username=admin&password=password' + -d 'grant_type=password&client_id={client_id}&client_secret={client_secret}&scope=read&username=admin&password=password' ``` #### Implicit grant +```uri +http://127.0.0.1:8000/authorize?response_type=token&client_id={client_id}&client_secret={client_secret}&scope=read ``` -http://127.0.0.1:8000/authorize?response_type=token&client_id=df9dea359f9076daae73f4aa07d6a7e8&client_secret=a921ed597f91e367e9d268e128b0550f165c6e415e768ed4b7e2dc29d406bf7d95b16e9b76e4f66912d0fc8dce388cbe4aa822a8515afc99f6fc6f4dfbfe58a7&scope=read + +#### Authorization code grant + +```uri +http://127.0.0.1:8000/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope=read +``` + +```shell +curl -X POST \ + http://127.0.0.1:8000/token \ + -H 'cache-control: no-cache' \ + -H 'content-type: application/x-www-form-urlencoded' \ + -d 'grant_type=authorization_code&client_id={client_id}&client_secret={client_secret}&redirect_uri={redirect_uri}&code={code}' ``` ### 動作確認環境 From 9ffdf3890cb1e4715a59a1f7e80fbb1a8c17c56d Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 13 Feb 2020 22:38:58 +0900 Subject: [PATCH 09/15] =?UTF-8?q?Refresh=20token=20grant=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 89e3beb2be0..95ff3951ff9 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,16 @@ curl -X POST \ -d 'grant_type=authorization_code&client_id={client_id}&client_secret={client_secret}&redirect_uri={redirect_uri}&code={code}' ``` +#### Refresh token grant + +```shell +curl -X POST \ + http://127.0.0.1:8000/token \ + -H 'cache-control: no-cache' \ + -H 'content-type: application/x-www-form-urlencoded' \ + -d 'grant_type=refresh_token&client_id={client_id}&client_secret={client_secret}&refresh_token={refresh_token}' +``` + ### 動作確認環境 * Apache/2.4.x (mod_rewrite / mod_ssl 必須) From 951ecd4d1e2244a265d098c3384603582718c488 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Tue, 18 Feb 2020 09:30:15 +0900 Subject: [PATCH 10/15] =?UTF-8?q?Implicit=20grant=E3=81=8A=E3=82=88?= =?UTF-8?q?=E3=81=B3Refresh=20token=20grant=E3=81=AB=E8=AA=8D=E5=8F=AF?= =?UTF-8?q?=E3=81=AE=E7=A2=BA=E8=AA=8D=E7=94=BB=E9=9D=A2=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- .../Admin/OAuth2/OAuth2Controller.php | 75 ++++++++++++++++++ .../Type/Admin/OAuth2AuthorizationType.php | 77 +++++++++++++++++++ .../template/admin/OAuth2/authorization.twig | 22 ++++++ 4 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 src/Eccube/Controller/Admin/OAuth2/OAuth2Controller.php create mode 100644 src/Eccube/Form/Type/Admin/OAuth2AuthorizationType.php create mode 100644 src/Eccube/Resource/template/admin/OAuth2/authorization.twig diff --git a/README.md b/README.md index 95ff3951ff9..29772abc35b 100644 --- a/README.md +++ b/README.md @@ -80,13 +80,13 @@ curl -X POST \ #### Implicit grant ```uri -http://127.0.0.1:8000/authorize?response_type=token&client_id={client_id}&client_secret={client_secret}&scope=read +http://127.0.0.1:8000/admin/authorize?response_type=token&client_id={client_id}&client_secret={client_secret}&scope=read&state={csrf_token} ``` #### Authorization code grant ```uri -http://127.0.0.1:8000/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope=read +http://127.0.0.1:8000/admin/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope=read&state={csrf_token} ``` ```shell diff --git a/src/Eccube/Controller/Admin/OAuth2/OAuth2Controller.php b/src/Eccube/Controller/Admin/OAuth2/OAuth2Controller.php new file mode 100644 index 00000000000..2954d841bca --- /dev/null +++ b/src/Eccube/Controller/Admin/OAuth2/OAuth2Controller.php @@ -0,0 +1,75 @@ +get('response_type'); + $client_id = $request->get('client_id'); + $client_secret = $request->get('client_secret'); + $redirect_uri = $request->get('redirect_uri'); + $state = $request->get('state'); + $scope = $request->get('scope'); + + $builder = $this->formFactory->createBuilder(OAuth2AuthorizationType::class); + + $form = $builder->getForm(); + + $form['response_type']->setData($response_type); + $form['client_id']->setData($client_id); + $form['client_secret']->setData($client_secret); + $form['redirect_uri']->setData($redirect_uri); + $form['state']->setData($state); + $form['scope']->setData($scope); + + if ('POST' === $request->getMethod()) { + $form->handleRequest($request); + if ($form->isValid()) { + return $this->redirectToRoute('oauth2_authorize', $form->getData()); + } + } + + return [ + 'client_id' => $client_id, + 'redirect_uri' => $redirect_uri, + 'response_type' => $response_type, + 'state' => $state, + 'scope' => $scope, + 'client_secret' => $client_secret, + 'form' => $form->createView(), + ]; + } +} diff --git a/src/Eccube/Form/Type/Admin/OAuth2AuthorizationType.php b/src/Eccube/Form/Type/Admin/OAuth2AuthorizationType.php new file mode 100644 index 00000000000..4033f2d1f1d --- /dev/null +++ b/src/Eccube/Form/Type/Admin/OAuth2AuthorizationType.php @@ -0,0 +1,77 @@ +eccubeConfig = $eccubeConfig; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + // TODO + $builder + ->add('client_id', HiddenType::class, [ + 'constraints' => [ + new Assert\NotBlank(), + ], + ]) + ->add('client_secret', HiddenType::class, [ +// 'constraints' => [ +// new Assert\NotBlank(), +// ], + ]) + ->add('redirect_uri', HiddenType::class, [ +// 'constraints' => [ +// new Assert\NotBlank(), +// ], + ]) + ->add('response_type', HiddenType::class, [ + 'constraints' => [ + new Assert\NotBlank(), + ], + ]) + ->add('state', HiddenType::class, [ + 'constraints' => [ + new Assert\NotBlank(), + ], + ]) + ->add('scope', HiddenType::class, [ + 'constraints' => [ + new Assert\NotBlank(), + ], + ]); + } + + public function getBlockPrefix() + { + return 'oauth_authorization'; + } +} diff --git a/src/Eccube/Resource/template/admin/OAuth2/authorization.twig b/src/Eccube/Resource/template/admin/OAuth2/authorization.twig new file mode 100644 index 00000000000..644a86e7928 --- /dev/null +++ b/src/Eccube/Resource/template/admin/OAuth2/authorization.twig @@ -0,0 +1,22 @@ +{% extends '@admin/login_frame.twig' %} + +{% block main %} +

このアプリ連携を許可しますか?

+

このアプリは以下のアクセス権を要求しています:

+

{{ scope }}

+ + {{ form_start(form) }} + {{ form_errors(form) }} + + {{ form_row(form.client_id) }} + {{ form_row(form.client_secret) }} + {{ form_row(form.redirect_uri) }} + {{ form_row(form.response_type) }} + {{ form_row(form.state) }} + {{ form_row(form.scope) }} +
+ +
+ {{ form_end(form) }} + +{% endblock %} From d981ba70858282c1353f36367299db04053d03ff Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Tue, 18 Feb 2020 14:32:14 +0900 Subject: [PATCH 11/15] =?UTF-8?q?GraphQL=E3=81=AE=E3=83=AB=E3=83=BC?= =?UTF-8?q?=E3=83=86=E3=82=A3=E3=83=B3=E3=82=B0(/api)=E3=81=AB=E3=82=A2?= =?UTF-8?q?=E3=82=AF=E3=82=BB=E3=82=B9=E3=83=88=E3=83=BC=E3=82=AF=E3=83=B3?= =?UTF-8?q?=E3=81=AB=E3=82=88=E3=82=8B=E3=82=A2=E3=82=AF=E3=82=BB=E3=82=B9?= =?UTF-8?q?=E5=88=B6=E9=99=90=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/config/eccube/packages/security.yaml | 5 +++++ src/Eccube/Controller/ApiController.php | 2 ++ 2 files changed, 7 insertions(+) diff --git a/app/config/eccube/packages/security.yaml b/app/config/eccube/packages/security.yaml index bc3868ee3cb..695cf59f57e 100644 --- a/app/config/eccube/packages/security.yaml +++ b/app/config/eccube/packages/security.yaml @@ -20,6 +20,11 @@ security: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false + api: + pattern: ^/api + security: true + stateless: true + oauth2: true admin: pattern: '^(/%eccube_admin_route%/|/authorize)' anonymous: true diff --git a/src/Eccube/Controller/ApiController.php b/src/Eccube/Controller/ApiController.php index 2b531a23c0e..8136ac50e59 100644 --- a/src/Eccube/Controller/ApiController.php +++ b/src/Eccube/Controller/ApiController.php @@ -28,6 +28,7 @@ use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\Type\Schema; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; @@ -61,6 +62,7 @@ public function __construct(Types $types, ProductRepository $productRepository, /** * @Route("/api", name="api") + * @Security("has_role('ROLE_OAUTH2_READ')") */ public function index(Request $request) { From dfaefecd4c9d983939acaca9dcd2422689273af7 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Wed, 19 Feb 2020 15:37:52 +0900 Subject: [PATCH 12/15] =?UTF-8?q?PHP7.1=E3=81=AF=E3=82=B5=E3=83=9D?= =?UTF-8?q?=E3=83=BC=E3=83=88=E5=A4=96=E3=81=AE=E3=81=9F=E3=82=81travis?= =?UTF-8?q?=E3=81=AE=E5=AF=BE=E8=B1=A1=E3=81=8B=E3=82=89=E9=99=A4=E5=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 76837aacf0d..eb5cc379277 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,6 @@ cache: - bin/.phpunit php: - - 7.1 - 7.2 - 7.3 - 7.4snapshot From 4485493102222072681d8214a94b27a07614259b Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Wed, 26 Feb 2020 14:40:49 +0900 Subject: [PATCH 13/15] =?UTF-8?q?=E8=AA=8D=E5=8F=AF=E3=83=95=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=81=AEUnitTest=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tests/Web/Admin/LoginControllerTest.php | 22 +++++ .../Web/Admin/OAuth2/OAuth2ControllerTest.php | 80 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 tests/Eccube/Tests/Web/Admin/OAuth2/OAuth2ControllerTest.php diff --git a/tests/Eccube/Tests/Web/Admin/LoginControllerTest.php b/tests/Eccube/Tests/Web/Admin/LoginControllerTest.php index 19275e97abc..be18ff96ed7 100644 --- a/tests/Eccube/Tests/Web/Admin/LoginControllerTest.php +++ b/tests/Eccube/Tests/Web/Admin/LoginControllerTest.php @@ -53,4 +53,26 @@ public function testRoutingAdminLogin_ログインしていない場合は401エ $this->client->getResponse()->getStatusCode() ); } + + public function testRoutingAdminOauth2Authorize_ログインしていない場合はログイン画面を表示() + { + $this->client->request('GET', $this->generateUrl('admin_oauth2_authorize')); + + // ログイン + $this->assertEquals( + 401, + $this->client->getResponse()->getStatusCode() + ); + } + + public function testRoutingOauth2Authorize_ログインしていない場合はログイン画面を表示() + { + $this->client->request('GET', $this->generateUrl('oauth2_authorize')); + + // ログイン + $this->assertEquals( + 401, + $this->client->getResponse()->getStatusCode() + ); + } } diff --git a/tests/Eccube/Tests/Web/Admin/OAuth2/OAuth2ControllerTest.php b/tests/Eccube/Tests/Web/Admin/OAuth2/OAuth2ControllerTest.php new file mode 100644 index 00000000000..67d2fb6ed36 --- /dev/null +++ b/tests/Eccube/Tests/Web/Admin/OAuth2/OAuth2ControllerTest.php @@ -0,0 +1,80 @@ +client->request('GET', $this->generateUrl('admin_oauth2_authorize')); + + // ログイン + $this->assertEquals( + 200, + $this->client->getResponse()->getStatusCode() + ); + } + + public function testRoutingAdminOauth2Authorize_権限移譲を許可() + { + $parameters = [ + 'oauth_authorization' => [ + 'client_id' => 'dummy', + 'client_secret' => 'dummy', + 'redirect_uri' => 'dummy', + 'response_type' => 'dummy', + 'state' => 'dummy', + 'scope' => 'dummy', + Constant::TOKEN_NAME => 'dummy', + ], + ]; + + $this->client->request( + 'POST', $this->generateUrl('admin_oauth2_authorize'), + $parameters + ); + + $this->assertTrue($this->client->getResponse()->isRedirection()); + } + + public function testRoutingAdminOauth2Authorize_権限移譲を許可_パラメータが足りない場合() + { + $parameters = [ + 'oauth_authorization' => [ + 'client_id' => '', + 'client_secret' => '', + 'redirect_uri' => '', + 'response_type' => '', + 'state' => '', + 'scope' => '', + Constant::TOKEN_NAME => '', + ], + ]; + + $this->client->request( + 'POST', $this->generateUrl('admin_oauth2_authorize'), + $parameters + ); + + $this->assertFalse($this->client->getResponse()->isRedirection()); + } +} From dedb34fe37d0e6eaedb6dac0d01432a5051c9cbb Mon Sep 17 00:00:00 2001 From: Chihiro Adachi <8196725+chihiro-adachi@users.noreply.github.com> Date: Thu, 27 Feb 2020 10:58:57 +0900 Subject: [PATCH 14/15] =?UTF-8?q?=E9=8D=B5=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index eb5cc379277..06a5057bdcf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,6 +50,11 @@ eccube_setup: &eccube_setup | bin/console doctrine:database:create --env=dev bin/console doctrine:schema:create --env=dev bin/console eccube:fixtures:load --env=dev + mkdir var/oauth + openssl genrsa -out private.key 2048 + openssl rsa -in private.key -pubout -out public.key + mv private.key var/oauth + mv public.key var/oauth package_api_setup: &package_api_setup | mkdir ${PWD}/repos From 92ee779852271bb5221abc6fe395767dd41d41e6 Mon Sep 17 00:00:00 2001 From: hideki_okajima Date: Thu, 27 Feb 2020 12:14:14 +0900 Subject: [PATCH 15/15] =?UTF-8?q?appveyor.yml=E3=81=AB=E9=8D=B5=E7=94=9F?= =?UTF-8?q?=E6=88=90=E3=81=AE=E5=87=A6=E7=90=86=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appveyor.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index aba72cf58d7..3b16da90c56 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -67,6 +67,11 @@ before_test: - php bin\console doctrine:database:create - php bin\console doctrine:schema:create - php bin\console eccube:fixtures:load + - mkdir var\oauth + - openssl genrsa -out private.key 2048 + - openssl rsa -in private.key -pubout -out public.key + - move private.key var\oauth + - move public.key var\oauth test_script: - php bin\phpunit --exclude-group cache-clear