diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53c4d08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/vendor/ +/build/ +/.idea/ + +/composer.lock +/phpunit.xml +/.php_cs.cache +/.phpunit.result.cache +.DS_Store diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..2ce35da --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,185 @@ +exclude(['tests/Fake', 'tests/tmp', 'template']) + ->in(__DIR__); + +return \PhpCsFixer\Config::create() + ->setRiskyAllowed(true) + ->setRules([ + '@PSR2' => true, + '@PHP70Migration:risky' => true, + '@PHP71Migration:risky' => true, + 'align_multiline_comment' => true, + 'array_indentation' => true, + 'array_syntax' => ['syntax' => 'short'], + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => true, // @Symfony + 'blank_line_after_opening_tag' => true, // @Symfony + 'blank_line_before_return' => true, + 'blank_line_before_statement' => ['statements' => ['break', 'continue', 'declare', 'return', 'throw']], // @Symfony + 'cast_spaces' => true, // @Symfony + 'class_attributes_separation' => ['elements' => ['const', 'method']], // @Symfony +// 'class_keyword_remove' => true, + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, +// 'comment_to_phpdoc' => true, + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], // @Symfony +// 'date_time_immutable' => true, + 'declare_equal_normalize' => true, // @Symfony + 'dir_constant' => true, // @Symfony:risky + 'ereg_to_preg' => true, // @Symfony:risky + 'error_suppression' => true, // @Symfony:risky + 'escape_implicit_backslashes' => true, + 'explicit_indirect_variable' => true, + 'explicit_string_variable' => true, +// 'final_internal_class' => true, + 'fully_qualified_strict_types' => true, + 'function_to_constant' => true, // @Symfony:risky + 'function_typehint_space' => true, // @Symfony + 'general_phpdoc_annotation_remove' => ['author', 'category', 'package', 'copyright', 'version'], + 'header_comment' => ['header' => $header, 'comment_type' => 'comment'], + 'heredoc_to_nowdoc' => true, + 'include' => true, // @Symfony +// 'increment_style' => 'pre', // @Symfony + 'indentation_type' => true, + 'is_null' => ['use_yoda_style' => false], // @Symfony:risky + 'linebreak_after_opening_tag' => true, +// 'list_syntax' => true, +// 'logical_operators' => true, + 'lowercase_cast' => true, // @Symfony + 'lowercase_static_reference' => true, // @Symfony + 'magic_constant_casing' => true, +// 'mb_str_functions' => true, + 'method_chaining_indentation' => true, + 'method_separation' => true, + 'modernize_types_casting' => true, // @Symfony:risky + 'multiline_comment_opening_closing' => true, + 'multiline_whitespace_before_semicolons' => true, +// 'native_constant_invocation' => true, + 'native_function_casing' => true, // @Symfony +// 'native_function_invocation' => true, +// 'new_with_braces' => true, // @Symfony + 'no_alias_functions' => true, // @Symfony:risky + 'no_alternative_syntax' => true, + 'no_binary_string' => true, + 'no_blank_lines_after_class_opening' => true, // @Symfony + 'no_blank_lines_after_phpdoc' => true, // @Symfony +// 'no_blank_lines_before_namespace' => true, + 'no_empty_comment' => true, // @Symfony + 'no_empty_phpdoc' => true, // @Symfony + 'no_empty_statement' => true, // @Symfony + 'no_extra_blank_lines' => true, + 'no_homoglyph_names' => true, // @Symfony:risky + 'no_leading_import_slash' => true, // @Symfony + 'no_leading_namespace_whitespace' => true, // @Symfony + 'no_mixed_echo_print' => true, // @Symfony + 'no_multiline_whitespace_around_double_arrow' => true, // @Symfony + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'no_short_bool_cast' => true, // @Symfony + 'no_short_echo_tag' => false, + 'no_singleline_whitespace_before_semicolons' => true, // @Symfony + 'no_spaces_around_offset' => true, // @Symfony + 'no_superfluous_elseif' => true, + 'no_superfluous_phpdoc_tags' => true, + 'no_trailing_comma_in_list_call' => true, // @Symfony + 'no_trailing_comma_in_singleline_array' => true, // @Symfony + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_control_parentheses' => true, // @Symfony + 'no_unneeded_curly_braces' => true, // @Symfony + 'no_unneeded_final_method' => true, // @Symfony + 'no_unreachable_default_argument_value' => true, + 'no_unset_on_property' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, // @Symfony + 'no_whitespace_in_blank_line' => true, // @Symfony + 'non_printable_character' => true, // @Symfony + 'normalize_index_brace' => true, // @Symfony + 'not_operator_with_space' => false, + 'not_operator_with_successor_space' => true, + 'object_operator_without_whitespace' => true, // @Symfony + 'ordered_class_elements' => true, + 'ordered_imports' => true, + 'php_unit_construct' => true, // @Symfony:risky + 'php_unit_dedicate_assert' => true, + 'php_unit_expectation' => true, + 'php_unit_fqcn_annotation' => true, // @Symfony +// 'php_unit_internal_class' => true, // @Symfony] +// 'php_unit_mock' => true, + 'php_unit_namespaced' => true, + 'php_unit_no_expectation_annotation' => true, + 'php_unit_ordered_covers' => true, + 'php_unit_set_up_tear_down_visibility' => true, + 'php_unit_strict' => true, +// 'php_unit_test_annotation' => true, +// 'php_unit_test_case_static_method_calls' => true, +// 'php_unit_test_class_requires_covers' => true, +// 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_align' => true, // @Symfony] + 'phpdoc_annotation_without_dot' => true, // @Symfony] + 'phpdoc_indent' => true, // @Symfony] + 'phpdoc_inline_tag' => true, // @Symfony] + 'phpdoc_no_access' => true, // @Symfony] + 'phpdoc_no_alias_tag' => true, // @Symfony + 'phpdoc_no_empty_return' => true, // @Symfony + 'phpdoc_no_package' => true, // @Symfony +// 'phpdoc_no_useless_inheritdoc' => true, // @Symfony + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, // @Symfony + 'phpdoc_scalar' => true, // @Symfony + 'phpdoc_separation' => true, // @Symfony + 'phpdoc_single_line_var_spacing' => true, // @Symfony +// 'phpdoc_summary' => true, // @Symfony + 'phpdoc_to_comment' => true, // @Symfony + 'phpdoc_trim' => true, // @Symfony + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => true, // @Symfony + 'phpdoc_types_order' => true, // @Symfony + 'phpdoc_var_without_name' => true, // @Symfony + 'protected_to_private' => true, + 'psr0' => true, + 'psr4' => true, // @Symfony:risky + 'return_assignment' => true, + 'return_type_declaration' => ['space_before' => 'one'], + 'self_accessor' => true, // @Symfony:risky + 'semicolon_after_instruction' => true, // @Symfony + 'set_type_to_cast' => true, // @Symfony:risky + 'short_scalar_cast' => true, // @Symfony:risky + 'simplified_null_return' => true, + 'single_blank_line_before_namespace' => true, // @Symfony +// 'single_line_comment_style' => true, // @Symfony + 'single_line_after_imports' => true, + 'single_quote' => true, // @Symfony + 'space_after_semicolon' => true, // @Symfony + 'standardize_increment' => true, // @Symfony + 'standardize_not_equals' => true, // @Symfony +// 'static_lambda' => true, +// 'strict_comparison' => true, + 'strict_param' => true, +// 'string_line_ending' => true, + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'ternary_operator_spaces' => true, +// 'trailing_comma_in_multiline_array' => true, // @Symfony + 'trim_array_spaces' => true, // @Symfony + 'unary_operator_spaces' => true, // @Symfony + 'visibility_required' => true, +// 'void_return' => true, // @PHP71Migration:risky + 'whitespace_after_comma_in_array' => true, // @Symfony +// 'yoda_style' => true // @Symfony + ]) + ->setFinder($finder); \ No newline at end of file diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000..fa99018 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,17 @@ +filter: + paths: ["src/*"] +tools: + external_code_coverage: true + php_code_coverage: true + php_sim: true + php_pdepend: true + php_analyzer: true + php_cpd: true + php_mess_detector: + enabled: true + config: + ruleset: ./phpmd.xml + php_code_sniffer: + enabled: true + config: + ruleset: ./phpcs.xml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..999c1d0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,57 @@ +language: php +sudo: false + +php: + - 7.2 + - 7.3 + - 7.4 + +cache: + directories: + - vendor + - $HOME/.composer/cache + +matrix: + fast_finish: true + +before_install: + - mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{,.disabled} || echo "xdebug not available" + - composer self-update + +install: + - composer install + +script: + - ./vendor/bin/phpunit; + +jobs: + include: + - stage: Test + name: Lowest dependencies + php: 7.2 + install: composer update --prefer-dist --prefer-lowest + + - stage: Test + name: Code coverage + php: 7.2 + before_script: + - mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{.disabled,} + - if [[ ! $(php -m | grep -si xdebug) ]]; then echo "xdebug required for coverage"; exit 1; fi + script: + - ./vendor/bin/phpunit -v --coverage-clover=coverage.clover + after_script: + - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; + + - stage: Code Quality + name: Static analysis + php: 7.2 + install: composer require --dev phpstan/phpstan-shim ^0.10; + script: + - ./vendor/bin/phpstan analyse -l max -c phpstan.neon src tests --no-progress --no-interaction; + + - stage: Code Quality + name: Coding standards + php: 7.2 + install: composer require --dev friendsofphp/php-cs-fixer ^2.0; + script: + - ./vendor/bin/php-cs-fixer --dry-run -v fix; \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..db86eac --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) <2018> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..b49ed6a --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Ray.Auth0Module diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..7bfd4ed --- /dev/null +++ b/composer.json @@ -0,0 +1,60 @@ +{ + "name": "ray/auth0-module", + "description": "auth0 module for Ray.Di", + "license": "MIT", + "authors": [ + { + "name": "Shingo Kumagai" + } + ], + "require": { + "auth0/auth0-php": "^7.0", + "ray/di": "^2.7.1", + "ray/aura-web-module": "^0.1.0", + "koriym/http-constants": "^1.1", + "josegonzalez/dotenv": "^3.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5", + "squizlabs/php_codesniffer": "^3.2", + "friendsofphp/php-cs-fixer": "^2.11", + "phpmd/phpmd": "^2.6", + "ray/di": "^2.10|2.x-dev", + "doctrine/annotations": "^1.8", + "phpstan/phpstan": "^0.12.5" + }, + "autoload": { + "psr-4": { + "Ray\\Auth0Module\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Ray\\Auth0Module\\": [ + "tests/", + "tests/Fake" + ] + } + }, + "scripts": { + "test": [ + "vendor/bin/phpunit" + ], + "tests": [ + "@cs", + "@test", + "vendor/bin/phpstan analyse -l max src -c phpstan.neon --no-progress" + ], + "coverage": [ + "php -dzend_extension=xdebug.so ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage" + ], + "cs": [ + "vendor/bin/php-cs-fixer fix -v --dry-run", + "vendor/bin/phpcs --standard=phpcs.xml src;" + ], + "cs-fix": [ + "vendor/bin/php-cs-fixer fix -v", + "vendor/bin/phpcbf src tests" + ] + } +} diff --git a/phpcs.xml b/phpcs.xml new file mode 100755 index 0000000..2169f08 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/phpmd.xml b/phpmd.xml new file mode 100755 index 0000000..85341c9 --- /dev/null +++ b/phpmd.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpstan.neon b/phpstan.neon new file mode 100755 index 0000000..95610f5 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,7 @@ +parameters: + level: max + paths: + - src + - tests + ignoreErrors: + checkMissingIterableValueType: false \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100755 index 0000000..a646ac4 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,19 @@ + + + + + tests + + + + + + + + + src + + + diff --git a/src/Annotation/Auth0Config.php b/src/Annotation/Auth0Config.php new file mode 100644 index 0000000..8e54023 --- /dev/null +++ b/src/Annotation/Auth0Config.php @@ -0,0 +1,18 @@ +getKeys('https://' . $config['domain'] . '/.well-known/jwks.json'); + $this->verifier = new AsymmetricVerifier($jwks); + } + + public function verifyToken(string $token) : Token + { + try { + return $this->verifier->verifyAndDecode($token); + } catch (InvalidTokenException $e) { + throw new InvalidToken($e->getMessage()); + } + } +} diff --git a/src/Auth/AuthInterface.php b/src/Auth/AuthInterface.php new file mode 100644 index 0000000..0169a99 --- /dev/null +++ b/src/Auth/AuthInterface.php @@ -0,0 +1,12 @@ +config = $config; + parent::__construct($module); + } + + /** + * {@inheritdoc} + */ + protected function configure() : void + { + $this->install(new AuraWebModule); + + $this->bind()->annotatedWith(Auth0Config::class)->toInstance($this->config); + $this->bind(AuthInterface::class)->to(Auth::class)->in(Scope::SINGLETON); + $this->bind()->annotatedWith(Extractors::class)->toInstance([ + new AuthorizationHeaderTokenExtractor(), + ]); + $this->bind(TokenExtractorResolver::class)->in(Scope::SINGLETON); + $this->bind(Management::class)->toProvider(ManagementClientProvider::class); + $this->bind(Authentication::class)->toProvider(AuthenticationClientProvider::class); + } +} diff --git a/src/Exception/AuthenticationException.php b/src/Exception/AuthenticationException.php new file mode 100644 index 0000000..29b8843 --- /dev/null +++ b/src/Exception/AuthenticationException.php @@ -0,0 +1,9 @@ +headers->get(RequestHeader::AUTHORIZATION)) { + return false; + } + + $parts = explode(' ', $header); + + return count($parts) === 2 && strcasecmp($parts[0], 'Bearer') === 0; + } + + public function extract(Request $request) : string + { + return str_ireplace('Bearer ', '', $request->headers->get(RequestHeader::AUTHORIZATION)); + } +} diff --git a/src/Extractor/TokenExtractorInterface.php b/src/Extractor/TokenExtractorInterface.php new file mode 100644 index 0000000..e212227 --- /dev/null +++ b/src/Extractor/TokenExtractorInterface.php @@ -0,0 +1,14 @@ +extractors = $extractors; + } + + public function resolve(Request $request) : TokenExtractorInterface + { + foreach ($this->extractors as $extractor) { + if ($extractor->supports($request)) { + return $extractor; + } + } + + throw new TokenNotFound(); + } +} diff --git a/src/Provider/AuthenticationClientInject.php b/src/Provider/AuthenticationClientInject.php new file mode 100644 index 0000000..0a164c7 --- /dev/null +++ b/src/Provider/AuthenticationClientInject.php @@ -0,0 +1,23 @@ +authClient = $authClient; + } +} diff --git a/src/Provider/AuthenticationClientProvider.php b/src/Provider/AuthenticationClientProvider.php new file mode 100644 index 0000000..49bd391 --- /dev/null +++ b/src/Provider/AuthenticationClientProvider.php @@ -0,0 +1,30 @@ +config = $config; + } + + public function get() : Authentication + { + return new Authentication($this->config['domain'], $this->config['client_id'], $this->config['client_secret']); + } +} diff --git a/src/Provider/ManagementClientInject.php b/src/Provider/ManagementClientInject.php new file mode 100644 index 0000000..7467f80 --- /dev/null +++ b/src/Provider/ManagementClientInject.php @@ -0,0 +1,23 @@ +managementClient = $managementClient; + } +} diff --git a/src/Provider/ManagementClientProvider.php b/src/Provider/ManagementClientProvider.php new file mode 100644 index 0000000..2381cdb --- /dev/null +++ b/src/Provider/ManagementClientProvider.php @@ -0,0 +1,36 @@ +config = $config; + } + + public function get() : Management + { + $response = $this->authClient->client_credentials([ + 'audience' => 'https://' . $this->config['domain'] . '/api/v2/', + ]); + + return new Management($response['access_token'], $this->config['domain']); + } +} diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php new file mode 100644 index 0000000..e69de29 diff --git a/tests/Auth0ModuleTest.php_ b/tests/Auth0ModuleTest.php_ new file mode 100644 index 0000000..65178c1 --- /dev/null +++ b/tests/Auth0ModuleTest.php_ @@ -0,0 +1,49 @@ +module = new class extends AbstractModule { +// protected function configure() : void +// { +// $this->install(new AuraWebModule()); +// +// $env = dirname(__DIR__, 2) . '/.env.test'; +// (new Loader($env))->parse()->putenv(true); +// $this->bind()->annotatedWith(Auth0Config::class)->toInstance([ +// 'domain' => getenv('AUTH0_DOMAIN'), +// 'client_id' => getenv('AUTH0_CLIENT_ID'), +// 'client_secret' => getenv('AUTH0_CLIENT_SECRET'), +// ]); +// $this->bind(AuthInterface::class)->to(Auth::class)->in(Scope::SINGLETON); +// $this->bind()->annotatedWith(Extractors::class)->toInstance([ +// new AuthorizationHeaderTokenExtractor(), +// ]); +// $this->bind(TokenExtractorResolver::class)->in(Scope::SINGLETON); +// $this->bind(Management::class)->toProvider(ManagementClientProvider::class); +// $this->bind(Authentication::class)->toProvider(AuthenticationClientProvider::class); +// } +// }; +// $injector = (new Injector($this->module, dirname(__DIR__) . '/tmp')); +// $this->assertInstanceOf(Authentication::class, $injector->getInstance(Authentication::class)); +// $this->assertInstanceOf(Management::class, $injector->getInstance(Management::class)); + } +} diff --git a/tests/Extractor/AuthorizationHeaderTokenExtractorTest.php b/tests/Extractor/AuthorizationHeaderTokenExtractorTest.php new file mode 100644 index 0000000..346cc16 --- /dev/null +++ b/tests/Extractor/AuthorizationHeaderTokenExtractorTest.php @@ -0,0 +1,52 @@ +module = new class extends AbstractModule { + protected function configure() : void + { + $this->install(new AuraWebModule()); + } + }; + } + + protected function tearDown() : void + { + unset($_SERVER['HTTP_AUTHORIZATION']); + } + + public function testSupports() : void + { + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer token'; + $request = (new Injector($this->module, dirname(__DIR__) . '/tmp'))->getInstance(Request::class); + $extractor = new AuthorizationHeaderTokenExtractor(); + $result = $extractor->supports($request); + $this->assertTrue($result); + } + + public function testExtract() : void + { + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer token'; + $request = (new Injector($this->module, dirname(__DIR__) . '/tmp'))->getInstance(Request::class); + $extractor = new AuthorizationHeaderTokenExtractor(); + $result = $extractor->extract($request); + $this->assertSame('token', $result); + } +} diff --git a/tests/Provider/AuthProviderTest.php_ b/tests/Provider/AuthProviderTest.php_ new file mode 100644 index 0000000..5a155ae --- /dev/null +++ b/tests/Provider/AuthProviderTest.php_ @@ -0,0 +1,96 @@ +module = new class extends AbstractModule { + protected function configure() : void + { + $env = dirname(__DIR__, 2) . '/../.env.test'; + (new Loader($env))->parse()->putenv(true); + [$host, $db, $user, $password, $charset] = [ + getenv('DB_HOST'), + getenv('DB_NAME'), + getenv('DB_USER'), + getenv('DB_PASS'), + getenv('DB_CHARSET') + ]; + + if ($user === false || $password === false) { + throw new \RuntimeException('DB_USER and DB_PASSWORD is required.'); + } + + $dsn = "mysql:host={$host};dbname={$db};charset={$charset}"; + $this->install(new AuraSqlModule($dsn, $user, $password)); + $this->install(new AuraWebModule); + $this->install(new IdentityValueModule); + + $this->bind()->annotatedWith(Auth0Config::class)->toInstance([ + 'domain' => getenv('AUTH0_DOMAIN'), + 'client_id' => getenv('AUTH0_CLIENT_ID'), + 'client_secret' => getenv('AUTH0_CLIENT_SECRET'), + ]); + $this->bind(AuthInterface::class)->to(Auth::class)->in(Scope::SINGLETON); + $this->bind()->annotatedWith(Extractors::class)->toInstance([ + new AuthorizationHeaderTokenExtractor(), + ]); + $this->bind(TokenExtractorResolver::class)->in(Scope::SINGLETON); + $this->bind(Management::class)->toProvider(ManagementClientProvider::class); + $this->bind(Authentication::class)->toProvider(AuthenticationClientProvider::class); + $this->bind(AbstractAuth::class)->toProvider(AuthProvider::class)->in(Scope::SINGLETON); + } + }; + } + + public function testInvoke() : void + { + $injector = (new Injector($this->module, dirname(__DIR__) . '/tmp')); + $authClient = $injector->getInstance(Authentication::class); + $response = $authClient->oauth_token([ + 'grant_type' => 'password', + 'username' => 'example1@example.co.jp', + 'password' => 'Test1234', + 'audience' => 'https://admin-maquia.hpplus.jp/' + ]); + + $accessToken = $response['access_token']; + $_SERVER['HTTP_AUTHORIZATION'] = "Bearer {$accessToken}"; + $auth = $injector->getInstance(AbstractAuth::class); + $this->assertSame('example1@example.co.jp', $auth->email); + + $pdo = $injector->getInstance(ExtendedPdoInterface::class); + $select = $injector->getInstance(SelectInterface::class); + $select->from('cms_users')->cols(['id', 'name', 'name_kana'])->where('email = :email')->bindValues(['email' => $auth->email]); + $results = $pdo->fetchAll($select->getStatement(), $select->getBindValues()); + $this->assertCount(1, $results); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..c98075f --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,6 @@ +