diff --git a/.editorconfig b/.editorconfig
index 654c18b..3aca22b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -6,13 +6,10 @@
root = true
-[*.{php,inc,module}]
+[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
-
-[*.{json,json.dist,yml,yml.dist}]
-indent_size = 4
\ No newline at end of file
diff --git a/composer.json b/composer.json
index f519434..bbacc76 100644
--- a/composer.json
+++ b/composer.json
@@ -15,7 +15,9 @@
"ext-json": "*",
"ext-libxml": "*",
"ext-simplexml": "*",
+ "ergebnis/http-method": "^2.2",
"league/uri-components": "^2",
+ "loophp/psr17": "^1.0",
"openlss/lib-array2xml": "^1.0",
"psr/cache": "^1.0.1 || ^2 || ^3",
"psr/http-client": "^1.0",
@@ -24,7 +26,8 @@
"psr/http-factory-implementation": "^1",
"psr/http-message": "^1.0",
"psr/http-message-implementation": "^1",
- "psr/log": "^1.1 || ^2 || ^3"
+ "psr/http-server-handler": "^1.0",
+ "psr/http-server-middleware": "^1.0"
},
"require-dev": {
"ext-xdebug": "*",
@@ -32,14 +35,18 @@
"friends-of-phpspec/phpspec-code-coverage": "^6.0.0",
"infection/infection": "^0.23 || ^0.24",
"infection/phpspec-adapter": "^0.1.2",
- "monolog/monolog": "^1.0 || ^2.0",
"nyholm/psr7": "^1.4",
- "nyholm/psr7-server": "^1.0.0",
"phpspec/phpspec": "^7",
- "phpstan/phpstan-strict-rules": "^0.12 || ^1.0",
+ "phpstan/phpstan-strict-rules": "^1",
"symfony/cache": "^5.2",
"symfony/http-client": "^5.2"
},
+ "provide": {
+ "psr/http-server-handler-implementation": "^1.0"
+ },
+ "suggest": {
+ "nyholm/psr7": "A super lightweight PSR-7 implementation"
+ },
"autoload": {
"psr-4": {
"EcPhp\\CasLib\\": "./src/"
@@ -64,7 +71,6 @@
"changelog-unreleased": "docker-compose run auto_changelog -c .auto-changelog -u",
"changelog-version": "docker-compose run auto_changelog -c .auto-changelog -v",
"grumphp": "./vendor/bin/grumphp run",
- "phpinsights": "./vendor/bin/phpinsights analyse src/",
"phpspec": "./vendor/bin/phpspec run"
}
}
diff --git a/docs/index.rst b/docs/index.rst
index df61783..a48ef4e 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,10 +3,14 @@ CAS Lib
CAS Lib, a standard PHP library for `CAS authentication`_.
-The Central Authentication Service (CAS) is an Open-Source single sign-on protocol for the web.
-Its purpose is to permit a user to access multiple applications while providing their credentials only once.
-It also allows web applications to authenticate users without gaining access to a user's security credentials,
-such as a password. The name CAS also refers to a software package that implements this protocol.
+The Central Authentication Service (CAS) is an Open-Source single sign-on
+protocol for the web.
+Its purpose is to permit a user to access multiple applications while providing
+their credentials only once.
+It also allows web applications to authenticate users without gaining access to
+a user's security credentials,
+such as a password. The name CAS also refers to a software package that
+implements this protocol.
For improving the flexibility and in order to maximize it, it is able to
authenticate users and leaves the session handling up to the developer.
@@ -15,11 +19,11 @@ In order to foster a greater adoption of this library, it has been built
with interoperability in mind. It only uses `PHP Standards
Recommendations`_ interfaces.
-- `PSR-3`_ for logging,
- `PSR-4`_ for classes autoloading,
- `PSR-6`_ for caching,
- `PSR-7`_ for HTTP messages (requests, responses),
- `PSR-12`_ for coding standards,
+- `PSR-15`_ for HTTP Server Request Handlers,
- `PSR-17`_ for HTTP messages factories,
- `PSR-18`_ for HTTP client.
@@ -28,11 +32,11 @@ any PHP project, with any framework.
.. _CAS authentication: https://en.wikipedia.org/wiki/Central_Authentication_Service
.. _PHP Standards Recommendations: https://www.php-fig.org/
-.. _PSR-3: https://www.php-fig.org/psr/psr-3/
.. _PSR-4: https://www.php-fig.org/psr/psr-4/
.. _PSR-6: https://www.php-fig.org/psr/psr-6/
.. _PSR-7: https://www.php-fig.org/psr/psr-7/
.. _PSR-12: https://www.php-fig.org/psr/psr-12/
+.. _PSR-15: https://www.php-fig.org/psr/psr-15/
.. _PSR-17: https://www.php-fig.org/psr/psr-17/
.. _PSR-18: https://www.php-fig.org/psr/psr-18/
diff --git a/docs/pages/configuration.rst b/docs/pages/configuration.rst
index 59f837a..9ca9604 100644
--- a/docs/pages/configuration.rst
+++ b/docs/pages/configuration.rst
@@ -7,36 +7,21 @@ Configuration
protocol:
login:
path: /login
- allowed_parameters:
- - service
- - renew
- - gateway
+ default_parameters:
+ foo: bar
serviceValidate:
path: /p3/serviceValidate
- allowed_parameters:
- - service
- - ticket
- - pgtUrl
- - renew
- - format
default_parameters:
pgtUrl: https://my-app/casProxyCallback
logout:
path: /logout
- allowed_parameters:
- - service
default_parameters:
service: https://my-app/homepage
proxy:
path: /proxy
- allowed_parameters:
- - targetService
- - pgt
+ default_parameters:
+ foo: bar
proxyValidate:
path: /proxyValidate
- allowed_parameters:
- - service
- - ticket
- - pgtUrl
default_parameters:
- pgtUrl: https://my-app/casProxyCallback
\ No newline at end of file
+ pgtUrl: https://my-app/casProxyCallback
diff --git a/docs/pages/installation.rst b/docs/pages/installation.rst
index ea8ca93..40afb26 100644
--- a/docs/pages/installation.rst
+++ b/docs/pages/installation.rst
@@ -7,4 +7,27 @@ The easiest way to install it is through Composer_
composer require ecphp/cas-lib
-.. _Composer: https://getcomposer.org
\ No newline at end of file
+Based on the context this package is used, you might also need to install
+a package which provides `PSR7 implementations`_.
+
+There are `many packages implementing PSR7`_, you can pick the one you prefer,
+exemple:
+
+.. code-block:: bash
+
+ composer require nyholm/psr7
+
+Next, you'll need an implementation of PSR17_. PSR17 provides the required
+factories for the HTTP protocol. In order to facilitate the customizations,
+you can either implements your own PSR17 implementation or use `loophp/psr17`_
+which provides a default one:
+
+.. code-block:: bash
+
+ composer require loophp/psr17
+
+.. _Composer: https://getcomposer.org
+.. _PSR7 implementations: https://www.php-fig.org/psr/psr-7/
+.. _many packages implementing PSR7: https://packagist.org/providers/psr/http-message-implementation
+.. _PSR17: https://www.php-fig.org/psr/psr-17/
+.. _`loophp/psr17`: https://github.com/loophp/psr17
\ No newline at end of file
diff --git a/docs/pages/requirements.rst b/docs/pages/requirements.rst
index eb77ff8..5dfcfab 100644
--- a/docs/pages/requirements.rst
+++ b/docs/pages/requirements.rst
@@ -4,7 +4,7 @@ Requirements
PHP
---
-PHP greater than 7.1 is required for this library.
+PHP >= 7.4 is required for this library.
PHP Extensions
--------------
@@ -24,13 +24,11 @@ class.
+------------------+-----------+---------------------------------+------------------------+
| Dependency | PSR | Implementations | Example package |
+==================+===========+=================================+========================+
-| Logger | `PSR-3`_ | `log-implementation`_ | `monolog/monolog`_ |
-+------------------+-----------+---------------------------------+------------------------+
| Cache | `PSR-6`_ | `cache-implementation`_ | `symfony/cache`_ |
+------------------+-----------+---------------------------------+------------------------+
-| Server request | `PSR-7`_ | `http-message-implementations`_ | `nyholm/psr7-server`_ |
+| HTTP Message | `PSR-7`_ | `http-message-implementations`_ | `nyholm/psr7`_ |
+------------------+-----------+---------------------------------+------------------------+
-| HTTP factories | `PSR-17`_ | `http-factory-implementations`_ | `nyholm/psr7`_ |
+| HTTP Factory | `PSR-17`_ | `http-factory-implementations`_ | `loophp/psr17`_ |
+------------------+-----------+---------------------------------+------------------------+
| HTTP Client | `PSR-18`_ | `http-client-implementations`_ | `symfony/http-client`_ |
+------------------+-----------+---------------------------------+------------------------+
@@ -46,18 +44,15 @@ You may use custom code for that, but you can also use any of the following pack
.. _zendframework/zend-httphandlerrunner: https://packagist.org/packages/zendframework/zend-httphandlerrunner
.. _http-interop/response-sender: https://packagist.org/packages/http-interop/response-sender
-.. _monolog/monolog: https://packagist.org/packages/monolog/monolog
-.. _nyholm/psr7-server: https://packagist.org/packages/nyholm/psr7-server
.. _nyholm/psr7: https://packagist.org/packages/nyholm/psr7
+.. _loophp/psr17: https://packagist.org/packages/loophp/psr17
.. _symfony/cache: https://packagist.org/packages/symfony/cache
.. _symfony/http-client: https://packagist.org/packages/symfony/http-client
.. _cache-implementation: https://packagist.org/providers/psr/cache-implementation
.. _http-client-implementations: https://packagist.org/providers/psr/http-client-implementation
.. _http-factory-implementations: https://packagist.org/providers/psr/http-factory-implementation
.. _http-message-implementations: https://packagist.org/providers/psr/http-message-implementation
-.. _log-implementation: https://packagist.org/providers/psr/log-implementation
.. _PSR-17: https://www.php-fig.org/psr/psr-17/
.. _PSR-18: https://www.php-fig.org/psr/psr-18/
-.. _PSR-3: https://www.php-fig.org/psr/psr-3/
.. _PSR-6: https://www.php-fig.org/psr/psr-6/
.. _PSR-7: https://www.php-fig.org/psr/psr-7/
diff --git a/docs/pages/tests.rst b/docs/pages/tests.rst
index 2866c13..7083409 100644
--- a/docs/pages/tests.rst
+++ b/docs/pages/tests.rst
@@ -1,57 +1,17 @@
Tests, code quality and code style
==================================
-Every time changes are introduced into the library, `Travis CI`_ and `Github Actions`_
-run the tests written with `PHPSpec`_.
+Every time changes are introduced into the library, the continuous integration
+system run and validate the tests.
-`PHPInfection`_ is also triggered used to ensure that your code is properly
-tested.
+A PHP quality tool, Grumphp_, is used to orchestrate all these tasks at each
+commit on the local machine, but also on the continuous integration tool in use.
-The code style is based on `PSR-12`_ plus a set of custom rules.
-Find more about the code style in use in the package `drupol/php-conventions`_.
-
-A PHP quality tool, Grumphp_, is used to orchestrate all these tasks at each commit
-on the local machine, but also on the continuous integration tools (Travis, Github actions)
-
-To run the whole tests tasks locally, do
+To run the tests locally:
.. code-block:: bash
composer grumphp
-or
-
-.. code-block:: bash
-
- ./vendor/bin/grumphp run
-
-Here's an example of output that shows all the tasks that are setup in Grumphp and that
-will check your code
-
-.. code-block:: bash
-
- $ ./vendor/bin/grumphp run
- GrumPHP is sniffing your code!
- Running task 1/13: SecurityChecker... ✔
- Running task 2/13: Composer... ✔
- Running task 3/13: ComposerNormalize... ✔
- Running task 4/13: YamlLint... ✔
- Running task 5/13: JsonLint... ✔
- Running task 6/13: PhpLint... ✔
- Running task 7/13: TwigCs... ✔
- Running task 8/13: PhpCsAutoFixerV2... ✔
- Running task 9/13: PhpCsFixerV2... ✔
- Running task 10/13: Phpcs... ✔
- Running task 11/13: PhpStan... ✔
- Running task 12/13: Phpspec... ✔
- Running task 13/13: Infection... ✔
- $
-
-
-.. _PSR-12: https://www.php-fig.org/psr/psr-12/
-.. _drupol/php-conventions: https://github.com/drupol/php-conventions
-.. _Travis CI: https://travis-ci.org/ecphp/cas-lib/builds
-.. _Github Actions: https://github.com/ecphp/cas-lib/actions
-.. _PHPSpec: http://www.phpspec.net/
-.. _PHPInfection: https://github.com/infection/infection
-.. _Grumphp: https://github.com/phpro/grumphp
\ No newline at end of file
+.. _ecphp/php-conventions: https://github.com/ecphp/php-conventions
+.. _Grumphp: https://github.com/phpro/grumphp
diff --git a/docs/pages/usage.rst b/docs/pages/usage.rst
index e0fe877..1875fe3 100644
--- a/docs/pages/usage.rst
+++ b/docs/pages/usage.rst
@@ -1,15 +1,19 @@
Usage
=====
-Apereo_ already provides a demo CAS server without no proxy authentication mechanism enabled.
+Apereo_ already provides a demo CAS server without no proxy authentication
+mechanism enabled.
-In order to test the libraries here, I've setup another `CAS server with Proxy authentication enabled`_ this time.
+In order to test the libraries here, I've setup another
+`CAS server with Proxy authentication enabled`_ this time.
Feel free to use it for your tests.
-.. warning:: If your client application is not hosted on a public server and in HTTPS, this won't work.
+.. warning:: If your client application is not hosted on a public server and in
+ HTTPS, this won't work.
-.. tip:: See more on the page :ref:`development`. if you want to have your own local CAS server.
+.. tip:: See more on the page :ref:`development`. if you want to have your own
+ local CAS server.
The test login is `casuser`, password is: `Mellon`
@@ -24,16 +28,16 @@ Test `the bare PHP demo application`_ now.
Symfony
-------
-The CAS Lib library can be used in a Symfony (4 or 5) project through the package `ecphp/cas-bundle`_
+The CAS Lib library can be used in a Symfony project through the package `ecphp/cas-bundle`_
-Test `the Symfony bundle demo application`_ now.
+Test `the Symfony demo application`_ now.
See `the documentation of the ecphp/cas-bundle`_ for more information.
.. _Apereo: https://www.apereo.org/
.. _ecphp/cas-bundle: https://github.com/ecphp/cas-bundle
.. _the documentation of the ecphp/cas-bundle: http://github.com/ecphp/cas-bundle
-.. _the Symfony bundle demo application: https://cas-bundle-demo.herokuapp.com/
+.. _the Symfony demo application: https://cas-bundle-demo.herokuapp.com/
.. _CAS server with Proxy authentication enabled: https://heroku-cas-server.herokuapp.com/cas/login
.. _drupol/psrcas-client-poc: https://github.com/drupol/psrcas-client-poc/
.. _the bare PHP demo application: https://psrcas-php-demo.herokuapp.com/
diff --git a/spec/EcPhp/CasLib/Cas.php b/spec/EcPhp/CasLib/Cas.php
index 78e4074..433b8f1 100644
--- a/spec/EcPhp/CasLib/Cas.php
+++ b/spec/EcPhp/CasLib/Cas.php
@@ -12,66 +12,56 @@
namespace spec\EcPhp\CasLib;
use EcPhp\CasLib\Configuration\Properties as CasProperties;
+use Exception;
use PhpSpec\ObjectBehavior;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
-use tests\EcPhp\CasLib\Exception\TestClientException;
+use Symfony\Contracts\HttpClient\ResponseInterface;
class Cas extends ObjectBehavior
{
public static function getHttpClientMock()
{
- $callback = static function ($method, $url, $options) {
+ $callback = static function ($method, $url, $options): ResponseInterface {
$body = '';
- $info = [];
+ $info = [
+ 'response_headers' => [
+ 'Content-Type' => 'application/xml',
+ ],
+ ];
switch ($url) {
- case 'http://local/cas/serviceValidate?service=service&ticket=ticket':
- case 'http://local/cas/serviceValidate?ticket=ST-ticket&service=http%3A%2F%2Ffrom':
- case 'http://local/cas/serviceValidate?ticket=ST-ticket&service=http%3A%2F%2Flocal%2Fcas%2FserviceValidate%3Fservice%3Dservice':
- case 'http://local/cas/serviceValidate?ticket=PT-ticket&service=http%3A%2F%2Flocal%2Fcas%2FproxyValidate%3Fservice%3Dservice':
- case 'http://local/cas/serviceValidate?ticket=PT-ticket&service=http%3A%2F%2Ffrom':
- $body = <<< 'EOF'
-
-
- username
-
-
- EOF;
-
- break;
-
- case 'http://local/cas/serviceValidate?service=service&ticket=ticket-failure':
+ case 'http://local/cas/proxyValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_get_credentials_with_pgtUrl%2Fmissing_pgt':
+ case 'http://from/it_can_detect_a_wrong_proxy_response':
+ case 'http://local/cas/serviceValidate?format=XML&service=http%3A%2F%2Ffrom&ticket=ST-TICKET-VALID':
+ case 'http://local/cas/serviceValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_test_the_proxy_mode_without_pgtUrl&ticket=ST-TICKET-VALID':
+ case 'http://local/cas/serviceValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_get_credentials_without_pgtUrl':
+ case 'http://local/cas/serviceValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_validate_a_service_ticket':
$body = <<< 'EOF'
-
-
-
-
+
+
+ username
+
+
EOF;
break;
- case 'http://local/cas/proxyValidate?service=service&ticket=ticket':
- case 'http://local/cas/proxyValidate?ticket=PT-ticket&service=http%3A%2F%2Ffrom':
- case 'http://local/cas/proxyValidate?ticket=ST-ticket&service=http%3A%2F%2Ffrom':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Flocal%2Fcas%2FproxyValidate%3Fservice%3Dservice&ticket=ticket':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Flocal%2Fcas%2FproxyValidate%3Fservice%3Dservice%26renew%3Dtrue&ticket=ticket&renew=true':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Flocal%2Fcas%2FserviceValidate%3Fservice%3Dservice&ticket=ticket':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Flocal%2Fcas%2FserviceValidate%3Fservice%3Dservice%26renew%3Dtrue&ticket=ticket&renew=true':
+ case 'http://local/cas/serviceValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_validate_a_bad_service_validate_request&ticket=ST-TICKET-INVALID':
$body = <<< 'EOF'
-
- username
-
- http://app/proxyCallback.php
-
-
+
+ service and ticket parameters are both required
+
EOF;
break;
- case 'http://local/cas/serviceValidate?ticket=ST-ticket-pgt&service=http%3A%2F%2Ffrom':
+ case 'http://local/cas/proxyValidate?format=XML&service=http%3A%2F%2Ffrom&ticket=ST-TICKET-VALID':
+ case 'http://local/cas/proxyValidate?format=XML&service=http%3A%2F%2Ffrom&ticket=PT-TICKET-VALID':
+ case 'http://local/cas/proxyValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_test_the_proxy_mode_with_pgtUrl&ticket=ST-TICKET-VALID':
+ case 'http://local/cas/proxyValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_get_credentials_with_pgtUrl':
$body = <<< 'EOF'
@@ -83,49 +73,13 @@ public static function getHttpClientMock()
break;
- case 'http://local/cas/serviceValidate?ticket=ST-ticket-pgt-pgtiou-not-found&service=http%3A%2F%2Ffrom':
- $body = <<< 'EOF'
-
-
- username
- unknownPgtIou
-
-
- EOF;
-
- break;
-
- case 'http://local/cas/proxyValidate?ticket=ST-ticket-pgt-pgtiou-pgtid-null&service=http%3A%2F%2Ffrom':
- $body = <<< 'EOF'
-
-
- username
- pgtIouWithPgtIdNull
-
-
- EOF;
+ case 'http://local/cas/serviceValidate?format=JSON&service=http%3A%2F%2Ffrom%2Fit_can_parse_json_in_a_response':
+ $info = [
+ 'response_headers' => [
+ 'Content-Type' => 'application/json',
+ ],
+ ];
- break;
-
- case 'http://local/cas/proxyValidate?service=service&ticket=ST-ticket-pgt':
- case 'http://local/cas/proxyValidate?ticket=ST-ticket-pgt&service=http%3A%2F%2Ffrom':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Ffrom&ticket=PT-ticket':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Flocal%2Fcas%2FproxyValidate%3Fservice%3Dhttp%253A%252F%252Ffrom&ticket=PT-ticket-pgt':
- $body = <<< 'EOF'
-
-
- username
- pgtIou
-
- http://app/proxyCallback.php
-
-
-
- EOF;
-
- break;
-
- case 'http://local/cas/serviceValidate?service=http%3A%2F%2Flocal%2Fcas%2FserviceValidate%3Fservice%3Dservice%26format%3DJSON&ticket=ticket&format=JSON':
$body = <<< 'EOF'
{
"serviceResponse": {
@@ -138,7 +92,10 @@ public static function getHttpClientMock()
break;
- case 'http://local/cas/proxy?targetService=targetService&pgt=pgt':
+ case 'http://local/cas/proxy?service=service-valid':
+ case 'http://local/cas/serviceValidate?format=XML&service=http%3A%2F%2Ffrom%2Fit_can_detect_when_response_type_is_invalid&ticket=ST-TICKET-VALID':
+ case 'http://from/it_can_request_a_proxy_ticket':
+ case 'http://from/it_can_parse_a_good_proxy_request_response':
$body = <<< 'EOF'
-
-
- TODO: Find something to put here.
-
-
- EOF;
-
- break;
-
- case 'http://local/cas/serviceValidate?service=http%3A%2F%2Ffrom&ticket=BAD-http-query':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Ffrom&ticket=BAD-http-query':
- case 'http://local/cas/proxyValidate?service=http%3A%2F%2Flocal%2Fcas%2FproxyValidate%3Fservice%3Dservice%26error%3DTestClientException&ticket=ticket&error=TestClientException':
- case 'http://local/cas/proxy?targetService=targetService&pgt=pgt&error=TestClientException':
- throw new TestClientException();
+ default:
+ throw new Exception(sprintf('URL %s is not defined in the HTTP mock client.', $url));
break;
}
@@ -188,48 +128,24 @@ public static function getTestProperties(): CasProperties
'protocol' => [
'login' => [
'path' => '/login',
- 'allowed_parameters' => [
- 'service',
- 'custom',
- 'renew',
- 'gateway',
- ],
],
'logout' => [
'path' => '/logout',
- 'allowed_parameters' => [
- 'service',
- 'custom',
- ],
],
'serviceValidate' => [
'path' => '/serviceValidate',
- 'allowed_parameters' => [
- 'ticket',
- 'service',
- 'custom',
- ],
'default_parameters' => [
'format' => 'XML',
],
],
'proxyValidate' => [
'path' => '/proxyValidate',
- 'allowed_parameters' => [
- 'ticket',
- 'service',
- 'custom',
- ],
'default_parameters' => [
'format' => 'XML',
],
],
'proxy' => [
'path' => '/proxy',
- 'allowed_parameters' => [
- 'targetService',
- 'pgt',
- ],
],
],
]);
diff --git a/spec/EcPhp/CasLib/CasSpec.php b/spec/EcPhp/CasLib/CasSpec.php
index ac2c29c..ebb4e02 100644
--- a/spec/EcPhp/CasLib/CasSpec.php
+++ b/spec/EcPhp/CasLib/CasSpec.php
@@ -13,26 +13,25 @@
use EcPhp\CasLib\Cas;
use EcPhp\CasLib\Configuration\Properties as CasProperties;
-use EcPhp\CasLib\Introspection\Introspector;
-use EcPhp\CasLib\Introspection\ServiceValidate;
+use EcPhp\CasLib\Exception\CasException;
+use EcPhp\CasLib\Exception\CasExceptionInterface;
+use EcPhp\CasLib\Exception\CasHandlerException;
+use EcPhp\CasLib\Response\CasResponseBuilder;
+use EcPhp\CasLib\Response\Factory\AuthenticationFailureFactory;
+use EcPhp\CasLib\Response\Factory\ProxyFactory;
+use EcPhp\CasLib\Response\Factory\ProxyFailureFactory;
+use EcPhp\CasLib\Response\Factory\ServiceValidateFactory;
+use EcPhp\CasLib\Utils\Uri as UtilsUri;
+use Ergebnis\Http\Method;
use Exception;
-use InvalidArgumentException;
+use loophp\psr17\Psr17;
use Nyholm\Psr7\Factory\Psr17Factory;
-use Nyholm\Psr7\Response;
use Nyholm\Psr7\ServerRequest;
use Nyholm\Psr7\Uri;
-use Nyholm\Psr7Server\ServerRequestCreator;
use PhpSpec\ObjectBehavior;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
-use Psr\Http\Client\ClientInterface;
-use Psr\Http\Message\RequestFactoryInterface;
-use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Message\StreamFactoryInterface;
-use Psr\Http\Message\UriFactoryInterface;
-use Psr\Log\LoggerInterface;
use spec\EcPhp\CasLib\Cas as CasSpecUtils;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\HttpClient\Psr18Client;
@@ -50,165 +49,102 @@ class CasSpec extends ObjectBehavior
protected $cacheItem;
/**
- * @var \Psr\Log\LoggerInterface
- */
- protected $logger;
-
- public function it_can_authenticate()
- {
- $request = new ServerRequest('GET', 'http://from?ticket=ST-TICKET');
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
-
- $request = new ServerRequest('GET', 'http://from?ticket=ST-ticket');
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeArray();
-
- $request = new ServerRequest('GET', 'http://from?ticket=FOO-TICKET');
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
-
- $request = new ServerRequest('GET', 'http://from?ticket=ST-INVALID-JSON&format=JSON');
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
- }
-
- /**
- * @param \PhpSpec\Wrapper\Collaborator|\Psr\Http\Message\ServerRequestInterface $serverRequest
- * @param \PhpSpec\Wrapper\Collaborator|\Psr\Http\Client\ClientInterface $client
- * @param \PhpSpec\Wrapper\Collaborator|\Psr\Http\Message\UriFactoryInterface $uriFactory
- * @param \PhpSpec\Wrapper\Collaborator|\Psr\Http\Message\RequestFactoryInterface $requestFactory
- * @param \PhpSpec\Wrapper\Collaborator|\Psr\Http\Message\ResponseFactoryInterface $responseFactory
- * @param \PhpSpec\Wrapper\Collaborator|\Psr\Http\Message\StreamFactoryInterface $streamFactory
* @param \PhpSpec\Wrapper\Collaborator|\Psr\Cache\CacheItemPoolInterface $cache
- * @param \PhpSpec\Wrapper\Collaborator|\Psr\Log\LoggerInterface $logger
*
* @throws \Psr\Cache\InvalidArgumentException
*/
- public function it_can_authenticate_a_request(ServerRequestInterface $serverRequest, ClientInterface $client, UriFactoryInterface $uriFactory, RequestFactoryInterface $requestFactory, ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, CacheItemPoolInterface $cache, LoggerInterface $logger)
+ public function it_can_authenticate_a_request(CacheItemPoolInterface $cache)
{
$psr17Factory = new Psr17Factory();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
- $cacheItem = new CacheItem();
- $cacheItem->set('pgtId');
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- //$logger = new Logger('psrcas', [new StreamHandler('php://stderr')]);
-
- $uri = new Uri('http://from?ticket=ST-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket']);
-
- $this->beConstructedWith($request, CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $this
- ->authenticate()
- ->shouldBeArray();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ CasSpecUtils::getTestProperties(),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
+ );
- $uri = new Uri('http://from?ticket=foo');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'foo']);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from?ticket=ST-TICKET-INVALID'
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
+ ->shouldThrow(CasException::class)
+ ->during('authenticate', [$request]);
- $uri = new Uri('http://from?ticket=PT-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'PT-ticket']);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from?ticket=ST-TICKET-VALID'
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
+ ->authenticate($request)
->shouldBeArray();
- $uri = new Uri('http://from');
- $request = new ServerRequest('GET', $uri);
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
-
- $uri = new Uri('http://from');
- $request = new ServerRequest('GET', $uri);
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
-
- $uri = new Uri('http://from?ticket=ST-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket']);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-TICKET-VALID']
+ )
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
+ ->authenticate($request)
->shouldBeArray();
- $uri = new Uri('http://from?ticket=ST-FOO');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-FOO']);
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
-
- $uri = new Uri('http://from?ticket=ST-ticket-pgt');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket-pgt']);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-TICKET-INVALID']
+ )
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeArray();
+ ->shouldThrow(Exception::class)
+ ->during('authenticate', [$request]);
- $uri = new Uri('http://from?ticket=ST-ticket-pgt-pgtiou-not-found');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket-pgt-pgtiou-not-found']);
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from')
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('authenticate', [$request]);
- $uri = new Uri('http://from?ticket=ST-ticket-pgt-pgtiou-pgtid-null');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket-pgt-pgtiou-pgtid-null']);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-TICKET-VALID']
+ )
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
+ ->authenticate($request)
+ ->shouldBeEqualTo([
+ 'serviceResponse' => [
+ 'authenticationSuccess' => [
+ 'user' => 'username',
+ ],
+ ],
+ ]);
}
- public function it_can_authenticate_a_request_in_proxy_mode(ServerRequestInterface $serverRequest, ClientInterface $client, UriFactoryInterface $uriFactory, RequestFactoryInterface $requestFactory, ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, CacheItemPoolInterface $cache, LoggerInterface $logger)
+ public function it_can_authenticate_a_request_in_proxy_mode(CacheItemPoolInterface $cache)
{
$psr17Factory = new Psr17Factory();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
$cacheItem = new CacheItem();
$cacheItem->set('pgtId');
@@ -221,331 +157,156 @@ public function it_can_authenticate_a_request_in_proxy_mode(ServerRequestInterfa
->getItem('pgtIou')
->willReturn($cacheItem);
- //$logger = new Logger('psrcas', [new StreamHandler('php://stderr')]);
-
- $uri = new Uri('http://from?ticket=ST-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket']);
+ $cache
+ ->hasItem('unknownPgtIou')
+ ->willReturn(false);
- $this->beConstructedWith($request, CasSpecUtils::getTestPropertiesWithPgtUrl(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
+ $cache
+ ->hasItem('pgtIouWithPgtIdNull')
+ ->willReturn(true);
- $this
- ->authenticate()
- ->shouldBeArray();
+ $cache
+ ->getItem('pgtIouWithPgtIdNull')
+ ->willReturn(new CacheItem());
+
+ $this->beConstructedWith(
+ CasSpecUtils::getTestPropertiesWithPgtUrl(),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
+ );
- $uri = new Uri('http://from?ticket=foo');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'foo']);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from?ticket=ST-TICKET-INVALID'
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
+ ->shouldThrow(CasException::class)
+ ->during('authenticate', [$request]);
- $uri = new Uri('http://from?ticket=PT-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'PT-ticket']);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from?ticket=ST-TICKET-VALID'
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
+ ->authenticate($request)
->shouldBeArray();
- $uri = new Uri('http://from');
- $request = new ServerRequest('GET', $uri);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-TICKET-VALID']
+ )
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
+ ->authenticate($request)
+ ->shouldBeArray();
- $uri = new Uri('http://from');
- $request = new ServerRequest('GET', $uri);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-TICKET-INVALID']
+ )
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('authenticate', [$request]);
- $uri = new Uri('http://from?ticket=ST-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket']);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-TICKET-VALID']
+ )
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
+ ->authenticate($request)
->shouldBeArray();
- $uri = new Uri('http://from?ticket=ST-FOO');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-FOO']);
-
- $this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
-
- $uri = new Uri('http://from?ticket=ST-ticket-pgt');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket-pgt']);
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from')
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeArray();
+ ->shouldThrow(Exception::class)
+ ->during('authenticate', [$request]);
- $uri = new Uri('http://from?ticket=ST-ticket-pgt-pgtiou-not-found');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket-pgt-pgtiou-not-found']);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-TICKET-VALID']
+ )
+ );
$this
- ->withServerRequest($request)
- ->authenticate()
- ->shouldBeNull();
- }
-
- public function it_can_be_constructed_without_base_url(LoggerInterface $logger, CacheItemPoolInterface $cache)
- {
- $properties = new CasProperties([
- 'base_url' => '//////',
- 'protocol' => [
- 'login' => [
- 'path' => '/login',
- 'allowed_parameters' => [
- 'coin',
+ ->authenticate($request)
+ ->shouldBeEqualTo([
+ 'serviceResponse' => [
+ 'authenticationSuccess' => [
+ 'user' => 'username',
+ 'proxyGrantingTicket' => 'pgtId',
],
],
- ],
- ]);
+ ]);
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-ticket-pgt-pgtiou-not-found']
+ )
);
- $serverRequest = $creator->fromGlobals();
- $this->beConstructedWith($serverRequest, $properties, $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $request = new ServerRequest('GET', 'http://foo');
-
- $this
- ->withServerRequest($request)
- ->login()
- ->getHeaders()
- ->shouldReturn(['Location' => ['/login']]);
- }
-
- public function it_can_check_if_the_logger_works_during_a_failed_authentication_of_service_ticket(ServerRequestInterface $serverRequest, ClientInterface $client, UriFactoryInterface $uriFactory, RequestFactoryInterface $requestFactory, ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
- $cacheItem = new CacheItem();
- $cacheItem->set('pgtId');
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $uri = new Uri('http://from?ticket=BAD-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'BAD-ticket']);
-
- $this->beConstructedWith($request, CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
$this
- ->authenticate()
- ->shouldBeNull();
-
- $logger
- ->error('Unable to parse the response with the specified format {format}.', ['format' => 'XML', 'response' => ''])
- ->shouldHaveBeenCalledOnce();
-
- $logger
- ->error('Unable to parse the response during the normalization process.', ['body' => ''])
- ->shouldHaveBeenCalledOnce();
-
- $logger
- ->error('Unable to detect the response format.')
- ->shouldHaveBeenCalledOnce();
-
- $logger
- ->error('Unable to authenticate the user.')
- ->shouldHaveBeenCalledOnce();
+ ->shouldThrow(Exception::class)
+ ->during('authenticate', [$request]);
- $logger
- ->error('Unable to authenticate the request.')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_check_if_the_logger_works_during_a_failed_proxy_validate_request(ServerRequestInterface $serverRequest, ClientInterface $client, UriFactoryInterface $uriFactory, RequestFactoryInterface $requestFactory, ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
- $cacheItem = new CacheItem();
- $cacheItem->set('pgtId');
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $uri = new Uri('http://from?ticket=BAD-http-query');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'BAD-ticket']);
-
- $this->beConstructedWith($request, CasSpecUtils::getTestPropertiesWithPgtUrl(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $this
- ->requestProxyValidate()
- ->shouldBeNull();
-
- $logger
- ->error('Error during the proxy validate request.')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_check_if_the_logger_works_during_a_failed_service_validate_request(ServerRequestInterface $serverRequest, ClientInterface $client, UriFactoryInterface $uriFactory, RequestFactoryInterface $requestFactory, ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
- $cacheItem = new CacheItem();
- $cacheItem->set('pgtId');
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $uri = new Uri('http://from?ticket=BAD-http-query');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'BAD-ticket']);
-
- $this->beConstructedWith($request, CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from'),
+ ['ticket' => 'ST-ticket-pgt-pgtiou-pgtid-null']
+ )
+ );
$this
- ->requestServiceValidate()
- ->shouldBeNull();
-
- $logger
- ->error('Error during the service validate request.')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_check_if_the_logger_works_during_a_successful_authentication_of_service_ticket(ServerRequestInterface $serverRequest, ClientInterface $client, UriFactoryInterface $uriFactory, RequestFactoryInterface $requestFactory, ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
- $cacheItem = new CacheItem();
- $cacheItem->set('pgtId');
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $uri = new Uri('http://from?ticket=ST-ticket');
- $request = (new ServerRequest('GET', $uri))
- ->withQueryParams(['ticket' => 'ST-ticket']);
-
- $this->beConstructedWith($request, CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $response = $this
- ->getWrappedObject()
- ->authenticate();
-
- $logger
- ->debug('Response normalization succeeded.', ['body' => json_encode($response)])
- ->shouldHaveBeenCalledOnce();
+ ->shouldThrow(Exception::class)
+ ->during('authenticate', [$request]);
}
public function it_can_check_if_the_request_needs_authentication()
{
- $from = 'http://local/page';
- $request = new ServerRequest('GET', $from);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from'
+ );
$this
- ->withServerRequest($request)
- ->supportAuthentication()
+ ->supportAuthentication($request)
->shouldReturn(false);
- $from = 'http://local/page?ticket=ticket';
- $request = new ServerRequest('GET', $from);
+ $request = new ServerRequest(Method::GET, 'http://from?ticket=ticket');
$this
- ->withServerRequest($request)
- ->supportAuthentication()
+ ->supportAuthentication($request)
->shouldReturn(true);
}
- public function it_can_detect_the_type_of_a_response(CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $body = <<< 'EOF'
-
-
- username
-
-
- EOF;
-
- $headers = [
- 'Content-Type' => 'application/xml',
- ];
-
- $response = new Response(
- 200,
- $headers,
- $body
- );
-
- $this
- ->detect(
- $response
- )
- ->shouldReturnAnInstanceOf(ServiceValidate::class);
-
- $body = <<< 'EOF'
-
-
- username
-
-
- EOF;
-
- $headers = [
- 'Content-Type' => 'application/foo',
- ];
-
- $response = new Response(
- 200,
- $headers,
- $body
- );
-
- $this
- ->shouldThrow(InvalidArgumentException::class)
- ->during('detect', [$response]);
- }
-
public function it_can_detect_when_gateway_and_renew_are_set_together()
{
$from = 'http://local/';
@@ -555,22 +316,30 @@ public function it_can_detect_when_gateway_and_renew_are_set_together()
'gateway' => true,
];
+ $request = new ServerRequest(
+ Method::GET,
+ $from
+ );
+
$this
- ->withServerRequest(new ServerRequest('GET', $from))
- ->login($parameters)
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('login', [$request, $parameters]);
$parameters = [
'gateway' => true,
];
+ $request = new ServerRequest(
+ Method::GET,
+ $from . '?gateway=false'
+ );
+
$this
- ->withServerRequest(new ServerRequest('GET', $from . '?gateway=false'))
- ->login($parameters)
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('login', [$request, $parameters]);
}
- public function it_can_detect_wrong_url(LoggerInterface $logger, CacheItemPoolInterface $cache)
+ public function it_can_detect_wrong_url(CacheItemPoolInterface $cache)
{
$properties = new CasProperties([
'base_url' => '',
@@ -584,196 +353,149 @@ public function it_can_detect_wrong_url(LoggerInterface $logger, CacheItemPoolIn
],
]);
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ $properties,
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
);
- $serverRequest = $creator->fromGlobals();
-
- $this->beConstructedWith($serverRequest, $properties, $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
$parameters = [
'service' => 'service',
'ticket' => 'ticket',
];
+ $request = new ServerRequest(Method::GET, 'error');
+
$this
- ->withServerRequest(new ServerRequest('GET', 'error'))
- ->requestServiceValidate($parameters)
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('requestServiceValidate', [$request, $parameters]);
}
public function it_can_do_a_request_to_validate_a_ticket()
{
- $from = 'http://local/cas/serviceValidate?service=service';
- $request = new ServerRequest('GET', $from);
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_do_a_request_to_validate_a_ticket/no-ticket')
+ );
$this
- ->withServerRequest($request)
- ->requestTicketValidation()
- ->shouldBeNull();
-
- $from = 'http://local/cas/serviceValidate?service=service&ticket=ST-ticket';
- $request = new ServerRequest('GET', $from);
+ ->shouldThrow(Exception::class)
+ ->during('requestTicketValidation', [$request]);
- $this
- ->withServerRequest($request)
- ->requestTicketValidation()
- ->shouldBeAnInstanceOf(ResponseInterface::class);
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from?ticket=ST-TICKET-VALID')
+ );
- $from = 'http://local/cas/proxyValidate?service=service&ticket=PT-ticket';
- $request = new ServerRequest('GET', $from);
+ $response = $this
+ ->requestTicketValidation($request);
- $this
- ->withServerRequest($request)
- ->requestTicketValidation()
+ $response
->shouldBeAnInstanceOf(ResponseInterface::class);
- $from = 'http://local/cas/proxyValidate?service=service&ticket=bar';
- $request = new ServerRequest('GET', $from);
+ $response
+ ->shouldThrow(Exception::class)
+ ->during('getProxyGrantingTicket', [$request]);
- $this
- ->withServerRequest($request)
- ->requestTicketValidation()
- ->shouldBeNull();
-
- $from = 'http://local/cas/proxyValidate?service=service';
- $request = new ServerRequest('GET', $from);
-
- $this
- ->withServerRequest($request)
- ->requestTicketValidation()
- ->shouldBeNull();
-
- $from = 'http://local/cas/serviceValidate?service=service&ticket=ST-ticket';
- $request = new ServerRequest('GET', $from);
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from?ticket=EMPTY-BODY')
+ );
$this
- ->withServerRequest($request)
- ->requestTicketValidation(['service' => 'foo', 'ticket' => 'bar'])
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('requestTicketValidation', [$request]);
}
- public function it_can_handle_proxy_callback_request(LoggerInterface $logger, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem)
+ public function it_can_handle_proxy_callback_request()
{
- $request = new ServerRequest('GET', 'http://local/proxycallback?pgtId=pgtId&pgtIou=false');
-
- $this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
-
- $this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->getStatusCode()
- ->shouldReturn(500);
-
- $request = new ServerRequest('GET', 'http://local/proxycallback?pgtIou=pgtIou&pgtId=pgtId');
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://local/proxycallback?pgtId=pgtId&pgtIou=pgtIou'
+ );
$this
- ->withServerRequest($request)
- ->handleProxyCallback()
+ ->handleProxyCallback($request)
->shouldReturnAnInstanceOf(ResponseInterface::class);
$this
- ->withServerRequest($request)
- ->handleProxyCallback()
+ ->handleProxyCallback($request)
->getStatusCode()
->shouldReturn(200);
- $request = new ServerRequest('GET', 'http://local/proxycallback?pgtId=pgtId');
-
- $this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://local/proxycallback?pgtId=pgtId&pgtIou=false'
+ );
$this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->getStatusCode()
- ->shouldReturn(500);
-
- $request = new ServerRequest('GET', 'http://local/proxycallback?pgtIou=pgtIou');
+ ->shouldThrow(Exception::class)
+ ->during('handleProxyCallback', [$request]);
- $this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://local/proxycallback?pgtId=pgtId'
+ );
$this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->getStatusCode()
- ->shouldReturn(500);
+ ->shouldThrow(Exception::class)
+ ->during('handleProxyCallback', [$request]);
- $request = new ServerRequest('GET', 'http://local/proxycallback');
-
- $this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://local/proxycallback?pgtIou=pgtIou'
+ );
$this
- ->withServerRequest($request)
- ->handleProxyCallback()
- ->getStatusCode()
- ->shouldReturn(200);
-
- $request = new ServerRequest('GET', 'http://local/proxycallback?pgtId=pgtId&pgtIou=pgtIou');
+ ->shouldThrow(Exception::class)
+ ->during('handleProxyCallback', [$request]);
- $this->cache
- ->getItem('false')
- ->willThrow(new InvalidArgumentException('foo'));
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://local/proxycallback'
+ );
$this
- ->withServerRequest($request)
- ->handleProxyCallback()
+ ->handleProxyCallback($request)
->shouldReturnAnInstanceOf(ResponseInterface::class);
$this
- ->withServerRequest($request)
- ->handleProxyCallback()
+ ->handleProxyCallback($request)
->getStatusCode()
->shouldReturn(200);
-
- $response = new Response(200);
-
- $this
- ->withServerRequest($request)
- ->handleProxyCallback([], $response)
- ->shouldReturn($response);
}
public function it_can_login()
{
- $request = new ServerRequest('GET', 'http://local/', ['referer' => 'http://google.com/']);
+ $request = new ServerRequest(Method::GET, 'http://local/', ['referer' => 'http://google.com/']);
$this
- ->withServerRequest($request)
- ->login()
+ ->login($request)
->shouldReturnAnInstanceOf(ResponseInterface::class);
$this
- ->withServerRequest($request)
- ->login()
+ ->login($request)
->getStatusCode()
->shouldReturn(302);
- $request = new ServerRequest('GET', 'http://local/');
+ $request = new ServerRequest(Method::GET, 'http://local/');
$this
- ->withServerRequest($request)
- ->login()
+ ->login($request)
->getHeader('Location')
->shouldReturn(['http://local/cas/login?service=http%3A%2F%2Flocal%2F']);
- $request = new ServerRequest('GET', 'http://local/');
+ $request = new ServerRequest(Method::GET, 'http://local/');
$parameters = [
'foo' => 'bar',
@@ -781,22 +503,20 @@ public function it_can_login()
];
$this
- ->withServerRequest($request)
- ->login($parameters)
+ ->login($request, $parameters)
->getHeader('Location')
- ->shouldReturn(['http://local/cas/login?service=http%3A%2F%2Ffoo.bar%2F']);
+ ->shouldReturn(['http://local/cas/login?foo=bar&service=http%3A%2F%2Ffoo.bar%2F']);
$parameters = [
'custom' => 'foo',
];
$this
- ->withServerRequest($request)
- ->login($parameters)
+ ->login($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/login?custom=foo&service=http%3A%2F%2Flocal%2F']);
- $request = new ServerRequest('GET', 'http://local/', ['referer' => 'http://referer/']);
+ $request = new ServerRequest(Method::GET, 'http://local/', ['referer' => 'http://referer/']);
$parameters = [
'foo' => 'bar',
@@ -804,18 +524,16 @@ public function it_can_login()
];
$this
- ->withServerRequest($request)
- ->login($parameters)
+ ->login($request, $parameters)
->getHeader('Location')
- ->shouldReturn(['http://local/cas/login?service=http%3A%2F%2Ffoo.bar%2F']);
+ ->shouldReturn(['http://local/cas/login?foo=bar&service=http%3A%2F%2Ffoo.bar%2F']);
$parameters = [
'custom' => 'foo',
];
$this
- ->withServerRequest($request)
- ->login($parameters)
+ ->login($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/login?custom=foo&service=http%3A%2F%2Flocal%2F']);
@@ -825,30 +543,26 @@ public function it_can_login()
];
$this
- ->withServerRequest($request)
- ->login($parameters)
+ ->login($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/login?custom=foo']);
}
public function it_can_logout()
{
- $request = new ServerRequest('GET', 'http://local/');
+ $request = new ServerRequest(Method::GET, 'http://local/');
$this
- ->withServerRequest($request)
- ->logout()
+ ->logout($request)
->shouldReturnAnInstanceOf(ResponseInterface::class);
$this
- ->withServerRequest($request)
- ->logout()
+ ->logout($request)
->getStatusCode()
->shouldReturn(302);
$this
- ->withServerRequest($request)
- ->logout()
+ ->logout($request)
->getHeader('Location')
->shouldReturn(['http://local/cas/logout']);
@@ -857,8 +571,7 @@ public function it_can_logout()
];
$this
- ->withServerRequest($request)
- ->logout($parameters)
+ ->logout($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/logout?custom=bar']);
@@ -868,20 +581,18 @@ public function it_can_logout()
];
$this
- ->withServerRequest($request)
- ->logout($parameters)
+ ->logout($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/logout?custom=bar&service=http%3A%2F%2Fcustom.local%2F']);
- $request = new ServerRequest('GET', 'http://local/', ['referer' => 'http://referer/']);
+ $request = new ServerRequest(Method::GET, 'http://local/', ['referer' => 'http://referer/']);
$parameters = [
'custom' => 'bar',
];
$this
- ->withServerRequest($request)
- ->logout($parameters)
+ ->logout($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/logout?custom=bar']);
@@ -891,8 +602,7 @@ public function it_can_logout()
];
$this
- ->withServerRequest($request)
- ->logout($parameters)
+ ->logout($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/logout?custom=bar&service=http%3A%2F%2Fcustom.local%2F']);
@@ -901,72 +611,17 @@ public function it_can_logout()
];
$this
- ->withServerRequest($request)
- ->logout($parameters)
+ ->logout($request, $parameters)
->shouldReturnAnInstanceOf(ResponseInterface::class);
}
- public function it_can_parse_a_bad_proxy_request_response(CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $serverRequest = $creator->fromGlobals();
- $this->beConstructedWith($serverRequest, CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $url = 'http://from';
-
- $this
- ->withServerRequest(new ServerRequest('GET', $url))
- ->requestProxyTicket(['targetService' => 'targetService', 'pgt' => 'pgt-error-in-getCredentials'])
- ->shouldBeNull();
-
- $logger
- ->error('Unable to authenticate the user.')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_parse_a_good_proxy_request_response(CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $serverRequest = $creator->fromGlobals();
- $this->beConstructedWith($serverRequest, CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $url = 'http://from';
-
- $this
- ->withServerRequest(new ServerRequest('GET', $url))
- ->requestProxyTicket(['targetService' => 'targetService', 'pgt' => 'pgt'])
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $logger
- ->error('Unable to authenticate the user.')
- ->shouldNotBeCalled();
- }
-
- public function it_can_parse_json_in_a_response(LoggerInterface $logger, CacheItemPoolInterface $cache)
+ public function it_can_parse_json_in_a_response(CacheItemPoolInterface $cache)
{
$properties = new CasProperties([
'base_url' => '',
'protocol' => [
'serviceValidate' => [
'path' => 'http://local/cas/serviceValidate',
- 'allowed_parameters' => [
- 'service',
- 'ticket',
- ],
'default_parameters' => [
'format' => 'JSON',
],
@@ -974,102 +629,96 @@ public function it_can_parse_json_in_a_response(LoggerInterface $logger, CacheIt
],
]);
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ $properties,
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
);
- $serverRequest = $creator->fromGlobals();
- $this->beConstructedWith($serverRequest, $properties, $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
- $request = new ServerRequest('GET', 'http://local/cas/serviceValidate?service=service&ticket=ticket&format=JSON');
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_parse_json_in_a_response')
+ );
$this
- ->withServerRequest($request)
- ->requestServiceValidate()
+ ->requestServiceValidate($request)
->shouldReturnAnInstanceOf(ResponseInterface::class);
}
public function it_can_renew_login()
{
- $from = 'http://local/';
-
- $request = new ServerRequest('GET', $from);
+ $request = new ServerRequest(Method::GET, 'http://local/');
$parameters = [
'renew' => true,
];
$this
- ->withServerRequest($request)
- ->login($parameters)
+ ->login($request, $parameters)
->getHeader('Location')
->shouldReturn(['http://local/cas/login?renew=true&service=http%3A%2F%2Flocal%2F']);
- $request = new ServerRequest('GET', $from . '?renew=false');
-
- $parameters = [
- 'renew' => true,
- ];
+ $request = new ServerRequest(Method::GET, 'http://local/?renew=false');
$this
- ->withServerRequest($request)
- ->login($parameters)
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('login', [$request, $parameters]);
}
- public function it_can_request_a_proxy_ticket(LoggerInterface $logger, CacheItemPoolInterface $cache)
+ public function it_can_request_a_proxy_ticket(CacheItemPoolInterface $cache)
{
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ CasSpecUtils::getTestProperties(),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
);
- $serverRequest = $creator->fromGlobals();
- //$logger = new Logger('psrcas', [new StreamHandler('php://stderr')]);
-
- $this->beConstructedWith($serverRequest, CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $url = 'http://from';
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_request_a_proxy_ticket')
+ );
$this
- ->withServerRequest(new ServerRequest('GET', $url))
- ->requestProxyTicket(['targetService' => 'targetService', 'pgt' => 'pgt'])
+ ->requestProxyTicket($request, ['service' => 'service-valid'])
->shouldBeAnInstanceOf(ResponseInterface::class);
- $url = 'http://from?error=TestClientException';
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_request_a_proxy_ticket')
+ );
$this
- ->withServerRequest(new ServerRequest('GET', $url))
- ->requestProxyTicket(['targetService' => 'targetService', 'pgt' => 'pgt'])
- ->shouldBeNull();
-
- $logger
- ->error('Error during the proxy ticket request.')
- ->shouldHaveBeenCalledOnce();
+ ->shouldThrow(Exception::class)
+ ->during('requestProxyTicket', [$request, ['service' => 'service-invalid']]);
}
- public function it_can_validate_a_bad_proxy_ticket(LoggerInterface $logger, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem)
+ public function it_can_validate_a_bad_proxy_ticket(CacheItemPoolInterface $cache)
{
$properties = new CasProperties([
'base_url' => '',
'protocol' => [
'proxyValidate' => [
'path' => 'http://local/cas/proxyValidate',
- 'allowed_parameters' => [
- 'service',
- 'ticket',
- 'http_code',
- 'invalid_xml',
- 'unrelated_xml',
- ],
'default_parameters' => [
'format' => 'XML',
],
@@ -1077,351 +726,165 @@ public function it_can_validate_a_bad_proxy_ticket(LoggerInterface $logger, Cach
],
]);
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $psr17 = new Psr17(
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory
);
- $serverRequest = $creator->fromGlobals();
-
- $this->beConstructedWith($serverRequest, $properties, $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
- $request = new ServerRequest('POST', 'foo');
-
- $this
- ->withServerRequest($request)
- ->requestProxyValidate()
- ->shouldBeNull();
+ $this->beConstructedWith(
+ $properties,
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
+ );
- $url = 'http://local/cas/proxyValidate?service=service&ticket=ticket&error=TestClientException';
+ $request = new ServerRequest(
+ Method::POST,
+ 'http://from/it_can_validate_a_bad_proxy_ticket'
+ );
$this
- ->withServerRequest(new ServerRequest('GET', $url))
- ->requestProxyValidate()
- ->shouldBeNull();
-
- $logger
- ->error('Unable to authenticate the user.')
- ->shouldHaveBeenCalledOnce();
+ ->shouldThrow(Exception::class)
+ ->during('requestServiceValidate', [$request]);
}
- public function it_can_validate_a_bad_service_validate_request(LoggerInterface $logger, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem)
+ public function it_can_validate_a_bad_service_validate_request(CacheItemPoolInterface $cache)
{
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ CasSpecUtils::getTestProperties(),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
);
- $this->beConstructedWith($creator->fromGlobals(), CasSpecUtils::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
- $from = 'http://from/';
-
- $parameters = [
- 'service' => 'service',
- 'ticket' => 'ticket-failure',
- ];
-
- $request = new ServerRequest('GET', $from);
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from/it_can_validate_a_bad_service_validate_request'
+ );
$this
- ->withServerRequest($request)
- ->requestServiceValidate($parameters)
- ->shouldBeNull();
-
- $logger
- ->error('Unable to authenticate the user.')
- ->shouldHaveBeenCalledOnce();
+ ->shouldThrow(CasHandlerException::class)
+ ->during(
+ 'requestServiceValidate',
+ [
+ $request,
+ ['ticket' => 'ST-TICKET-INVALID'],
+ ]
+ );
}
- public function it_can_validate_a_good_proxy_ticket(LoggerInterface $logger, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem)
+ public function it_can_validate_a_service_ticket()
{
- $properties = new CasProperties([
- 'base_url' => '',
- 'protocol' => [
- 'proxyValidate' => [
- 'path' => 'http://local/cas/proxyValidate',
- 'allowed_parameters' => [
- 'service',
- 'ticket',
- 'http_code',
- 'invalid_xml',
- 'unrelated_xml',
- ],
- 'default_parameters' => [
- 'format' => 'XML',
- ],
- ],
- ],
- ]);
-
- $cacheItem
- ->get()
- ->willReturn('pgtIou');
-
- $cacheItem
- ->set('pgtId')
- ->willReturn($cacheItem);
-
- $cacheItem
- ->expiresAfter(300)
- ->willReturn($cacheItem);
-
- $cache
- ->save($cacheItem)
- ->willReturn(true);
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->hasItem('pgtIouInvalid')
- ->willReturn(false);
-
- // See: https://github.com/phpspec/prophecy/pull/429
- $cache
- ->hasItem('false')
- ->willThrow(new InvalidArgumentException('foo'));
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_validate_a_service_ticket')
);
- $serverRequest = $creator->fromGlobals();
-
- //$logger = new Logger('psrcas', [new StreamHandler('php://stderr')]);
-
- $this->beConstructedWith($serverRequest, $properties, $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $request = new ServerRequest('GET', 'http://local/cas/proxyValidate?service=service&ticket=ticket');
$this
- ->withServerRequest($request)
- ->requestProxyValidate()
+ ->requestServiceValidate($request)
->shouldReturnAnInstanceOf(ResponseInterface::class);
$this
- ->withServerRequest($request)
- ->requestProxyValidate()
+ ->requestServiceValidate($request)
->getStatusCode()
->shouldReturn(200);
$this
- ->withServerRequest($request)
- ->requestProxyValidate()
+ ->requestServiceValidate($request)
->shouldReturnAnInstanceOf(ResponseInterface::class);
- $request = new ServerRequest('GET', 'http://local/cas/proxyValidate?service=service&ticket=ticket&renew=true');
-
- $this
- ->withServerRequest($request)
- ->requestProxyValidate()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
-
- $url = 'http://local/cas/proxyValidate?ticket=PT-ticket-pgt&service=http%3A%2F%2Ffrom';
-
- $this
- ->withServerRequest(new ServerRequest('GET', $url))
- ->requestProxyValidate()
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $logger
- ->error('Unable to authenticate the user.')
- ->shouldNotHaveBeenCalled();
- }
-
- public function it_can_validate_a_good_service_validate_request(LoggerInterface $logger, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem)
- {
- $properties = new CasProperties([
- 'base_url' => '',
- 'protocol' => [
- 'serviceValidate' => [
- 'path' => 'http://local/cas/serviceValidate',
- 'allowed_parameters' => [
- 'service',
- 'ticket',
- 'http_code',
- 'invalid_xml',
- 'with_pgt',
- 'pgt_valid',
- 'pgt_is_not_string',
- ],
- 'default_parameters' => [
- 'format' => 'XML',
- ],
- ],
- ],
- ]);
-
- $cacheItem
- ->set('pgtId')
- ->willReturn($cacheItem);
-
- $cacheItem
- ->expiresAfter(300)
- ->willReturn($cacheItem);
-
- $cache
- ->save($cacheItem)
- ->willReturn(true);
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->hasItem('pgtIouInvalid')
- ->willReturn(false);
-
- // See: https://github.com/phpspec/prophecy/pull/429
- $cache
- ->hasItem('false')
- ->willThrow(new InvalidArgumentException('foo'));
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_validate_a_service_ticket/404')
);
- $this->beConstructedWith($creator->fromGlobals(), $properties, $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $from = 'http://local/';
-
- $request = new ServerRequest('GET', $from);
-
- $parameters = [
- 'service' => 'service',
- 'ticket' => 'ticket',
- ];
$this
- ->withServerRequest($request)
- ->requestServiceValidate($parameters)
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $logger
- ->error('Unable to authenticate the user.')
- ->shouldNotHaveBeenCalled();
+ ->shouldThrow(Exception::class)
+ ->during('requestServiceValidate', [$request]);
}
- public function it_can_validate_a_service_ticket()
+ public function it_can_validate_any_type_of_ticket()
{
- $request = new ServerRequest('GET', 'http://local/cas/serviceValidate?service=service&ticket=ticket');
+ $request = new ServerRequest(Method::GET, 'http://from?ticket=ST-TICKET-VALID');
$this
- ->withServerRequest($request)
- ->requestProxyValidate()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
+ ->requestTicketValidation($request)
+ ->shouldBeAnInstanceOf(ResponseInterface::class);
- $this
- ->withServerRequest($request)
- ->requestProxyValidate()
- ->getStatusCode()
- ->shouldReturn(200);
+ $request = new ServerRequest(Method::GET, 'http://from?ticket=ST-TICKET-INVALID');
$this
- ->withServerRequest($request)
- ->requestProxyValidate()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
+ ->shouldThrow(Exception::class)
+ ->during('requestTicketValidation', [$request]);
- $request = new ServerRequest('GET', 'http://local/cas/serviceValidate?service=service&ticket=ticket&http_code=404');
+ $request = new ServerRequest(Method::GET, 'http://from/it_can_validate_any_type_of_ticket/ticket-is-available-but-invalid');
$this
- ->withServerRequest($request)
- ->requestProxyValidate()
- ->shouldBeNull();
+ ->shouldThrow(CasExceptionInterface::class)
+ ->during('requestTicketValidation', [$request, ['ticket' => 'ticket-invalid']]);
- $request = new ServerRequest('GET', 'http://local/cas/serviceValidate?service=service&ticket=ticket&renew=true');
+ $request = new ServerRequest(Method::GET, 'http://from/it_can_validate_any_type_of_ticket/ticket-is-unavailable');
$this
- ->withServerRequest($request)
- ->requestProxyValidate()
- ->shouldReturnAnInstanceOf(ResponseInterface::class);
+ ->shouldThrow(CasExceptionInterface::class)
+ ->during('requestTicketValidation', [$request]);
}
- public function it_can_validate_any_type_of_ticket()
+ public function it_cannot_be_constructed_without_base_url(CacheItemPoolInterface $cache)
{
- $body = [
- 'serviceResponse' => [
- 'authenticationSuccess' => [
- 'user' => 'username',
- ],
- ],
- ];
-
- $request = new ServerRequest('GET', 'http://from?ticket=ST-TICKET');
- $response = new Response(
- 200,
- ['Content-Type' => 'application/json'],
- json_encode($body)
- );
-
- $this
- ->withServerRequest($request)
- ->requestTicketValidation([], $response)
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $body = [
- 'serviceResponse' => [
- 'authenticationSuccess' => [
- 'user' => 'username',
- 'proxyGrantingTicket' => 'pgtIou',
+ $properties = new CasProperties([
+ 'base_url' => '//////',
+ 'protocol' => [
+ 'login' => [
+ 'path' => '/login',
],
],
- ];
+ ]);
- $request = new ServerRequest('GET', 'http://from?ticket=PT-TICKET');
- $response = new Response(
- 200,
- ['Content-Type' => 'application/json'],
- json_encode($body)
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ $properties,
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
);
- $this
- ->withServerRequest($request)
- ->requestTicketValidation([], $response)
- ->shouldBeNull();
-
- $body = [
- 'serviceResponse' => [
- 'authenticationSuccess' => [
- 'user' => 'username',
- ],
- ],
- ];
-
- $request = new ServerRequest('GET', 'http://from');
- $response = new Response(
- 500,
- ['Content-Type' => 'application/json'],
- json_encode($body)
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://foo'
);
$this
- ->withServerRequest($request)
- ->requestTicketValidation([], $response)
- ->shouldBeNull();
+ ->shouldThrow(Exception::class)
+ ->during('login', [$request]);
}
public function it_is_initializable()
@@ -1429,23 +892,13 @@ public function it_is_initializable()
$this->shouldHaveType(Cas::class);
}
- public function let(LoggerInterface $logger, CacheItemPoolInterface $cache, CacheItemInterface $cacheItemPgtIou, CacheItemInterface $cacheItemPgtIdNull)
+ public function let(CacheItemPoolInterface $cache, CacheItemInterface $cacheItemPgtIou, CacheItemInterface $cacheItemPgtIdNull)
{
- $this->logger = $logger;
$this->cache = $cache;
$this->cacheItem = $cacheItemPgtIou;
- $properties = CasSpecUtils::getTestProperties();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $serverRequest = $creator->fromGlobals();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
$cacheItemPgtIou
->set('pgtId')
@@ -1499,6 +952,17 @@ public function let(LoggerInterface $logger, CacheItemPoolInterface $cache, Cach
->getItem('pgtIouWithPgtIdNull')
->willReturn($cacheItemPgtIdNull);
- $this->beConstructedWith($serverRequest, $properties, $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
+ $this->beConstructedWith(
+ CasSpecUtils::getTestProperties(),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
+ );
}
}
diff --git a/spec/EcPhp/CasLib/Handler/LoginSpec.php b/spec/EcPhp/CasLib/Handler/LoginSpec.php
new file mode 100644
index 0000000..e58c799
--- /dev/null
+++ b/spec/EcPhp/CasLib/Handler/LoginSpec.php
@@ -0,0 +1,153 @@
+ range(1, 5),
+ ];
+
+ $this->beConstructedWith(
+ $parameters,
+ $cache,
+ $casResponseBuilder,
+ new Psr18Client(Cas::getHttpClientMock()),
+ Cas::getTestProperties(),
+ $psr17
+ );
+
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_deal_with_array_parameters')
+ );
+
+ $this
+ ->handle($request)
+ ->shouldBeAnInstanceOf(ResponseInterface::class);
+
+ $this
+ ->handle($request)
+ ->getHeaderLine('Location')
+ ->shouldReturn('http://local/cas/login?custom%5B0%5D=1&custom%5B1%5D=2&custom%5B2%5D=3&custom%5B3%5D=4&custom%5B4%5D=5&service=http%3A%2F%2Ffrom%2Fit_can_deal_with_array_parameters');
+ }
+
+ public function it_can_deal_with_renew_and_gateway_parameters(CacheItemPoolInterface $cache, CasResponseBuilderInterface $casResponseBuilder)
+ {
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $parameters = [
+ 'renew' => true,
+ 'gateway' => true,
+ 'service' => 'service',
+ ];
+
+ $this->beConstructedWith(
+ $parameters,
+ $cache,
+ $casResponseBuilder,
+ new Psr18Client(Cas::getHttpClientMock()),
+ Cas::getTestProperties(),
+ $psr17
+ );
+
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_deal_with_renew_and_gateway_parameters')
+ );
+
+ $this
+ ->shouldThrow(Exception::class)
+ ->during('handle', [$request]);
+ }
+
+ public function it_can_deal_with_renew_parameter(CacheItemPoolInterface $cache, CasResponseBuilderInterface $casResponseBuilder)
+ {
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $parameters = [
+ 'renew' => 'coin',
+ 'gateway' => false,
+ ];
+
+ $this->beConstructedWith(
+ $parameters,
+ $cache,
+ $casResponseBuilder,
+ new Psr18Client(Cas::getHttpClientMock()),
+ Cas::getTestProperties(),
+ $psr17
+ );
+
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_deal_with_renew_parameter')
+ );
+
+ $this
+ ->handle($request)
+ ->shouldBeAnInstanceOf(ResponseInterface::class);
+ }
+
+ public function it_can_get_a_response()
+ {
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_deal_with_renew_parameter')
+ );
+
+ $this
+ ->handle($request)
+ ->shouldBeAnInstanceOf(ResponseInterface::class);
+ }
+
+ public function it_is_initializable()
+ {
+ $this->shouldHaveType(Login::class);
+ }
+
+ public function let(CacheItemPoolInterface $cache, CasResponseBuilderInterface $casResponseBuilder)
+ {
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ [],
+ $cache,
+ $casResponseBuilder,
+ new Psr18Client(Cas::getHttpClientMock()),
+ Cas::getTestProperties(),
+ $psr17
+ );
+ }
+}
diff --git a/spec/EcPhp/CasLib/Handler/LogoutSpec.php b/spec/EcPhp/CasLib/Handler/LogoutSpec.php
new file mode 100644
index 0000000..ae775c4
--- /dev/null
+++ b/spec/EcPhp/CasLib/Handler/LogoutSpec.php
@@ -0,0 +1,59 @@
+handle($request)
+ ->shouldBeAnInstanceOf(ResponseInterface::class);
+ }
+
+ public function it_is_initializable()
+ {
+ $this->shouldHaveType(Logout::class);
+ }
+
+ public function let(CacheItemPoolInterface $cache, CasResponseBuilderInterface $casResponseBuilder)
+ {
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ [],
+ $cache,
+ $casResponseBuilder,
+ new Psr18Client(Cas::getHttpClientMock()),
+ Cas::getTestProperties(),
+ $psr17
+ );
+ }
+}
diff --git a/spec/EcPhp/CasLib/Handler/ProxyCallbackSpec.php b/spec/EcPhp/CasLib/Handler/ProxyCallbackSpec.php
index f9b9005..a552bde 100644
--- a/spec/EcPhp/CasLib/Handler/ProxyCallbackSpec.php
+++ b/spec/EcPhp/CasLib/Handler/ProxyCallbackSpec.php
@@ -11,24 +11,38 @@
namespace spec\EcPhp\CasLib\Handler;
+use EcPhp\CasLib\Contract\Response\CasResponseBuilderInterface;
use EcPhp\CasLib\Handler\ProxyCallback;
+use EcPhp\CasLib\Utils\Uri as UtilsUri;
+use Ergebnis\Http\Method;
use Exception;
+use loophp\psr17\Psr17;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\ServerRequest;
+use Nyholm\Psr7\Uri;
use PhpSpec\ObjectBehavior;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use Psr\Log\LoggerInterface;
+use Psr\Http\Client\ClientInterface;
use spec\EcPhp\CasLib\Cas;
class ProxyCallbackSpec extends ObjectBehavior
{
- public function it_can_catch_issue_with_the_cache(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, LoggerInterface $logger)
+ public function it_can_catch_issue_with_the_cache(CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, ClientInterface $client, CasResponseBuilderInterface $casResponseBuilder)
{
$psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from?pgtId=pgtId&pgtIou=pgtIou');
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from/it_can_catch_issue_with_the_cache'),
+ [
+ 'pgtId' => 'pgtId',
+ 'pgtIou' => 'pgtIou',
+ ]
+ )
+ );
$cacheItem
->set('pgtId')
@@ -48,103 +62,31 @@ public function it_can_catch_issue_with_the_cache(ServerRequestInterface $server
->save($cacheItem)
->willReturn(true);
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle();
-
- $logger
- ->error($uniqid)
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_test_if_the_cache_is_working(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, LoggerInterface $logger)
- {
- $this
- ->handle();
-
- $cache
- ->save($cacheItem)
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_test_the_logger_when_missing_pgtId(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from?pgtIou=pgtIou');
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
+ $this->beConstructedWith([], $cache, $casResponseBuilder, $client, Cas::getTestProperties(), $psr17);
$this
- ->handle();
-
- $logger
- ->debug('Missing proxy callback parameter (pgtId).')
- ->shouldHaveBeenCalledOnce();
+ ->shouldThrow(Exception::class)
+ ->during('handle', [$request]);
}
- public function it_can_test_the_logger_when_missing_pgtIou(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, LoggerInterface $logger)
+ public function it_can_test_if_the_cache_is_working(CacheItemPoolInterface $cache, CacheItemInterface $cacheItem)
{
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from?pgtId=pgtId');
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
+ $request = new ServerRequest(
+ Method::GET,
+ UtilsUri::withParams(
+ new Uri('http://from/it_can_test_if_the_cache_is_working'),
+ [
+ 'pgtId' => 'pgtId',
+ 'pgtIou' => 'pgtIou',
+ ]
+ )
+ );
$this
- ->handle();
-
- $logger
- ->debug('Missing proxy callback parameter (pgtIou).')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_test_the_logger_when_no_parameter_is_in_the_url(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from');
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle();
-
- $logger
- ->debug('CAS server just checked the proxy callback endpoint.')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_test_the_logger_when_parameters_are_in_the_url(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from?pgtId=pgtId&pgtIou=pgtIou');
-
- $cacheItem
- ->set('pgtId')
- ->willReturn($cacheItem);
-
- $cacheItem
- ->expiresAfter(300)
- ->willReturn($cacheItem);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
+ ->handle($request);
$cache
->save($cacheItem)
- ->willReturn(true);
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle();
-
- $logger
- ->debug('Storing proxy callback parameters (pgtId and pgtIou).')
->shouldHaveBeenCalledOnce();
}
@@ -153,11 +95,10 @@ public function it_is_initializable()
$this->shouldHaveType(ProxyCallback::class);
}
- public function let(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, LoggerInterface $logger)
+ public function let(CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, ClientInterface $client, CasResponseBuilderInterface $casResponseBuilder)
{
$psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from?pgtId=pgtId&pgtIou=pgtIou');
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
$cacheItem
->set('pgtId')
@@ -175,6 +116,6 @@ public function let(ServerRequestInterface $serverRequest, CacheItemPoolInterfac
->save($cacheItem)
->willReturn(true);
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
+ $this->beConstructedWith([], $cache, $casResponseBuilder, $client, Cas::getTestProperties(), $psr17);
}
}
diff --git a/spec/EcPhp/CasLib/Handler/ProxySpec.php b/spec/EcPhp/CasLib/Handler/ProxySpec.php
new file mode 100644
index 0000000..c2563c8
--- /dev/null
+++ b/spec/EcPhp/CasLib/Handler/ProxySpec.php
@@ -0,0 +1,85 @@
+shouldThrow(Exception::class)
+ ->during('handle', [$request]);
+ }
+
+ public function it_can_detect_when_no_credentials()
+ {
+ $request = new ServerRequest(Method::GET, 'http://from');
+
+ $this
+ ->shouldThrow(Exception::class)
+ ->during('handle', [$request]);
+ }
+
+ public function it_is_initializable()
+ {
+ $this->shouldHaveType(Proxy::class);
+ }
+
+ public function let(CacheItemPoolInterface $cache)
+ {
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17(
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory,
+ $psr17Factory
+ );
+
+ $this->beConstructedWith(
+ [],
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ ),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ Cas::getTestProperties(),
+ $psr17
+ );
+ }
+}
diff --git a/spec/EcPhp/CasLib/Handler/ServiceValidateSpec.php b/spec/EcPhp/CasLib/Handler/ServiceValidateSpec.php
new file mode 100644
index 0000000..5b352e9
--- /dev/null
+++ b/spec/EcPhp/CasLib/Handler/ServiceValidateSpec.php
@@ -0,0 +1,156 @@
+shouldThrow(Exception::class)
+ ->during('handle', [$request]);
+ }
+
+ public function it_can_detect_when_response_type_is_invalid()
+ {
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from/it_can_detect_when_response_type_is_invalid?ticket=ST-TICKET-VALID'
+ );
+
+ $this
+ ->shouldThrow(Exception::class)
+ ->during('handle', [$request]);
+ }
+
+ public function it_can_get_credentials_with_pgtUrl(CacheItemPoolInterface $cache, CacheItemInterface $cacheItem)
+ {
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $cacheItem
+ ->set('pgtId')
+ ->willReturn($cacheItem);
+
+ $cacheItem
+ ->expiresAfter(300)
+ ->willReturn($cacheItem);
+
+ $cacheItem
+ ->get()
+ ->willReturn('pgtIou');
+
+ $cache
+ ->save($cacheItem)
+ ->willReturn(true);
+
+ $cache
+ ->hasItem('pgtIou')
+ ->willReturn(true);
+
+ $cache
+ ->getItem('pgtIou')
+ ->willReturn($cacheItem);
+
+ $this->beConstructedWith(
+ [],
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ ),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ Cas::getTestPropertiesWithPgtUrl(),
+ $psr17
+ );
+
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_get_credentials_with_pgtUrl')
+ );
+
+ $this
+ ->handle($request)
+ ->shouldImplement(ResponseInterface::class);
+
+ $request = new ServerRequest(
+ Method::GET,
+ new Uri('http://from/it_can_get_credentials_with_pgtUrl/missing_pgt')
+ );
+
+ $this
+ ->shouldThrow(CasExceptionInterface::class)
+ ->during('handle', [$request]);
+ }
+
+ public function it_can_get_credentials_without_pgtUrl()
+ {
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from/it_can_get_credentials_without_pgtUrl'
+ );
+
+ $this
+ ->handle($request)
+ ->shouldImplement(ResponseInterface::class);
+ }
+
+ public function it_is_initializable()
+ {
+ $this->shouldHaveType(ServiceValidate::class);
+ }
+
+ public function let(CacheItemPoolInterface $cache)
+ {
+ $psr17Factory = new Psr17Factory();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $this->beConstructedWith(
+ [],
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ ),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ Cas::getTestProperties(),
+ $psr17
+ );
+ }
+}
diff --git a/spec/EcPhp/CasLib/Introspection/ServiceValidateSpec.php b/spec/EcPhp/CasLib/Introspection/ServiceValidateSpec.php
deleted file mode 100644
index 7d1a34e..0000000
--- a/spec/EcPhp/CasLib/Introspection/ServiceValidateSpec.php
+++ /dev/null
@@ -1,163 +0,0 @@
-withHeader('Content-Type', 'application/xml')
- ->withBody($psr17Factory->createStream($body));
-
- $credentials = [
- 'user' => 'user',
- 'proxyGrantingTicket' => 'proxyGrantingTicket',
- 'proxies' => [
- 'proxy' => [
- 'http://proxy1',
- 'http://proxy2',
- ],
- ],
- 'extendedAttributes' => [
- 'extendedAttribute' => [
- 'attributeValue' => [
- 0 => 'rex',
- 1 => 'snoopy',
- ],
- '@attributes' => [
- 'name' => 'http://stork.eu/motherInLawDogName',
- ],
- ],
- ],
- ];
-
- $parsed = [
- 'serviceResponse' => [
- 'authenticationSuccess' => $credentials,
- ],
- ];
-
- $this
- ->beConstructedWith($parsed, 'XML', $response);
-
- $this
- ->getCredentials()
- ->shouldReturn(
- $credentials
- );
-
- $this
- ->getFormat()
- ->shouldReturn('XML');
-
- $this
- ->getProxies()
- ->shouldReturn([
- 'proxy' => [
- 'http://proxy1',
- 'http://proxy2',
- ],
- ]);
-
- $this
- ->getResponse()
- ->shouldReturn($response);
-
- $this
- ->getParsedResponse()
- ->shouldReturn($parsed);
- }
-
- public function it_can_detect_a_service_validate_response()
- {
- $psr17Factory = new Psr17Factory();
-
- $body = <<< 'EOF'
-
-
- user
- proxyGrantingTicket
-
-
- EOF;
-
- $response = (new Response(200))
- ->withHeader('Content-Type', 'application/xml')
- ->withBody($psr17Factory->createStream($body));
-
- $credentials = [
- 'user' => 'user',
- 'proxyGrantingTicket' => 'proxyGrantingTicket',
- ];
-
- $parsed = [
- 'serviceResponse' => [
- 'authenticationSuccess' => [
- 'user' => 'user',
- 'proxyGrantingTicket' => 'proxyGrantingTicket',
- ],
- ],
- ];
-
- $this
- ->beConstructedWith($parsed, 'XML', $response);
-
- $this
- ->getCredentials()
- ->shouldReturn($credentials);
-
- $this
- ->getFormat()
- ->shouldReturn('XML');
-
- $this
- ->getProxies()
- ->shouldReturn([]);
-
- $this
- ->getResponse()
- ->shouldReturn($response);
- }
-
- public function it_can_use_the_withParsedResponse_wither_method()
- {
- $psr17Factory = new Psr17Factory();
- $body = 'body';
-
- $response = (new Response(200))
- ->withHeader('Content-Type', 'application/xml')
- ->withBody($psr17Factory->createStream($body));
-
- $this
- ->beConstructedWith([], 'XML', $response);
-
- $this
- ->withParsedResponse(['foo'])
- ->shouldNotReturn($this);
-
- $this
- ->withParsedResponse(['foo'])
- ->shouldReturnAnInstanceOf(IntrospectionInterface::class);
- }
-}
diff --git a/spec/EcPhp/CasLib/Redirect/LoginSpec.php b/spec/EcPhp/CasLib/Redirect/LoginSpec.php
deleted file mode 100644
index 49dced7..0000000
--- a/spec/EcPhp/CasLib/Redirect/LoginSpec.php
+++ /dev/null
@@ -1,138 +0,0 @@
- range(1, 5),
- ];
-
- $this->beConstructedWith($serverRequest, $parameters, Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle()
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $this
- ->handle()
- ->getHeaderLine('Location')
- ->shouldReturn('http://local/cas/login?custom%5B0%5D=1&custom%5B1%5D=2&custom%5B2%5D=3&custom%5B3%5D=4&custom%5B4%5D=5&service=http%3A%2F%2Fapp');
- }
-
- public function it_can_deal_with_renew_and_gateway_parameters(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $parameters = [
- 'renew' => true,
- 'gateway' => true,
- 'service' => 'service',
- ];
-
- $this->beConstructedWith($serverRequest, $parameters, Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle()
- ->shouldBeNull();
-
- $logger
- ->error('Unable to get the Login response, gateway and renew parameter cannot be set together.')
- ->shouldHaveBeenCalledOnce();
-
- $logger
- ->debug(
- 'Login parameters are invalid, not redirecting to login page.',
- [
- 'parameters' => [
- 'renew' => true,
- 'gateway' => true,
- 'service' => 'service',
- ],
- 'validatedParameters' => null,
- ]
- )
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_deal_with_renew_parameter(ServerRequestInterface $serverRequest, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://app');
-
- $parameters = [
- 'renew' => 'coin',
- 'gateway' => false,
- ];
-
- $this->beConstructedWith($serverRequest, $parameters, Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle()
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $logger
- ->debug(
- 'Building service response redirection to {url}.',
- [
- 'url' => 'http://local/cas/login?renew=true&service=http%3A%2F%2Fapp',
- ]
- )
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_get_a_response(CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $this->beConstructedWith($creator->fromGlobals(), [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle()
- ->shouldBeAnInstanceOf(ResponseInterface::class);
- }
-
- public function it_is_initializable(CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $this->beConstructedWith($creator->fromGlobals(), [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this->shouldHaveType(Login::class);
- }
-}
diff --git a/spec/EcPhp/CasLib/Redirect/LogoutSpec.php b/spec/EcPhp/CasLib/Redirect/LogoutSpec.php
deleted file mode 100644
index 88ee632..0000000
--- a/spec/EcPhp/CasLib/Redirect/LogoutSpec.php
+++ /dev/null
@@ -1,54 +0,0 @@
-beConstructedWith($creator->fromGlobals(), [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this
- ->handle()
- ->shouldBeAnInstanceOf(ResponseInterface::class);
- }
-
- public function it_is_initializable(CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $this->beConstructedWith($creator->fromGlobals(), [], Cas::getTestProperties(), $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger);
-
- $this->shouldHaveType(Logout::class);
- }
-}
diff --git a/spec/EcPhp/CasLib/Introspection/IntrospectorSpec.php b/spec/EcPhp/CasLib/Response/CasResponseBuilderSpec.php
similarity index 63%
rename from spec/EcPhp/CasLib/Introspection/IntrospectorSpec.php
rename to spec/EcPhp/CasLib/Response/CasResponseBuilderSpec.php
index d5da3d5..f6a1ef9 100644
--- a/spec/EcPhp/CasLib/Introspection/IntrospectorSpec.php
+++ b/spec/EcPhp/CasLib/Response/CasResponseBuilderSpec.php
@@ -9,19 +9,23 @@
declare(strict_types=1);
-namespace spec\EcPhp\CasLib\Introspection;
-
-use EcPhp\CasLib\Introspection\Contract\AuthenticationFailure;
-use EcPhp\CasLib\Introspection\Contract\Proxy;
-use EcPhp\CasLib\Introspection\Contract\ProxyFailure;
-use EcPhp\CasLib\Introspection\Contract\ServiceValidate;
-use EcPhp\CasLib\Introspection\Introspector;
-use InvalidArgumentException;
+namespace spec\EcPhp\CasLib\Response;
+
+use EcPhp\CasLib\Contract\Response\CasResponseBuilderInterface;
+use EcPhp\CasLib\Contract\Response\Type\AuthenticationFailure;
+use EcPhp\CasLib\Contract\Response\Type\Proxy;
+use EcPhp\CasLib\Contract\Response\Type\ProxyFailure;
+use EcPhp\CasLib\Contract\Response\Type\ServiceValidate;
+use EcPhp\CasLib\Response\Factory\AuthenticationFailureFactory;
+use EcPhp\CasLib\Response\Factory\ProxyFactory;
+use EcPhp\CasLib\Response\Factory\ProxyFailureFactory;
+use EcPhp\CasLib\Response\Factory\ServiceValidateFactory;
+use Exception;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\Response;
use PhpSpec\ObjectBehavior;
-class IntrospectorSpec extends ObjectBehavior
+class CasResponseBuilderSpec extends ObjectBehavior
{
public function it_can_detect_a_proxy_failure_response()
{
@@ -39,7 +43,8 @@ public function it_can_detect_a_proxy_failure_response()
->withHeader('Content-Type', 'application/xml')
->withBody($psr17Factory->createStream($body));
- $this->detect($response)
+ $this
+ ->fromResponse($response)
->shouldImplement(ProxyFailure::class);
}
@@ -62,7 +67,8 @@ public function it_can_detect_a_proxy_response()
->withHeader('Content-Type', 'application/xml')
->withBody($psr17Factory->createStream($body));
- $this->detect($response)
+ $this
+ ->fromResponse($response)
->shouldBeAnInstanceOf(Proxy::class);
}
@@ -83,7 +89,8 @@ public function it_can_detect_a_service_validate_response()
->withHeader('Content-Type', 'application/xml')
->withBody($psr17Factory->createStream($body));
- $this->detect($response)
+ $this
+ ->fromResponse($response)
->shouldBeAnInstanceOf(ServiceValidate::class);
$body = <<< 'EOF'
@@ -100,7 +107,8 @@ public function it_can_detect_a_service_validate_response()
->withHeader('Content-Type', 'application/json')
->withBody($psr17Factory->createStream($body));
- $this->detect($response)
+ $this
+ ->fromResponse($response)
->shouldBeAnInstanceOf(ServiceValidate::class);
}
@@ -124,7 +132,8 @@ public function it_can_detect_a_service_validate_response_with_proxy()
->withHeader('Content-Type', 'application/xml')
->withBody($psr17Factory->createStream($body));
- $this->detect($response)
+ $this
+ ->fromResponse($response)
->shouldBeAnInstanceOf(ServiceValidate::class);
}
@@ -141,8 +150,8 @@ public function it_can_detect_a_wrong_response()
->withBody($psr17Factory->createStream($body));
$this
- ->shouldThrow(InvalidArgumentException::class)
- ->during('detect', [$response]);
+ ->shouldThrow(Exception::class)
+ ->during('fromResponse', [$response]);
$body = <<< 'EOF'
FOO
@@ -153,8 +162,8 @@ public function it_can_detect_a_wrong_response()
->withBody($psr17Factory->createStream($body));
$this
- ->shouldThrow(InvalidArgumentException::class)
- ->during('detect', [$response]);
+ ->shouldThrow(Exception::class)
+ ->during('fromResponse', [$response]);
}
public function it_can_detect_an_authentication_failure_response()
@@ -173,7 +182,8 @@ public function it_can_detect_an_authentication_failure_response()
->withHeader('Content-Type', 'application/xml')
->withBody($psr17Factory->createStream($body));
- $this->detect($response)
+ $this
+ ->fromResponse($response)
->shouldBeAnInstanceOf(AuthenticationFailure::class);
}
@@ -196,8 +206,8 @@ public function it_can_detect_an_unknown_type_of_response()
->withBody($psr17Factory->createStream($body));
$this
- ->shouldThrow(InvalidArgumentException::class)
- ->during('detect', [$response]);
+ ->shouldThrow(Exception::class)
+ ->during('fromResponse', [$response]);
}
public function it_can_detect_an_unsupported_parse_format()
@@ -213,12 +223,94 @@ public function it_can_detect_an_unsupported_parse_format()
->withBody($psr17Factory->createStream($body));
$this
- ->shouldThrow(InvalidArgumentException::class)
- ->during('parse', [$response, 'FOOBAR']);
+ ->shouldThrow(Exception::class)
+ ->during('fromResponse', [$response]);
+ }
+
+ public function it_can_detect_an_unsupported_response_type()
+ {
+ $body = <<< 'EOF'
+
+
+
+
+ EOF;
+
+ $headers = [
+ 'Content-Type' => 'application/xml',
+ ];
+
+ $response = new Response(
+ 200,
+ $headers,
+ $body
+ );
+
+ $this
+ ->shouldThrow(Exception::class)
+ ->during('fromResponse', [$response]);
+ }
+
+ public function it_can_detect_the_type_of_a_response()
+ {
+ $body = <<< 'EOF'
+
+
+ username
+
+
+ EOF;
+
+ $headers = [
+ 'Content-Type' => 'application/xml',
+ ];
+
+ $response = new Response(
+ 200,
+ $headers,
+ $body
+ );
+
+ $this
+ ->fromResponse($response)
+ ->shouldReturnAnInstanceOf(ServiceValidate::class);
+
+ $body = <<< 'EOF'
+
+
+ username
+
+
+ EOF;
+
+ $headers = [
+ 'Content-Type' => 'application/foo',
+ ];
+
+ $response = new Response(
+ 200,
+ $headers,
+ $body
+ );
+
+ $this
+ ->shouldThrow(Exception::class)
+ ->during('fromResponse', [$response]);
}
public function it_is_initializable()
{
- $this->shouldHaveType(Introspector::class);
+ $this->shouldHaveType(CasResponseBuilderInterface::class);
+ }
+
+ public function let()
+ {
+ $this
+ ->beConstructedWith(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ );
}
}
diff --git a/spec/EcPhp/CasLib/Introspection/ProxyFailureSpec.php b/spec/EcPhp/CasLib/Response/Type/ProxyFailureSpec.php
similarity index 58%
rename from spec/EcPhp/CasLib/Introspection/ProxyFailureSpec.php
rename to spec/EcPhp/CasLib/Response/Type/ProxyFailureSpec.php
index cf4c81f..5f26564 100644
--- a/spec/EcPhp/CasLib/Introspection/ProxyFailureSpec.php
+++ b/spec/EcPhp/CasLib/Response/Type/ProxyFailureSpec.php
@@ -9,7 +9,7 @@
declare(strict_types=1);
-namespace spec\EcPhp\CasLib\Introspection;
+namespace spec\EcPhp\CasLib\Response\Type;
use Nyholm\Psr7\Response;
use PhpSpec\ObjectBehavior;
@@ -18,7 +18,19 @@ class ProxyFailureSpec extends ObjectBehavior
{
public function it_can_detect_a_proxy_failure_response()
{
- $response = (new Response(200));
+ $body = [
+ 'serviceResponse' => [
+ 'proxyFailure' => "unrecognized pgt: 'PGT-123'",
+ ],
+ ];
+
+ $response = new Response(
+ 200,
+ [
+ 'Content-Type' => 'application/json',
+ ],
+ json_encode($body)
+ );
$parsed = [
'serviceResponse' => [
@@ -27,14 +39,14 @@ public function it_can_detect_a_proxy_failure_response()
];
$this
- ->beConstructedWith($parsed, 'XML', $response);
+ ->beConstructedWith($response);
$this
->getMessage()
->shouldReturn("unrecognized pgt: 'PGT-123'");
$this
- ->getResponse()
- ->shouldReturn($response);
+ ->toArray()
+ ->shouldReturn($parsed);
}
}
diff --git a/spec/EcPhp/CasLib/Introspection/ProxySpec.php b/spec/EcPhp/CasLib/Response/Type/ProxySpec.php
similarity index 50%
rename from spec/EcPhp/CasLib/Introspection/ProxySpec.php
rename to spec/EcPhp/CasLib/Response/Type/ProxySpec.php
index 230def5..493e321 100644
--- a/spec/EcPhp/CasLib/Introspection/ProxySpec.php
+++ b/spec/EcPhp/CasLib/Response/Type/ProxySpec.php
@@ -9,7 +9,7 @@
declare(strict_types=1);
-namespace spec\EcPhp\CasLib\Introspection;
+namespace spec\EcPhp\CasLib\Response\Type;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\Response;
@@ -23,11 +23,9 @@ public function it_can_detect_a_proxy_response()
$body = <<< 'EOF'
-
+
- PT-214-A3OoEPNr4Q9kNNuYzmfN8azU31aDUsuW8nk380k7wDExT5PFJpxR1TrNI3q3VGzyDdi0DpZ1LKb8IhPKZKQvavW-8hnfexYjmLCx7qWNsLib1W-DCzzoLVTosAUFzP3XDn5dNzoNtxIXV9KSztF9fYhwHvU0
+ PGT-TICKET
EOF;
@@ -39,24 +37,20 @@ public function it_can_detect_a_proxy_response()
$parsed = [
'serviceResponse' => [
'proxySuccess' => [
- 'proxyTicket' => 'PT-214-A3OoEPNr4Q9kNNuYzmfN8azU31aDUsuW8nk380k7wDExT5PFJpxR1TrNI3q3VGzyDdi0DpZ1LKb8IhPKZKQvavW-8hnfexYjmLCx7qWNsLib1W-DCzzoLVTosAUFzP3XDn5dNzoNtxIXV9KSztF9fYhwHvU0',
+ 'proxyTicket' => 'PGT-TICKET',
],
],
];
$this
- ->beConstructedWith($parsed, 'XML', $response);
+ ->beConstructedWith($response);
$this
->getProxyTicket()
- ->shouldReturn('PT-214-A3OoEPNr4Q9kNNuYzmfN8azU31aDUsuW8nk380k7wDExT5PFJpxR1TrNI3q3VGzyDdi0DpZ1LKb8IhPKZKQvavW-8hnfexYjmLCx7qWNsLib1W-DCzzoLVTosAUFzP3XDn5dNzoNtxIXV9KSztF9fYhwHvU0');
+ ->shouldReturn('PGT-TICKET');
$this
- ->getFormat()
- ->shouldReturn('XML');
-
- $this
- ->getResponse()
- ->shouldReturn($response);
+ ->toArray()
+ ->shouldReturn($parsed);
}
}
diff --git a/spec/EcPhp/CasLib/Response/Type/ServiceValidateSpec.php b/spec/EcPhp/CasLib/Response/Type/ServiceValidateSpec.php
new file mode 100644
index 0000000..d3ebb4e
--- /dev/null
+++ b/spec/EcPhp/CasLib/Response/Type/ServiceValidateSpec.php
@@ -0,0 +1,195 @@
+ [
+ 'authenticationSuccess' => [
+ 'user' => 'user',
+ 'proxyGrantingTicket' => 'proxyGrantingTicket',
+ 'proxies' => [
+ 'proxy' => [
+ 'http://proxy1',
+ 'http://proxy2',
+ ],
+ ],
+ 'extendedAttributes' => [
+ 'extendedAttribute' => [
+ 'attributeValue' => [
+ 0 => 'rex',
+ 1 => 'snoopy',
+ ],
+ '@attributes' => [
+ 'name' => 'http://stork.eu/motherInLawDogName',
+ ],
+ ],
+ ],
+ ],
+ ],
+ ];
+
+ $response = (new Response(200))
+ ->withHeader('Content-Type', 'application/json')
+ ->withBody($psr17Factory->createStream(json_encode($bodyArray)));
+
+ $this
+ ->beConstructedWith($response);
+
+ $this
+ ->getCredentials()
+ ->shouldReturn(
+ $bodyArray['serviceResponse']['authenticationSuccess']
+ );
+
+ $this
+ ->getProxies()
+ ->shouldReturn([
+ 'proxy' => [
+ 'http://proxy1',
+ 'http://proxy2',
+ ],
+ ]);
+
+ $this
+ ->toArray()
+ ->shouldReturn($bodyArray);
+ }
+
+ public function it_can_detect_a_service_validate_response()
+ {
+ $psr17Factory = new Psr17Factory();
+
+ $body = <<< 'EOF'
+
+
+ user
+ proxyGrantingTicket
+
+
+ EOF;
+
+ $response = (new Response(200))
+ ->withHeader('Content-Type', 'application/xml')
+ ->withBody($psr17Factory->createStream($body));
+
+ $parsed = [
+ 'serviceResponse' => [
+ 'authenticationSuccess' => [
+ 'user' => 'user',
+ 'proxyGrantingTicket' => 'proxyGrantingTicket',
+ ],
+ ],
+ ];
+
+ $this
+ ->beConstructedWith($response);
+
+ $this
+ ->toArray()
+ ->shouldReturn($parsed);
+
+ $this
+ ->getProxies()
+ ->shouldReturn([]);
+
+ $this
+ ->toArray()
+ ->shouldReturn($parsed);
+
+ $this
+ ->getBody()
+ ->__toString()
+ ->shouldReturn($body);
+
+ $this
+ ->getHeader('Content-Type')
+ ->shouldReturn(['application/xml']);
+
+ $this
+ ->withHeader('Content-Type', 'application/html')
+ ->getHeader('Content-Type')
+ ->shouldReturn(['application/html']);
+
+ $this
+ ->getHeaderLine('Content-Type')
+ ->shouldReturn('application/xml');
+
+ $this
+ ->getHeaders()
+ ->shouldReturn([
+ 'Content-Type' => [
+ 'application/xml',
+ ],
+ ]);
+
+ $this
+ ->getProtocolVersion()
+ ->shouldReturn('1.1');
+
+ $this
+ ->getReasonPhrase()
+ ->shouldReturn('OK');
+
+ $this
+ ->getStatusCode()
+ ->shouldReturn(200);
+
+ $this
+ ->hasHeader('Content-Type')
+ ->shouldReturn(true);
+
+ $this
+ ->hasHeader('foobar')
+ ->shouldReturn(false);
+
+ $this
+ ->withAddedHeader('foobar', 'barfoo')
+ ->hasHeader('foobar')
+ ->shouldReturn(true);
+
+ $this
+ ->withBody($psr17Factory->createStream('foobar'))
+ ->getBody()
+ ->__toString()
+ ->shouldReturn('foobar');
+
+ $this
+ ->withoutHeader('Content-Type')
+ ->hasHeader('Content-Type')
+ ->shouldReturn(false);
+
+ $this
+ ->withProtocolVersion('2.0')
+ ->getProtocolVersion()
+ ->shouldReturn('2.0');
+
+ $this
+ ->withStatus(500, 'foo')
+ ->getStatusCode()
+ ->shouldReturn(500);
+
+ $this
+ ->withStatus(500, 'foo')
+ ->getReasonPhrase()
+ ->shouldReturn('foo');
+ }
+}
diff --git a/spec/EcPhp/CasLib/Service/ProxySpec.php b/spec/EcPhp/CasLib/Service/ProxySpec.php
deleted file mode 100644
index 99790aa..0000000
--- a/spec/EcPhp/CasLib/Service/ProxySpec.php
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
- username
- pgtIou
-
- http://app/proxyCallback.php
-
-
-
- EOF;
-
- $response = new Response(200, ['Content-Type' => 'application/xml'], $body);
-
- $this
- ->getCredentials($response)
- ->shouldBeNull();
- }
-
- public function it_can_detect_when_no_credentials()
- {
- $response = new Response(500);
-
- $this
- ->getCredentials($response)
- ->shouldBeNull();
- }
-
- public function it_is_initializable()
- {
- $this->shouldHaveType(Proxy::class);
- }
-
- public function let(ServerRequestInterface $serverRequest, ClientInterface $client, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
- }
-}
diff --git a/spec/EcPhp/CasLib/Service/ProxyValidateSpec.php b/spec/EcPhp/CasLib/Service/ProxyValidateSpec.php
deleted file mode 100644
index db78fdb..0000000
--- a/spec/EcPhp/CasLib/Service/ProxyValidateSpec.php
+++ /dev/null
@@ -1,122 +0,0 @@
-getCredentials($response)
- ->shouldBeNull();
- }
-
- public function it_can_get_credentials_with_pgtUrl(ServerRequestInterface $serverRequest, ClientInterface $client, CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from');
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
- $cacheItem
- ->set('pgtId')
- ->willReturn($cacheItem);
-
- $cacheItem
- ->expiresAfter(300)
- ->willReturn($cacheItem);
-
- $cacheItem
- ->get()
- ->willReturn('pgtIou');
-
- $cache
- ->save($cacheItem)
- ->willReturn(true);
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $this->beConstructedWith($serverRequest, ['service' => 'service', 'ticket' => 'ST-ticket-pgt'], Cas::getTestPropertiesWithPgtUrl(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $response = $this->handle();
-
- $response
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $this
- ->getCredentials($response->getWrappedObject())
- ->shouldImplement(ResponseInterface::class);
-
- $logger
- ->debug('Proxy validation service successful.')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_get_credentials_without_pgtUrl(ServerRequestInterface $serverRequest, ClientInterface $client, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from');
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
- $this->beConstructedWith($serverRequest, ['service' => 'service', 'ticket' => 'ticket'], Cas::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $response = $this->handle();
-
- $response
- ->shouldBeAnInstanceOf(ResponseInterface::class);
-
- $this
- ->getCredentials($response->getWrappedObject())
- ->shouldImplement(ResponseInterface::class);
-
- $logger
- ->debug('Service validation service successful.')
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_is_initializable(ServerRequestInterface $serverRequest, ClientInterface $client, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $this->shouldHaveType(ProxyValidate::class);
- }
-
- public function let(ServerRequestInterface $serverRequest, ClientInterface $client, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
- }
-}
diff --git a/spec/EcPhp/CasLib/Utils/ResponseSpec.php b/spec/EcPhp/CasLib/Utils/ResponseSpec.php
new file mode 100644
index 0000000..37e3330
--- /dev/null
+++ b/spec/EcPhp/CasLib/Utils/ResponseSpec.php
@@ -0,0 +1,113 @@
+ 'application/json',
+ ],
+ $body
+ );
+
+ $this
+ ->toArray($response)
+ ->shouldReturn([
+ 'serviceResponse' => [
+ 'authenticationSuccess' => [
+ 'user' => 'username',
+ ],
+ ],
+ ]);
+ }
+
+ public function it_convert_a_xml_response()
+ {
+ $body = <<< 'EOF'
+
+
+ username
+
+
+ EOF;
+
+ $response = new Response(
+ 200,
+ [
+ 'Content-Type' => 'application/xml',
+ ],
+ $body
+ );
+
+ $this
+ ->toArray($response)
+ ->shouldReturn([
+ 'serviceResponse' => [
+ 'authenticationSuccess' => [
+ 'user' => 'username',
+ ],
+ ],
+ ]);
+ }
+
+ public function it_throws_when_body_is_empty()
+ {
+ $response = new Response(
+ 200,
+ [],
+ ''
+ );
+
+ $this
+ ->shouldThrow(CasExceptionInterface::class)
+ ->during('toArray', [$response]);
+ }
+
+ public function it_throws_when_content_type_header_is_missing()
+ {
+ $body = <<< 'EOF'
+
+
+ username
+
+
+ EOF;
+
+ $response = new Response(
+ 200,
+ [],
+ $body
+ );
+
+ $this
+ ->shouldThrow(CasExceptionInterface::class)
+ ->during('toArray', [$response]);
+ }
+}
diff --git a/spec/EcPhp/CasLib/Utils/UriSpec.php b/spec/EcPhp/CasLib/Utils/UriSpec.php
index e38927e..c734063 100644
--- a/spec/EcPhp/CasLib/Utils/UriSpec.php
+++ b/spec/EcPhp/CasLib/Utils/UriSpec.php
@@ -132,7 +132,7 @@ public function it_can_get_a_single_param_from_uri()
$this
->getParam($uri, 'param3')
- ->shouldBeNull();
+ ->shouldReturn('');
$this
->getParam($uri, 'param3', 'foo')
diff --git a/spec/tests/EcPhp/CasLib/CasSpec.php b/spec/tests/EcPhp/CasLib/CasSpec.php
index 108c0c0..313b41d 100644
--- a/spec/tests/EcPhp/CasLib/CasSpec.php
+++ b/spec/tests/EcPhp/CasLib/CasSpec.php
@@ -12,13 +12,17 @@
namespace spec\tests\EcPhp\CasLib;
use EcPhp\CasLib\Cas;
-use EcPhp\CasLib\Introspection\Introspector;
+use EcPhp\CasLib\Contract\Response\Type\ServiceValidate;
+use EcPhp\CasLib\Response\CasResponseBuilder;
+use EcPhp\CasLib\Response\Factory\AuthenticationFailureFactory;
+use EcPhp\CasLib\Response\Factory\ProxyFactory;
+use EcPhp\CasLib\Response\Factory\ProxyFailureFactory;
+use EcPhp\CasLib\Response\Factory\ServiceValidateFactory;
+use Ergebnis\Http\Method;
+use loophp\psr17\Psr17;
use Nyholm\Psr7\Factory\Psr17Factory;
-use Nyholm\Psr7Server\ServerRequestCreator;
+use Nyholm\Psr7\ServerRequest;
use PhpSpec\ObjectBehavior;
-use Psr\Cache\CacheItemPoolInterface;
-use Psr\Log\LoggerInterface;
-use Psr\Log\NullLogger;
use spec\EcPhp\CasLib\Cas as CasSpecUtils;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\HttpClient\Psr18Client;
@@ -27,73 +31,65 @@ class CasSpec extends ObjectBehavior
{
public function it_can_test_the_proxy_mode_with_pgtUrl()
{
- $properties = CasSpecUtils::getTestPropertiesWithPgtUrl();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $serverRequest = $creator->fromGlobals();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
+
+ $cache = new ArrayAdapter();
- $introspector = new Introspector();
+ $cacheItem = $cache->getItem('pgtIou');
+ $cacheItem->set('pgtId');
+
+ $cache
+ ->save($cacheItem);
$this->beConstructedWith(new Cas(
- $serverRequest,
- $properties,
- $client,
- $psr17Factory,
- $psr17Factory,
- $psr17Factory,
- $psr17Factory,
- new ArrayAdapter(),
- new NullLogger(),
- $introspector
+ CasSpecUtils::getTestPropertiesWithPgtUrl(),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
+ $cache,
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
));
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from/it_can_test_the_proxy_mode_with_pgtUrl'
+ );
+
$this
- ->requestTicketValidation(['service' => 'service', 'ticket' => 'ticket'], null)
- ->getBody()
- ->__toString()
- ->shouldReturn('{"serviceResponse":{"authenticationSuccess":{"user":"username","proxies":{"proxy":"http:\/\/app\/proxyCallback.php"}}}}');
+ ->requestTicketValidation($request, ['ticket' => 'ST-TICKET-VALID'])
+ ->shouldBeAnInstanceOf(ServiceValidate::class);
}
- public function it_can_test_the_proxy_mode_without_pgtUrl(CacheItemPoolInterface $cache, LoggerInterface $logger)
+ public function it_can_test_the_proxy_mode_without_pgtUrl()
{
- $properties = CasSpecUtils::getTestProperties();
- $client = new Psr18Client(CasSpecUtils::getHttpClientMock());
-
$psr17Factory = new Psr17Factory();
- $creator = new ServerRequestCreator(
- $psr17Factory, // ServerRequestFactory
- $psr17Factory, // UriFactory
- $psr17Factory, // UploadedFileFactory
- $psr17Factory // StreamFactory
- );
- $serverRequest = $creator->fromGlobals();
-
- $introspector = new Introspector();
+ $psr17 = new Psr17($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
$this->beConstructedWith(new Cas(
- $serverRequest,
- $properties,
- $client,
- $psr17Factory,
- $psr17Factory,
- $psr17Factory,
- $psr17Factory,
+ CasSpecUtils::getTestProperties(),
+ new Psr18Client(CasSpecUtils::getHttpClientMock()),
+ $psr17,
new ArrayAdapter(),
- new NullLogger(),
- $introspector
+ new CasResponseBuilder(
+ new AuthenticationFailureFactory(),
+ new ProxyFactory(),
+ new ProxyFailureFactory(),
+ new ServiceValidateFactory()
+ )
));
+ $request = new ServerRequest(
+ Method::GET,
+ 'http://from/it_can_test_the_proxy_mode_without_pgtUrl'
+ );
+
$this
- ->requestTicketValidation(['service' => 'service', 'ticket' => 'ticket'], null)
- ->getBody()
- ->__toString()
- ->shouldReturn('{"serviceResponse":{"authenticationSuccess":{"user":"username"}}}');
+ ->requestTicketValidation($request, ['ticket' => 'ST-TICKET-VALID'])
+ ->shouldBeAnInstanceOf(ServiceValidate::class);
}
}
diff --git a/spec/tests/EcPhp/CasLib/Service/ProxyValidateSpec.php b/spec/tests/EcPhp/CasLib/Service/ProxyValidateSpec.php
deleted file mode 100644
index aca939d..0000000
--- a/spec/tests/EcPhp/CasLib/Service/ProxyValidateSpec.php
+++ /dev/null
@@ -1,200 +0,0 @@
-set('pgtId')
- ->willReturn($cacheItem);
-
- $cacheItem
- ->expiresAfter(300)
- ->willReturn($cacheItem);
-
- $cacheItem
- ->get()
- ->willReturn('pgtId');
-
- $cache
- ->save($cacheItem)
- ->willReturn(true);
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(true);
-
- $cache
- ->getItem('pgtIou')
- ->willReturn($cacheItem);
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $this
- ->getClient()
- ->shouldBeAnInstanceOf(ClientInterface::class);
-
- $this
- ->getLogger()
- ->shouldBeAnInstanceOf(LoggerInterface::class);
-
- $this
- ->getCache()
- ->shouldBeAnInstanceOf(CacheItemPoolInterface::class);
-
- $this
- ->getUriFactory()
- ->shouldBeAnInstanceOf(UriFactoryInterface::class);
-
- $this
- ->getServerRequest()
- ->shouldBeAnInstanceOf(ServerRequestInterface::class);
-
- $this
- ->getStreamFactory()
- ->shouldBeAnInstanceOf(StreamFactoryInterface::class);
-
- $this
- ->getRequestFactory()
- ->shouldBeAnInstanceOf(RequestFactoryInterface::class);
-
- $this
- ->getResponseFactory()
- ->shouldBeAnInstanceOf(ResponseFactoryInterface::class);
-
- $this
- ->getRequest()
- ->shouldBeAnInstanceOf(RequestInterface::class);
-
- $this
- ->getIntrospector()
- ->shouldBeAnInstanceOf(IntrospectorInterface::class);
-
- $response = [
- 'serviceResponse' => [
- 'authenticationSuccess' => [
- 'proxyGrantingTicket' => 'pgtIou',
- ],
- ],
- ];
-
- $this
- ->updateParsedResponseWithPgt($response)
- ->shouldReturn(
- [
- 'serviceResponse' => [
- 'authenticationSuccess' => [
- 'proxyGrantingTicket' => 'pgtId',
- ],
- ],
- ]
- );
- }
-
- public function it_can_detect_when_no_credentials()
- {
- $response = new Response(500);
-
- $this
- ->getCredentials($response)
- ->shouldBeNull();
- }
-
- public function it_can_log_debugging_information_when_trying_to_get_unexisting_pgtIou(CacheItemPoolInterface $cache, CacheItemInterface $cacheItem, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from');
- $client = new Psr18Client(Cas::getHttpClientMock());
-
- $cache
- ->hasItem('pgtIou')
- ->willReturn(false);
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $response = [
- 'serviceResponse' => [
- 'authenticationSuccess' => [
- 'proxyGrantingTicket' => 'pgtIou',
- ],
- ],
- ];
-
- $this
- ->updateParsedResponseWithPgt($response)
- ->shouldReturn(null);
-
- $logger
- ->error('CAS validation failed: pgtIou not found in the cache.', ['pgtIou' => 'pgtIou'])
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_can_parse_a_response(CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $serverRequest = new ServerRequest('GET', 'http://from');
- $client = new Psr18Client(Cas::getHttpClientMock());
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
-
- $response = new Response(200, [], 'foo');
-
- $this
- ->parse($response)
- ->shouldBeArray();
-
- $logger
- ->error('Unable to parse the response with the specified format {format}.', ['format' => 'XML', 'response' => 'foo'])
- ->shouldHaveBeenCalledOnce();
- }
-
- public function it_is_initializable()
- {
- $this->shouldHaveType(ProxyValidate::class);
- }
-
- public function let(ServerRequestInterface $serverRequest, ClientInterface $client, CacheItemPoolInterface $cache, LoggerInterface $logger)
- {
- $psr17Factory = new Psr17Factory();
-
- $this->beConstructedWith($serverRequest, [], Cas::getTestProperties(), $client, $psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory, $cache, $logger, new Introspector());
- }
-}
diff --git a/src/Cas.php b/src/Cas.php
index 97fe0b0..baf38f9 100644
--- a/src/Cas.php
+++ b/src/Cas.php
@@ -11,25 +11,23 @@
namespace EcPhp\CasLib;
-use EcPhp\CasLib\Configuration\PropertiesInterface;
+use EcPhp\CasLib\Contract\CasInterface;
+use EcPhp\CasLib\Contract\Configuration\PropertiesInterface;
+use EcPhp\CasLib\Contract\Response\CasResponseBuilderInterface;
+use EcPhp\CasLib\Exception\CasException;
+use EcPhp\CasLib\Handler\Login;
+use EcPhp\CasLib\Handler\Logout;
+use EcPhp\CasLib\Handler\Proxy;
use EcPhp\CasLib\Handler\ProxyCallback;
-use EcPhp\CasLib\Introspection\Contract\IntrospectionInterface;
-use EcPhp\CasLib\Introspection\Contract\IntrospectorInterface;
-use EcPhp\CasLib\Redirect\Login;
-use EcPhp\CasLib\Redirect\Logout;
-use EcPhp\CasLib\Service\Proxy;
-use EcPhp\CasLib\Service\ProxyValidate;
-use EcPhp\CasLib\Service\ServiceValidate;
+use EcPhp\CasLib\Handler\ServiceValidate;
use EcPhp\CasLib\Utils\Uri;
+use loophp\psr17\Psr17Interface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Http\Client\ClientInterface;
-use Psr\Http\Message\RequestFactoryInterface;
-use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Message\StreamFactoryInterface;
-use Psr\Http\Message\UriFactoryInterface;
-use Psr\Log\LoggerInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use Throwable;
use function array_key_exists;
@@ -37,318 +35,178 @@ final class Cas implements CasInterface
{
private CacheItemPoolInterface $cache;
- private ClientInterface $client;
-
- private IntrospectorInterface $introspector;
+ private CasResponseBuilderInterface $casResponseBuilder;
- private LoggerInterface $logger;
+ private ClientInterface $client;
private PropertiesInterface $properties;
- private RequestFactoryInterface $requestFactory;
-
- private ResponseFactoryInterface $responseFactory;
-
- private ServerRequestInterface $serverRequest;
-
- private StreamFactoryInterface $streamFactory;
-
- private UriFactoryInterface $uriFactory;
+ private Psr17Interface $psr17;
public function __construct(
- ServerRequestInterface $serverRequest,
PropertiesInterface $properties,
ClientInterface $client,
- UriFactoryInterface $uriFactory,
- ResponseFactoryInterface $responseFactory,
- RequestFactoryInterface $requestFactory,
- StreamFactoryInterface $streamFactory,
+ Psr17Interface $psr17,
CacheItemPoolInterface $cache,
- LoggerInterface $logger,
- IntrospectorInterface $introspector
+ CasResponseBuilderInterface $casResponseBuilder
) {
- $this->serverRequest = $serverRequest;
- $this->properties = $properties;
- $this->client = $client;
- $this->uriFactory = $uriFactory;
- $this->responseFactory = $responseFactory;
- $this->requestFactory = $requestFactory;
- $this->streamFactory = $streamFactory;
$this->cache = $cache;
- $this->logger = $logger;
- $this->introspector = $introspector;
+ $this->client = $client;
+ $this->casResponseBuilder = $casResponseBuilder;
+ $this->properties = $properties;
+ $this->psr17 = $psr17;
}
- public function authenticate(array $parameters = []): ?array
- {
- if (null === $response = $this->requestTicketValidation($parameters)) {
- $this
- ->getLogger()
- ->error('Unable to authenticate the request.');
-
- return null;
+ public function authenticate(
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): array {
+ try {
+ $response = $this->requestTicketValidation($request, $parameters);
+ } catch (Throwable $exception) {
+ throw CasException::unableToAuthenticate($exception);
}
- return $this->getIntrospector()->detect($response)->getParsedResponse();
- }
-
- public function detect(ResponseInterface $response): IntrospectionInterface
- {
- return $this->getIntrospector()->detect($response);
- }
-
- public function getProperties(): PropertiesInterface
- {
- return $this->properties;
- }
-
- public function handleProxyCallback(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- $proxyCallback = new ProxyCallback(
- $this->getServerRequest(),
- $parameters,
- $this->getProperties(),
- $this->getUriFactory(),
- $this->getResponseFactory(),
- $this->getStreamFactory(),
- $this->getCache(),
- $this->getLogger()
- );
-
- return $response ?? $proxyCallback->handle();
- }
-
- public function login(array $parameters = []): ?ResponseInterface
- {
- $login = new Login(
- $this->getServerRequest(),
- $parameters,
- $this->getProperties(),
- $this->getUriFactory(),
- $this->getResponseFactory(),
- $this->getStreamFactory(),
- $this->getCache(),
- $this->getLogger()
- );
-
- return $login->handle();
- }
-
- public function logout(array $parameters = []): ?ResponseInterface
- {
- $logout = new Logout(
- $this->getServerRequest(),
- $parameters,
- $this->getProperties(),
- $this->getUriFactory(),
- $this->getResponseFactory(),
- $this->getStreamFactory(),
- $this->getCache(),
- $this->getLogger()
- );
-
- return $logout->handle();
- }
-
- public function requestProxyTicket(array $parameters = [], ?ResponseInterface $response = null): ?ResponseInterface
- {
- $proxyRequestService = new Proxy(
- $this->getServerRequest(),
- $parameters,
- $this->getProperties(),
- $this->getHttpClient(),
- $this->getUriFactory(),
- $this->getResponseFactory(),
- $this->getRequestFactory(),
- $this->getStreamFactory(),
- $this->getCache(),
- $this->getLogger(),
- $this->getIntrospector()
- );
-
- if (null === $response) {
- if (null === $response = $proxyRequestService->handle()) {
- $this
- ->getLogger()
- ->error('Error during the proxy ticket request.');
-
- return null;
- }
+ try {
+ $casResponse = $this
+ ->casResponseBuilder
+ ->fromResponse($response);
+ } catch (Throwable $exception) {
+ throw CasException::unableToAuthenticate($exception);
}
- $credentials = $proxyRequestService->getCredentials($response);
-
- if (null === $credentials) {
- $this
- ->getLogger()
- ->error('Unable to authenticate the user.');
+ try {
+ $credentials = $casResponse->toArray();
+ } catch (Throwable $exception) {
+ throw CasException::unableToAuthenticate($exception);
}
return $credentials;
}
- public function requestProxyValidate(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- $proxyValidateService = new ProxyValidate(
- $this->getServerRequest(),
- $parameters,
- $this->getProperties(),
- $this->getHttpClient(),
- $this->getUriFactory(),
- $this->getResponseFactory(),
- $this->getRequestFactory(),
- $this->getStreamFactory(),
- $this->getCache(),
- $this->getLogger(),
- $this->getIntrospector()
- );
-
- if (null === $response) {
- if (null === $response = $proxyValidateService->handle()) {
- $this
- ->getLogger()
- ->error('Error during the proxy validate request.');
-
- return null;
- }
- }
-
- $credentials = $proxyValidateService->getCredentials($response);
-
- if (null === $credentials) {
- $this
- ->getLogger()
- ->error('Unable to authenticate the user.');
- }
-
- return $credentials;
+ public function handleProxyCallback(
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this
+ ->process(
+ $request,
+ new ProxyCallback(
+ $parameters,
+ $this->cache,
+ $this->casResponseBuilder,
+ $this->client,
+ $this->properties,
+ $this->psr17,
+ )
+ );
+ }
+
+ public function login(
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this
+ ->process(
+ $request,
+ new Login(
+ $parameters,
+ $this->cache,
+ $this->casResponseBuilder,
+ $this->client,
+ $this->properties,
+ $this->psr17,
+ )
+ );
+ }
+
+ public function logout(
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this
+ ->process(
+ $request,
+ new Logout(
+ $parameters,
+ $this->cache,
+ $this->casResponseBuilder,
+ $this->client,
+ $this->properties,
+ $this->psr17,
+ )
+ );
+ }
+
+ public function process(
+ ServerRequestInterface $request,
+ RequestHandlerInterface $handler
+ ): ResponseInterface {
+ return $handler->handle($request);
+ }
+
+ public function requestProxyTicket(
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this
+ ->process(
+ $request,
+ new Proxy(
+ $parameters,
+ $this->cache,
+ $this->casResponseBuilder,
+ $this->client,
+ $this->properties,
+ $this->psr17,
+ )
+ );
}
public function requestServiceValidate(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- $serviceValidateService = new ServiceValidate(
- $this->getServerRequest(),
- $parameters,
- $this->getProperties(),
- $this->getHttpClient(),
- $this->getUriFactory(),
- $this->getResponseFactory(),
- $this->getRequestFactory(),
- $this->getStreamFactory(),
- $this->getCache(),
- $this->getLogger(),
- $this->getIntrospector()
- );
-
- if (null === $response) {
- if (null === $response = $serviceValidateService->handle()) {
- $this
- ->getLogger()
- ->error('Error during the service validate request.');
-
- return null;
- }
- }
-
- $credentials = $serviceValidateService->getCredentials($response);
-
- if (null === $credentials) {
- $this
- ->getLogger()
- ->error('Unable to authenticate the user.');
- }
-
- return $credentials;
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this
+ ->process(
+ $request,
+ new ServiceValidate(
+ $parameters,
+ $this->cache,
+ $this->casResponseBuilder,
+ $this->client,
+ $this->properties,
+ $this->psr17,
+ )
+ );
}
public function requestTicketValidation(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- if (false === $this->supportAuthentication($parameters)) {
- return null;
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ if (false === $this->supportAuthentication($request, $parameters)) {
+ throw CasException::unsupportedRequest();
}
/** @var string $ticket */
$ticket = Uri::getParam(
- $this->getServerRequest()->getUri(),
+ $request->getUri(),
'ticket',
''
);
- $parameters += ['ticket' => $ticket];
-
- return true === $this->proxyMode() ?
- $this->requestProxyValidate($parameters, $response) :
- $this->requestServiceValidate($parameters, $response);
- }
-
- public function supportAuthentication(array $parameters = []): bool
- {
- return array_key_exists('ticket', $parameters) || Uri::hasParams($this->getServerRequest()->getUri(), 'ticket');
- }
-
- public function withServerRequest(ServerRequestInterface $serverRequest): CasInterface
- {
- $clone = clone $this;
- $clone->serverRequest = $serverRequest;
-
- return $clone;
- }
-
- private function getCache(): CacheItemPoolInterface
- {
- return $this->cache;
- }
-
- private function getHttpClient(): ClientInterface
- {
- return $this->client;
- }
-
- private function getIntrospector(): IntrospectorInterface
- {
- return $this->introspector;
- }
-
- private function getLogger(): LoggerInterface
- {
- return $this->logger;
- }
-
- private function getRequestFactory(): RequestFactoryInterface
- {
- return $this->requestFactory;
- }
-
- private function getResponseFactory(): ResponseFactoryInterface
- {
- return $this->responseFactory;
- }
-
- private function getServerRequest(): ServerRequestInterface
- {
- return $this->serverRequest;
- }
-
- private function getStreamFactory(): StreamFactoryInterface
- {
- return $this->streamFactory;
- }
-
- private function getUriFactory(): UriFactoryInterface
- {
- return $this->uriFactory;
+ return $this
+ ->requestServiceValidate(
+ $request,
+ $parameters + ['ticket' => $ticket]
+ );
}
- private function proxyMode(): bool
- {
- return isset($this->getProperties()['protocol']['serviceValidate']['default_parameters']['pgtUrl']);
+ public function supportAuthentication(
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): bool {
+ return array_key_exists('ticket', $parameters) || Uri::hasParams($request->getUri(), 'ticket');
}
}
diff --git a/src/CasInterface.php b/src/CasInterface.php
deleted file mode 100644
index df13e51..0000000
--- a/src/CasInterface.php
+++ /dev/null
@@ -1,165 +0,0 @@
-getMessage()),
+ 0,
+ $previous
+ );
+ }
+
+ public static function missingResponseContentTypeHeader(): self
+ {
+ return new self(
+ 'Missing "Content-Type" header, unable to detect response format.'
+ );
+ }
+
+ public static function unableToAuthenticate(?Throwable $previous = null)
+ {
+ return new self(
+ sprintf('Authentication failure: %s', $previous->getMessage()),
+ 0,
+ $previous
+ );
+ }
+
+ public static function unableToConvertResponseFromJson(Throwable $previous): self
+ {
+ return new self(
+ 'Unable to convert JSON Response to array.',
+ 0,
+ $previous
+ );
+ }
+
+ public static function unableToConvertResponseFromXml(Throwable $previous): self
+ {
+ return new self(
+ 'Unable to convert XML Response to array.',
+ 0,
+ $previous
+ );
+ }
+
+ public static function unableToLoadXml(Throwable $previous): self
+ {
+ return new self(
+ 'Unable to load the body of the XML Response.',
+ 0,
+ $previous
+ );
+ }
+
+ public static function unsupportedRequest(): self
+ {
+ return new self('The request does not support CAS authentication.');
+ }
+
+ public static function unsupportedResponseFormat(string $format): self
+ {
+ return new self(
+ sprintf('Unsupported response format: %s', $format)
+ );
+ }
+}
diff --git a/src/Redirect/RedirectInterface.php b/src/Exception/CasExceptionInterface.php
similarity index 62%
rename from src/Redirect/RedirectInterface.php
rename to src/Exception/CasExceptionInterface.php
index 942c6b0..a8afeab 100644
--- a/src/Redirect/RedirectInterface.php
+++ b/src/Exception/CasExceptionInterface.php
@@ -9,10 +9,10 @@
declare(strict_types=1);
-namespace EcPhp\CasLib\Redirect;
+namespace EcPhp\CasLib\Exception;
-use EcPhp\CasLib\Handler\HandlerInterface;
+use Throwable;
-interface RedirectInterface extends HandlerInterface
+interface CasExceptionInterface extends Throwable
{
}
diff --git a/src/Exception/CasHandlerException.php b/src/Exception/CasHandlerException.php
new file mode 100644
index 0000000..eb359fa
--- /dev/null
+++ b/src/Exception/CasHandlerException.php
@@ -0,0 +1,129 @@
+getBody())
+ );
+ }
+
+ public static function errorWhileDoingRequest(Throwable $previous): self
+ {
+ $exception = CasException::errorWhileDoingRequest($previous);
+
+ return new self($exception->getMessage(), 0, $exception);
+ }
+
+ public static function getItemFromCacheFailure(Throwable $exception): self
+ {
+ return new self(
+ sprintf('Unable to get item from cache: %s', $exception->getMessage()),
+ 0,
+ $exception
+ );
+ }
+
+ public static function invalidProxyResponseType(ResponseInterface $response): self
+ {
+ return new self(
+ sprintf(
+ 'CAS proxy failure: Invalid response type, %s given while expecting %s.',
+ get_class($response),
+ Proxy::class
+ )
+ );
+ }
+
+ public static function loginInvalidParameters(): self
+ {
+ return new self(
+ 'Login parameters are invalid.'
+ );
+ }
+
+ public static function loginRenewAndGatewayParametersAreSet(): self
+ {
+ return new self(
+ 'Unable to get the Login response, gateway and renew parameter cannot be set together.'
+ );
+ }
+
+ public static function missingPGT(Throwable $exception): self
+ {
+ return new self(
+ $exception->getMessage(),
+ 0,
+ $exception
+ );
+ }
+
+ public static function pgtIdIsNull(): self
+ {
+ return new self(
+ 'CAS proxy callback failure: PGT ID is null'
+ );
+ }
+
+ public static function pgtIouIsNull(): self
+ {
+ return new self(
+ 'CAS proxy callback failure: PGT IOU is null'
+ );
+ }
+
+ public static function serviceValidateInvalidPGTIdValue(): self
+ {
+ return new self(
+ 'CAS service validation failed: Invalid PGT ID value.'
+ );
+ }
+
+ public static function serviceValidatePGTNotFound(): self
+ {
+ return new self(
+ 'CAS service validation failed: ProxyGrantingTicket not found.'
+ );
+ }
+
+ public static function serviceValidateUnableToGetPGTFromCache(Throwable $exception): self
+ {
+ return new self(
+ sprintf('CAS service validation failed: Unable to get PGT (%s).', $exception->getMessage()),
+ 0,
+ $exception
+ );
+ }
+
+ public static function serviceValidateValidationFailed(ResponseInterface $response): self
+ {
+ return new self(
+ sprintf(
+ 'CAS service validation failure: Invalid response type, %s given while expecting %s.',
+ get_class($response),
+ ServiceValidate::class
+ )
+ );
+ }
+}
diff --git a/src/Exception/CasResponseBuilderException.php b/src/Exception/CasResponseBuilderException.php
new file mode 100644
index 0000000..2607ae1
--- /dev/null
+++ b/src/Exception/CasResponseBuilderException.php
@@ -0,0 +1,38 @@
+serverRequest = $serverRequest;
+ $this->cache = $cache;
+ $this->casResponseBuilder = $casResponseBuilder;
+ $this->client = $client;
$this->parameters = $parameters;
$this->properties = $properties;
- $this->uriFactory = $uriFactory;
- $this->responseFactory = $responseFactory;
- $this->streamFactory = $streamFactory;
- $this->cache = $cache;
- $this->logger = $logger;
+ $this->psr17 = $psr17;
}
- /**
- * @param mixed[]|string[]|UriInterface[] $query
- */
- protected function buildUri(UriInterface $from, string $name, array $query = []): UriInterface
- {
+ protected function buildUri(
+ UriInterface $from,
+ string $type,
+ array $queryParams = []
+ ): UriInterface {
$properties = $this->getProperties();
- // Remove parameters that are not allowed.
- $query = array_intersect_key(
- $query,
- (array) array_combine(
- $properties['protocol'][$name]['allowed_parameters'] ?? [],
- $properties['protocol'][$name]['allowed_parameters'] ?? []
- )
- ) + Uri::getParams($from);
-
+ $queryParams += Uri::getParams($from);
$baseUrl = parse_url($properties['base_url']);
if (false === $baseUrl) {
- $baseUrl = ['path' => ''];
- $properties['base_url'] = '';
+ throw new CasHandlerException(
+ sprintf('Unable to parse URL: %s', $properties['base_url'])
+ );
}
- $baseUrl += ['path' => ''];
-
- if (true === array_key_exists('service', $query)) {
- $query['service'] = (string) $query['service'];
+ if (true === array_key_exists('service', $queryParams)) {
+ $queryParams['service'] = (string) $queryParams['service'];
}
- // Filter out empty $query parameters
- $query = array_filter(
- $query,
- static function ($item): bool {
- if ([] === $item) {
- return false;
- }
-
- return '' !== $item;
- }
- );
-
- return $this->getUriFactory()
+ return $this
+ ->getPsr17()
->createUri($properties['base_url'])
- ->withPath($baseUrl['path'] . $properties['protocol'][$name]['path'])
- ->withQuery(http_build_query($query))
+ ->withPath(sprintf('%s%s', $baseUrl['path'], $properties['protocol'][$type]['path']))
+ ->withQuery(http_build_query($queryParams))
->withFragment($from->getFragment());
}
@@ -119,30 +90,22 @@ static function ($item): bool {
*/
protected function formatProtocolParameters(array $parameters): array
{
- $parameters = array_filter(
- $parameters
- );
-
$parameters = array_map(
- static function ($parameter) {
- return true === $parameter ? 'true' : $parameter;
- },
- $parameters
+ static fn ($parameter) => true === $parameter ? 'true' : $parameter,
+ array_filter($parameters)
);
if (true === array_key_exists('service', $parameters)) {
- $service = $this->getUriFactory()->createUri(
- $parameters['service']
- );
-
- $service = Uri::removeParams(
- $service,
+ $parameters['service'] = (string) Uri::removeParams(
+ $this
+ ->getPsr17()
+ ->createUri($parameters['service']),
'ticket'
);
-
- $parameters['service'] = (string) $service;
}
+ ksort($parameters);
+
return $parameters;
}
@@ -151,51 +114,31 @@ protected function getCache(): CacheItemPoolInterface
return $this->cache;
}
- protected function getLogger(): LoggerInterface
+ protected function getCasResponseBuilder(): CasResponseBuilderInterface
{
- return $this->logger;
+ return $this->casResponseBuilder;
}
- /**
- * @return array[]
- */
- protected function getParameters(): array
+ protected function getClient(): ClientInterface
{
- return $this->parameters + ($this->getProtocolProperties()['default_parameters'] ?? []);
- }
-
- protected function getProperties(): PropertiesInterface
- {
- return $this->properties;
+ return $this->client;
}
/**
- * Get the scoped properties of the protocol endpoint.
- *
* @return array[]
*/
- protected function getProtocolProperties(): array
- {
- return [];
- }
-
- protected function getResponseFactory(): ResponseFactoryInterface
- {
- return $this->responseFactory;
- }
-
- protected function getServerRequest(): ServerRequestInterface
+ protected function getParameters(): array
{
- return $this->serverRequest;
+ return $this->parameters;
}
- protected function getStreamFactory(): StreamFactoryInterface
+ protected function getProperties(): PropertiesInterface
{
- return $this->streamFactory;
+ return $this->properties;
}
- protected function getUriFactory(): UriFactoryInterface
+ protected function getPsr17(): Psr17Interface
{
- return $this->uriFactory;
+ return $this->psr17;
}
}
diff --git a/src/Handler/Login.php b/src/Handler/Login.php
new file mode 100644
index 0000000..c4ddf2c
--- /dev/null
+++ b/src/Handler/Login.php
@@ -0,0 +1,79 @@
+getParameters();
+ $parameters += Uri::getParams($request->getUri());
+ $parameters += $this->getProperties()['protocol'][HandlerInterface::TYPE_LOGIN]['default_parameters'] ?? [];
+ $parameters += [
+ 'service' => (string) $request->getUri(),
+ ];
+ $parameters = $this->formatProtocolParameters($parameters);
+
+ $this->validate($request, $parameters);
+
+ return $this
+ ->getPsr17()
+ ->createResponse(302)
+ ->withHeader(
+ 'Location',
+ (string) $this
+ ->buildUri(
+ $request->getUri(),
+ HandlerInterface::TYPE_LOGIN,
+ $parameters
+ )
+ );
+ }
+
+ /**
+ * @param string[] $parameters
+ *
+ * @throws CasExceptionInterface
+ */
+ private function validate(
+ RequestInterface $request,
+ array $parameters
+ ): void {
+ $uri = $request->getUri();
+
+ $renew = $parameters['renew'] ?? false;
+ $gateway = $parameters['gateway'] ?? false;
+
+ if ('true' === $renew && 'true' === $gateway) {
+ throw CasHandlerException::loginRenewAndGatewayParametersAreSet();
+ }
+
+ foreach (['gateway', 'renew'] as $queryParameter) {
+ if (false === array_key_exists($queryParameter, $parameters)) {
+ continue;
+ }
+
+ if ('true' !== Uri::getParam($uri, $queryParameter, 'true')) {
+ throw CasHandlerException::loginInvalidParameters();
+ }
+ }
+ }
+}
diff --git a/src/Handler/Logout.php b/src/Handler/Logout.php
new file mode 100644
index 0000000..90344fd
--- /dev/null
+++ b/src/Handler/Logout.php
@@ -0,0 +1,40 @@
+getParameters();
+ $parameters += Uri::getParams($request->getUri());
+ $parameters += $this->getProperties()['protocol'][HandlerInterface::TYPE_LOGOUT]['default_parameters'] ?? [];
+
+ return $this
+ ->getPsr17()
+ ->createResponse(302)
+ ->withHeader(
+ 'Location',
+ (string) $this
+ ->buildUri(
+ $request->getUri(),
+ HandlerInterface::TYPE_LOGOUT,
+ $this->formatProtocolParameters($parameters)
+ )
+ );
+ }
+}
diff --git a/src/Handler/Proxy.php b/src/Handler/Proxy.php
new file mode 100644
index 0000000..ab8eefc
--- /dev/null
+++ b/src/Handler/Proxy.php
@@ -0,0 +1,61 @@
+getProperties();
+
+ $parameters = $this->getParameters();
+ $parameters += Uri::getParams($request->getUri());
+ $parameters += $properties['protocol'][HandlerInterface::TYPE_PROXY]['default_parameters'] ?? [];
+ $parameters += ['service' => (string) $request->getUri()];
+
+ $request = $this
+ ->getPsr17()
+ ->createRequest(
+ Method::GET,
+ $this
+ ->buildUri(
+ $request->getUri(),
+ HandlerInterface::TYPE_PROXY,
+ $this->formatProtocolParameters($parameters)
+ )
+ );
+
+ try {
+ $response = $this
+ ->getClient()
+ ->sendRequest($request);
+ } catch (Throwable $exception) {
+ throw CasHandlerException::errorWhileDoingRequest($exception);
+ }
+
+ $response = $this->getCasResponseBuilder()->fromResponse($response);
+
+ if (false === ($response instanceof \EcPhp\CasLib\Contract\Response\Type\Proxy)) {
+ throw CasHandlerException::invalidProxyResponseType($response);
+ }
+
+ return $response;
+ }
+}
diff --git a/src/Handler/ProxyCallback.php b/src/Handler/ProxyCallback.php
index bede7b3..055e5aa 100644
--- a/src/Handler/ProxyCallback.php
+++ b/src/Handler/ProxyCallback.php
@@ -11,63 +11,48 @@
namespace EcPhp\CasLib\Handler;
+use EcPhp\CasLib\Contract\Handler\HandlerInterface;
+use EcPhp\CasLib\Exception\CasHandlerException;
use EcPhp\CasLib\Utils\Uri;
use Exception;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Throwable;
final class ProxyCallback extends Handler implements HandlerInterface
{
- public function handle(): ?ResponseInterface
+ public function handle(ServerRequestInterface $request): ResponseInterface
{
- $serverRequest = $this->getServerRequest();
$response = $this
- ->getResponseFactory()
- ->createResponse(200);
+ ->getPsr17()
+ ->createResponse();
- // POST parameters prevails over GET parameters.
- $parameters = $this->getParameters() +
- (array) $serverRequest->getParsedBody() +
- Uri::getParams($serverRequest->getUri()) +
- ['pgtId' => null, 'pgtIou' => null];
+ $parameters = $this->getParameters();
+ $parameters += Uri::getParams($request->getUri());
+ $parameters += (array) $request->getBody();
+ $parameters += ['pgtId' => null, 'pgtIou' => null];
if (null === $parameters['pgtId'] && null === $parameters['pgtIou']) {
- $this
- ->getLogger()
- ->debug(
- 'CAS server just checked the proxy callback endpoint.'
- );
-
+ // We cannot return an exception here because prior sending the
+ // PGT ID and PGTIOU, a request is made by the CAS server in order
+ // to check the existence of the proxy callback endpoint.
return $response;
}
if (null === $parameters['pgtIou']) {
- $this
- ->getLogger()
- ->debug(
- 'Missing proxy callback parameter (pgtIou).'
- );
-
- return $response->withStatus(500);
+ throw CasHandlerException::pgtIouIsNull();
}
if (null === $parameters['pgtId']) {
- $this
- ->getLogger()
- ->debug(
- 'Missing proxy callback parameter (pgtId).'
- );
-
- return $response->withStatus(500);
+ throw CasHandlerException::pgtIdIsNull();
}
try {
- $cacheItem = $this->getCache()->getItem($parameters['pgtIou']);
- } catch (Exception $exception) {
- $this
- ->getLogger()
- ->error($exception->getMessage());
-
- return $response->withStatus(500);
+ $cacheItem = $this
+ ->getCache()
+ ->getItem($parameters['pgtIou']);
+ } catch (Throwable $exception) {
+ throw CasHandlerException::getItemFromCacheFailure($exception);
}
$this
@@ -78,12 +63,6 @@ public function handle(): ?ResponseInterface
->expiresAfter(300)
);
- $this
- ->getLogger()
- ->debug(
- 'Storing proxy callback parameters (pgtId and pgtIou).'
- );
-
return $response;
}
}
diff --git a/src/Handler/ServiceValidate.php b/src/Handler/ServiceValidate.php
new file mode 100644
index 0000000..67e18a9
--- /dev/null
+++ b/src/Handler/ServiceValidate.php
@@ -0,0 +1,116 @@
+getProperties();
+
+ $type = $properties['protocol'][HandlerInterface::TYPE_SERVICE_VALIDATE]['default_parameters']['pgtUrl'] ?? false
+ ? HandlerInterface::TYPE_PROXY_VALIDATE
+ : HandlerInterface::TYPE_SERVICE_VALIDATE;
+
+ $parameters = $this->getParameters();
+ $parameters += Uri::getParams($request->getUri());
+ $parameters += $properties['protocol'][$type]['default_parameters'] ?? [];
+ $parameters += ['service' => (string) $request->getUri()];
+
+ $request = $this
+ ->getPsr17()
+ ->createRequest(
+ Method::GET,
+ $this
+ ->buildUri(
+ $request->getUri(),
+ $type,
+ $this->formatProtocolParameters($parameters)
+ )
+ );
+
+ try {
+ $response = $this
+ ->getClient()
+ ->sendRequest($request);
+ } catch (Throwable $exception) {
+ throw CasHandlerException::errorWhileDoingRequest($exception);
+ }
+
+ $response = $this->getCasResponseBuilder()->fromResponse($response);
+
+ if ($response instanceof AuthenticationFailure) {
+ throw CasHandlerException::authenticationFailure($response);
+ }
+
+ if (false === ($response instanceof TypeServiceValidate)) {
+ throw CasHandlerException::serviceValidateValidationFailed($response);
+ }
+
+ if (HandlerInterface::TYPE_SERVICE_VALIDATE === $type) {
+ return $response;
+ }
+
+ /** @var TypeServiceValidate $response */
+ try {
+ $proxyGrantingTicket = $response->getProxyGrantingTicket();
+ } catch (Throwable $exception) {
+ throw CasHandlerException::missingPGT($exception);
+ }
+
+ $hasPgtIou = $this
+ ->getCache()
+ ->hasItem($proxyGrantingTicket);
+
+ if (false === $hasPgtIou) {
+ throw CasHandlerException::serviceValidatePGTNotFound();
+ }
+
+ try {
+ $pgtId = $this
+ ->getCache()
+ ->getItem($proxyGrantingTicket);
+ } catch (Throwable $exception) {
+ throw CasHandlerException::serviceValidateUnableToGetPGTFromCache($exception);
+ }
+
+ if (null === $pgtId->get()) {
+ throw CasHandlerException::serviceValidateInvalidPGTIdValue();
+ }
+
+ return $response
+ ->withBody(
+ $this
+ ->getPsr17()
+ ->createStream(
+ str_replace(
+ $proxyGrantingTicket,
+ $pgtId->get(),
+ (string) $response->getBody()
+ )
+ )
+ );
+ }
+}
diff --git a/src/Introspection/Contract/IntrospectionInterface.php b/src/Introspection/Contract/IntrospectionInterface.php
deleted file mode 100644
index 0b68b02..0000000
--- a/src/Introspection/Contract/IntrospectionInterface.php
+++ /dev/null
@@ -1,25 +0,0 @@
-
- */
- public function parse(ResponseInterface $response, string $format = 'XML'): array;
-}
diff --git a/src/Introspection/Introspection.php b/src/Introspection/Introspection.php
deleted file mode 100644
index a8d86be..0000000
--- a/src/Introspection/Introspection.php
+++ /dev/null
@@ -1,54 +0,0 @@
-response = $response;
- $this->parsedResponse = $parsedResponse;
- $this->format = $format;
- }
-
- public function getFormat(): string
- {
- return $this->format;
- }
-
- public function getParsedResponse(): array
- {
- return $this->parsedResponse;
- }
-
- public function getResponse(): ResponseInterface
- {
- return $this->response;
- }
-
- public function withParsedResponse(array $parsedResponse): IntrospectionInterface
- {
- $clone = clone $this;
- $clone->parsedResponse = $parsedResponse;
-
- return $clone;
- }
-}
diff --git a/src/Introspection/Introspector.php b/src/Introspection/Introspector.php
deleted file mode 100644
index 64138a5..0000000
--- a/src/Introspection/Introspector.php
+++ /dev/null
@@ -1,143 +0,0 @@
-getStatusCode()) {
- throw new InvalidArgumentException('Unable to detect the response format.');
- }
-
- if (true === $response->hasHeader('Content-Type')) {
- $header = substr($response->getHeaderLine('Content-Type'), 0, 16);
-
- switch ($header) {
- case 'application/json':
- $format = 'JSON';
-
- break;
-
- case 'application/xml':
- $format = 'XML';
-
- break;
- }
- }
-
- if (null === $format) {
- throw new InvalidArgumentException('Unable to detect the response format.');
- }
-
- try {
- $data = $this->parse($response, $format);
- } catch (InvalidArgumentException $exception) {
- throw new InvalidArgumentException($exception->getMessage());
- }
-
- if (false === array_key_exists('serviceResponse', $data)) {
- throw new InvalidArgumentException('Unable to find the response type.');
- }
-
- if (array_key_exists('authenticationFailure', $data['serviceResponse'])) {
- return new AuthenticationFailure($data, $format, $response);
- }
-
- if (array_key_exists('proxyFailure', $data['serviceResponse'])) {
- return new ProxyFailure($data, $format, $response);
- }
-
- if (array_key_exists('authenticationSuccess', $data['serviceResponse']) && array_key_exists('user', $data['serviceResponse']['authenticationSuccess'])) {
- return new ServiceValidate($data, $format, $response);
- }
-
- if (array_key_exists('proxySuccess', $data['serviceResponse']) && array_key_exists('proxyTicket', $data['serviceResponse']['proxySuccess'])) {
- return new Proxy($data, $format, $response);
- }
-
- throw new InvalidArgumentException('Unable to find the response type.');
- }
-
- /**
- * @throws InvalidArgumentException
- *
- * @return mixed[]
- */
- public function parse(ResponseInterface $response, string $format = 'XML'): array
- {
- $body = (string) $response->getBody();
-
- if ('' === $body) {
- throw new InvalidArgumentException('Empty response body');
- }
-
- if ('XML' === $format) {
- try {
- $dom = new DOMDocument();
-
- $dom
- ->loadXML(
- $body,
- LIBXML_NSCLEAN | LIBXML_NOCDATA | LIBXML_NOBLANKS | LIBXML_NONET
- );
-
- $this->removeDomNamespace($dom, 'cas');
-
- $data = XML2Array::createArray($dom);
- } catch (Exception $e) {
- throw new InvalidArgumentException('Unable to parse the response using XML format.', 0, $e);
- }
-
- return $data;
- }
-
- if ('JSON' === $format) {
- $json = json_decode($body, true);
-
- if (null === $json || JSON_ERROR_NONE !== json_last_error()) {
- throw new InvalidArgumentException('Unable to parse the response using JSON format.');
- }
-
- return $json;
- }
-
- throw new InvalidArgumentException('Unsupported format.');
- }
-
- private function removeDomNamespace(DOMDocument $doc, string $namespace): void
- {
- $query = sprintf('//*[namespace::%s and not(../namespace::%s)]', $namespace, $namespace);
-
- foreach ((new DOMXPath($doc))->query($query) as $node) {
- $node->removeAttributeNS($node->lookupNamespaceURI($namespace), $namespace);
- }
- }
-}
diff --git a/src/Introspection/ServiceValidate.php b/src/Introspection/ServiceValidate.php
deleted file mode 100644
index c4dff54..0000000
--- a/src/Introspection/ServiceValidate.php
+++ /dev/null
@@ -1,31 +0,0 @@
-getParsedResponse()['serviceResponse']['authenticationSuccess'];
- }
-
- public function getProxies(): array
- {
- $hasProxy = isset($this->getParsedResponse()['serviceResponse']['authenticationSuccess']['proxies']);
-
- return true === $hasProxy ?
- $this->getParsedResponse()['serviceResponse']['authenticationSuccess']['proxies'] :
- [];
- }
-}
diff --git a/src/Redirect/Login.php b/src/Redirect/Login.php
deleted file mode 100644
index 6f47d03..0000000
--- a/src/Redirect/Login.php
+++ /dev/null
@@ -1,114 +0,0 @@
-formatProtocolParameters($this->getParameters());
- $validatedParameters = $this->validate($parameters);
-
- if (null === $validatedParameters) {
- $this
- ->getLogger()
- ->debug(
- 'Login parameters are invalid, not redirecting to login page.',
- [
- 'parameters' => $parameters,
- 'validatedParameters' => $validatedParameters,
- ]
- );
-
- return null;
- }
-
- return $this->createRedirectResponse((string) $this->getUri($validatedParameters));
- }
-
- protected function formatProtocolParameters(array $parameters): array
- {
- $parameters = parent::formatProtocolParameters($parameters);
-
- foreach (['gateway', 'renew'] as $queryParameter) {
- if (false === array_key_exists($queryParameter, $parameters)) {
- continue;
- }
-
- $parameters[$queryParameter] = 'true';
- }
-
- return $parameters;
- }
-
- protected function getProtocolProperties(): array
- {
- $protocolProperties = $this->getProperties()['protocol']['login'] ?? [];
-
- $protocolProperties['default_parameters'] += [
- 'service' => (string) $this->getServerRequest()->getUri(),
- ];
-
- return $protocolProperties;
- }
-
- /**
- * @param string[] $parameters
- */
- private function getUri(array $parameters = []): UriInterface
- {
- return $this->buildUri(
- $this->getServerRequest()->getUri(),
- 'login',
- $parameters
- );
- }
-
- /**
- * @param string[] $parameters
- *
- * @return string[]|null
- */
- private function validate(array $parameters): ?array
- {
- $uri = $this->getServerRequest()->getUri();
-
- $renew = $parameters['renew'] ?? false;
- $gateway = $parameters['gateway'] ?? false;
-
- if ('true' === $renew && 'true' === $gateway) {
- $this
- ->getLogger()
- ->error('Unable to get the Login response, gateway and renew parameter cannot be set together.');
-
- return null;
- }
-
- foreach (['gateway', 'renew'] as $queryParameter) {
- if (false === array_key_exists($queryParameter, $parameters)) {
- continue;
- }
-
- if ('true' !== Uri::getParam($uri, $queryParameter, 'true')) {
- return null;
- }
- }
-
- return $parameters;
- }
-}
diff --git a/src/Redirect/Logout.php b/src/Redirect/Logout.php
deleted file mode 100644
index 2314bfe..0000000
--- a/src/Redirect/Logout.php
+++ /dev/null
@@ -1,36 +0,0 @@
-createRedirectResponse((string) $this->getUri());
- }
-
- protected function getProtocolProperties(): array
- {
- return $this->getProperties()['protocol']['logout'] ?? [];
- }
-
- private function getUri(): UriInterface
- {
- $serverRequest = $this->getServerRequest()->getUri();
- $parameters = $this->formatProtocolParameters($this->getParameters());
-
- return $this->buildUri($serverRequest, 'logout', $parameters);
- }
-}
diff --git a/src/Redirect/Redirect.php b/src/Redirect/Redirect.php
deleted file mode 100644
index f908170..0000000
--- a/src/Redirect/Redirect.php
+++ /dev/null
@@ -1,30 +0,0 @@
-getLogger()
- ->debug('Building service response redirection to {url}.', ['url' => $url]);
-
- return $this
- ->getResponseFactory()
- ->createResponse(302)
- ->withHeader('Location', $url);
- }
-}
diff --git a/src/Response/CasResponseBuilder.php b/src/Response/CasResponseBuilder.php
new file mode 100644
index 0000000..25ebe1d
--- /dev/null
+++ b/src/Response/CasResponseBuilder.php
@@ -0,0 +1,80 @@
+authenticationFailureFactory = $authenticationFailureFactory;
+ $this->proxyFactory = $proxyFactory;
+ $this->proxyFailureFactory = $proxyFailureFactory;
+ $this->serviceValidateFactory = $serviceValidateFactory;
+ }
+
+ public function fromResponse(ResponseInterface $response): CasResponseInterface
+ {
+ if (200 !== $code = $response->getStatusCode()) {
+ throw CasResponseBuilderException::invalidStatusCode($code);
+ }
+
+ $data = (new ResponseUtils())->toArray($response);
+
+ if (false === array_key_exists('serviceResponse', $data)) {
+ throw CasResponseBuilderException::invalidResponseType();
+ }
+
+ if (array_key_exists('authenticationFailure', $data['serviceResponse'])) {
+ return $this->authenticationFailureFactory->decorate($response);
+ }
+
+ if (array_key_exists('proxyFailure', $data['serviceResponse'])) {
+ return $this->proxyFailureFactory->decorate($response);
+ }
+
+ if (array_key_exists('authenticationSuccess', $data['serviceResponse'])) {
+ return $this->serviceValidateFactory->decorate($response);
+ }
+
+ if (array_key_exists('proxySuccess', $data['serviceResponse'])) {
+ return $this->proxyFactory->decorate($response);
+ }
+
+ throw CasResponseBuilderException::unknownResponseType();
+ }
+}
diff --git a/src/Response/Factory/AuthenticationFailureFactory.php b/src/Response/Factory/AuthenticationFailureFactory.php
new file mode 100644
index 0000000..c8a3e72
--- /dev/null
+++ b/src/Response/Factory/AuthenticationFailureFactory.php
@@ -0,0 +1,25 @@
+response = $response;
+ }
+
+ public function getBody()
+ {
+ return $this->response->getBody();
+ }
+
+ public function getHeader($name)
+ {
+ return $this->response->getHeader($name);
+ }
+
+ public function getHeaderLine($name)
+ {
+ return $this->response->getHeaderLine($name);
+ }
+
+ public function getHeaders()
+ {
+ return $this->response->getHeaders();
+ }
+
+ public function getProtocolVersion()
+ {
+ return $this->response->getProtocolVersion();
+ }
+
+ public function getReasonPhrase()
+ {
+ return $this->response->getReasonPhrase();
+ }
+
+ public function getStatusCode()
+ {
+ return $this->response->getStatusCode();
+ }
+
+ public function hasHeader($name)
+ {
+ return $this->response->hasHeader($name);
+ }
+
+ public function toArray(): array
+ {
+ return (new ResponseUtils())->toArray($this->response);
+ }
+
+ public function withAddedHeader($name, $value)
+ {
+ $clone = clone $this;
+ $clone->response = $this->response->withAddedHeader($name, $value);
+
+ return $clone;
+ }
+
+ public function withBody(StreamInterface $body)
+ {
+ $clone = clone $this;
+ $clone->response = $this->response->withBody($body);
+
+ return $clone;
+ }
+
+ public function withHeader($name, $value)
+ {
+ $clone = clone $this;
+ $clone->response = $this->response->withHeader($name, $value);
+
+ return $clone;
+ }
+
+ public function withoutHeader($name)
+ {
+ $clone = clone $this;
+ $clone->response = $this->response->withoutHeader($name);
+
+ return $clone;
+ }
+
+ public function withProtocolVersion($version)
+ {
+ $clone = clone $this;
+ $clone->response = $this->response->withProtocolVersion($version);
+
+ return $clone;
+ }
+
+ public function withStatus($code, $reasonPhrase = '')
+ {
+ $clone = clone $this;
+ $clone->response = $this->response->withStatus($code, $reasonPhrase);
+
+ return $clone;
+ }
+}
diff --git a/src/Introspection/Proxy.php b/src/Response/Type/Proxy.php
similarity index 50%
rename from src/Introspection/Proxy.php
rename to src/Response/Type/Proxy.php
index 446fa93..995aa5e 100644
--- a/src/Introspection/Proxy.php
+++ b/src/Response/Type/Proxy.php
@@ -9,14 +9,14 @@
declare(strict_types=1);
-namespace EcPhp\CasLib\Introspection;
+namespace EcPhp\CasLib\Response\Type;
-use EcPhp\CasLib\Introspection\Contract\Proxy as ProxyInterface;
+use EcPhp\CasLib\Contract\Response\Type\Proxy as ProxyInterface;
-final class Proxy extends Introspection implements ProxyInterface
+final class Proxy extends CasResponse implements ProxyInterface
{
public function getProxyTicket(): string
{
- return $this->getParsedResponse()['serviceResponse']['proxySuccess']['proxyTicket'];
+ return $this->toArray()['serviceResponse']['proxySuccess']['proxyTicket'];
}
}
diff --git a/src/Introspection/ProxyFailure.php b/src/Response/Type/ProxyFailure.php
similarity index 51%
rename from src/Introspection/ProxyFailure.php
rename to src/Response/Type/ProxyFailure.php
index 3fac641..24577d3 100644
--- a/src/Introspection/ProxyFailure.php
+++ b/src/Response/Type/ProxyFailure.php
@@ -9,14 +9,14 @@
declare(strict_types=1);
-namespace EcPhp\CasLib\Introspection;
+namespace EcPhp\CasLib\Response\Type;
-use EcPhp\CasLib\Introspection\Contract\ProxyFailure as ProxyFailureInterface;
+use EcPhp\CasLib\Contract\Response\Type\ProxyFailure as ProxyFailureInterface;
-final class ProxyFailure extends Introspection implements ProxyFailureInterface
+final class ProxyFailure extends CasResponse implements ProxyFailureInterface
{
public function getMessage(): string
{
- return $this->getParsedResponse()['serviceResponse']['proxyFailure'];
+ return $this->toArray()['serviceResponse']['proxyFailure'];
}
}
diff --git a/src/Response/Type/ServiceValidate.php b/src/Response/Type/ServiceValidate.php
new file mode 100644
index 0000000..863ff32
--- /dev/null
+++ b/src/Response/Type/ServiceValidate.php
@@ -0,0 +1,51 @@
+toArray()['serviceResponse']['authenticationSuccess'];
+ }
+
+ public function getProxies(): array
+ {
+ $hasProxy = isset($this->toArray()['serviceResponse']['authenticationSuccess']['proxies']);
+
+ return true === $hasProxy ?
+ $this->toArray()['serviceResponse']['authenticationSuccess']['proxies'] :
+ [];
+ }
+
+ public function getProxyGrantingTicket(): string
+ {
+ $credentials = $this->getCredentials();
+
+ $proxyGrantingTicket = array_key_exists(
+ 'proxyGrantingTicket',
+ $credentials
+ );
+
+ if (false === $proxyGrantingTicket) {
+ // TODO: Create a CasResponseException class.
+ throw new Exception('Service validate response: Missing proxy granting ticket key in CAS response body.');
+ }
+
+ return $credentials['proxyGrantingTicket'];
+ }
+}
diff --git a/src/Service/Proxy.php b/src/Service/Proxy.php
deleted file mode 100644
index ceb7b1a..0000000
--- a/src/Service/Proxy.php
+++ /dev/null
@@ -1,52 +0,0 @@
-getIntrospector()->detect($response);
- } catch (InvalidArgumentException $exception) {
- $this
- ->getLogger()
- ->error($exception->getMessage());
-
- return null;
- }
-
- if (false === ($introspect instanceof \EcPhp\CasLib\Introspection\Contract\Proxy)) {
- return null;
- }
-
- return $response;
- }
-
- protected function getProtocolProperties(): array
- {
- return $this->getProperties()['protocol']['proxy'] ?? [];
- }
-
- protected function getUri(): UriInterface
- {
- return $this->buildUri(
- $this->getServerRequest()->getUri(),
- 'proxy',
- $this->formatProtocolParameters($this->getParameters())
- );
- }
-}
diff --git a/src/Service/ProxyValidate.php b/src/Service/ProxyValidate.php
deleted file mode 100644
index fb1478b..0000000
--- a/src/Service/ProxyValidate.php
+++ /dev/null
@@ -1,39 +0,0 @@
-getProperties()['protocol']['proxyValidate'] ?? [];
-
- $protocolProperties['default_parameters'] += [
- 'service' => (string) $this->getServerRequest()->getUri(),
- 'ticket' => Uri::getParam($this->getServerRequest()->getUri(), 'ticket'),
- ];
-
- return $protocolProperties;
- }
-
- protected function getUri(): UriInterface
- {
- return $this->buildUri(
- $this->getServerRequest()->getUri(),
- 'proxyValidate',
- $this->formatProtocolParameters($this->getParameters())
- );
- }
-}
diff --git a/src/Service/Service.php b/src/Service/Service.php
deleted file mode 100644
index 7a9adcb..0000000
--- a/src/Service/Service.php
+++ /dev/null
@@ -1,272 +0,0 @@
-client = $client;
- $this->requestFactory = $requestFactory;
- $this->introspector = $introspector;
- }
-
- public function getCredentials(ResponseInterface $response): ?ResponseInterface
- {
- try {
- $introspect = $this->getIntrospector()->detect($response);
- } catch (InvalidArgumentException $exception) {
- $this
- ->getLogger()
- ->error($exception->getMessage());
-
- return null;
- }
-
- if (false === ($introspect instanceof ServiceValidate)) {
- $this
- ->getLogger()
- ->error(
- 'Service validation failed.',
- [
- 'response' => (string) $response->getBody(),
- ]
- );
-
- return null;
- }
-
- $parsedResponse = $introspect->getParsedResponse();
- $proxyGrantingTicket = array_key_exists(
- 'proxyGrantingTicket',
- $parsedResponse['serviceResponse']['authenticationSuccess']
- );
-
- if (false === $proxyGrantingTicket) {
- $this
- ->getLogger()
- ->debug('Service validation service successful.');
-
- return $response->withHeader('Content-Type', 'application/json');
- }
-
- $parsedResponse = $this->updateParsedResponseWithPgt($parsedResponse);
-
- if (null === $parsedResponse) {
- return null;
- }
-
- $body = json_encode($parsedResponse);
-
- if (false === $body) {
- return null;
- }
-
- $this
- ->getLogger()
- ->debug('Proxy validation service successful.');
-
- return $response
- ->withBody($this->getStreamFactory()->createStream($body))
- ->withHeader('Content-Type', 'application/json');
- }
-
- public function handle(): ?ResponseInterface
- {
- try {
- $response = $this->getClient()->sendRequest($this->getRequest());
- } catch (ClientExceptionInterface $exception) {
- $this
- ->getLogger()
- ->error($exception->getMessage());
-
- $response = null;
- }
-
- return null === $response ? $response : $this->normalize($response);
- }
-
- protected function getClient(): ClientInterface
- {
- return $this->client;
- }
-
- protected function getIntrospector(): IntrospectorInterface
- {
- return $this->introspector;
- }
-
- protected function getRequest(): RequestInterface
- {
- return $this->getRequestFactory()->createRequest('GET', $this->getUri());
- }
-
- protected function getRequestFactory(): RequestFactoryInterface
- {
- return $this->requestFactory;
- }
-
- /**
- * Get the URI.
- */
- abstract protected function getUri(): UriInterface;
-
- /**
- * Parse the response format.
- *
- * @return array[]|string[]
- * The parsed response.
- */
- protected function parse(ResponseInterface $response): array
- {
- $format = $this->getProtocolProperties()['default_parameters']['format'] ?? 'XML';
-
- try {
- $array = $this->getIntrospector()->parse($response, $format);
- } catch (InvalidArgumentException $exception) {
- $this
- ->getLogger()
- ->error(
- 'Unable to parse the response with the specified format {format}.',
- [
- 'format' => $format,
- 'response' => (string) $response->getBody(),
- ]
- );
-
- $array = [];
- }
-
- return $array;
- }
-
- /**
- * @param array[] $response
- *
- * @return array[]|null
- */
- protected function updateParsedResponseWithPgt(array $response): ?array
- {
- $pgt = $response['serviceResponse']['authenticationSuccess']['proxyGrantingTicket'];
-
- $hasPgtIou = $this->getCache()->hasItem($pgt);
-
- if (false === $hasPgtIou) {
- $this
- ->getLogger()
- ->error('CAS validation failed: pgtIou not found in the cache.', ['pgtIou' => $pgt]);
-
- return null;
- }
-
- $response['serviceResponse']['authenticationSuccess']['proxyGrantingTicket'] = $this
- ->getCache()
- ->getItem($pgt)
- ->get();
-
- return $response;
- }
-
- /**
- * Normalize a response.
- */
- private function normalize(ResponseInterface $response): ResponseInterface
- {
- $body = $this->parse($response);
-
- if ([] === $body) {
- $this
- ->getLogger()
- ->error(
- 'Unable to parse the response during the normalization process.',
- [
- 'body' => (string) $response->getBody(),
- ]
- );
-
- return $response;
- }
-
- $body = json_encode($body);
-
- if (false === $body || JSON_ERROR_NONE !== json_last_error()) {
- $this
- ->getLogger()
- ->error(
- 'Unable to encode the response in JSON during the normalization process.',
- [
- 'body' => (string) $response->getBody(),
- ]
- );
-
- return $response;
- }
-
- $this
- ->getLogger()
- ->debug('Response normalization succeeded.', ['body' => $body]);
-
- return $response
- ->withBody($this->getStreamFactory()->createStream($body))
- ->withHeader('Content-Type', 'application/json');
- }
-}
diff --git a/src/Service/ServiceValidate.php b/src/Service/ServiceValidate.php
deleted file mode 100644
index 33fa863..0000000
--- a/src/Service/ServiceValidate.php
+++ /dev/null
@@ -1,39 +0,0 @@
-getProperties()['protocol']['serviceValidate'] ?? [];
-
- $protocolProperties['default_parameters'] += [
- 'service' => (string) $this->getServerRequest()->getUri(),
- 'ticket' => Uri::getParam($this->getServerRequest()->getUri(), 'ticket'),
- ];
-
- return $protocolProperties;
- }
-
- protected function getUri(): UriInterface
- {
- return $this->buildUri(
- $this->getServerRequest()->getUri(),
- 'serviceValidate',
- $this->formatProtocolParameters($this->getParameters())
- );
- }
-}
diff --git a/src/Utils/Response.php b/src/Utils/Response.php
new file mode 100644
index 0000000..3e25071
--- /dev/null
+++ b/src/Utils/Response.php
@@ -0,0 +1,100 @@
+getBody();
+
+ if ('' === $body) {
+ throw CasException::emptyResponseBodyFailure();
+ }
+
+ if (false === $response->hasHeader('Content-Type')) {
+ throw CasException::missingResponseContentTypeHeader();
+ }
+
+ $header = substr($response->getHeaderLine('Content-Type'), 0, 16);
+
+ switch (true) {
+ case 0 === strpos($header, 'application/json'):
+ try {
+ $json = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
+ } catch (Throwable $exception) {
+ throw CasException::unableToConvertResponseFromJson($exception);
+ }
+
+ return $json;
+
+ case 0 === strpos($header, 'text/html'):
+ case 0 === strpos($header, 'text/xml'):
+ case 0 === strpos($header, 'application/xml'):
+ set_error_handler(
+ static function ($errno, $errstr, $errfile, $errline): void {
+ throw CasException::unableToLoadXml(
+ new ErrorException($errstr, 0, $errno, $errfile, $errline)
+ );
+ }
+ );
+ $dom = new DOMDocument();
+ $dom
+ ->loadXML(
+ $body,
+ LIBXML_NSCLEAN | LIBXML_NOCDATA | LIBXML_NOBLANKS | LIBXML_NONET
+ );
+ restore_error_handler();
+
+ $this->removeDomNamespace($dom, 'cas');
+
+ try {
+ $data = XML2Array::createArray($dom);
+ } catch (Throwable $exception) {
+ throw CasException::unableToConvertResponseFromXml($exception);
+ }
+
+ return $data;
+ }
+
+ throw CasException::unsupportedResponseFormat($header);
+ }
+
+ private function removeDomNamespace(DOMDocument $doc, string $namespace): void
+ {
+ $query = sprintf('//*[namespace::%s and not(../namespace::%s)]', $namespace, $namespace);
+
+ foreach ((new DOMXPath($doc))->query($query) as $node) {
+ $node->removeAttributeNS($node->lookupNamespaceURI($namespace), $namespace);
+ }
+ }
+}
diff --git a/src/Utils/Uri.php b/src/Utils/Uri.php
index 0b0ce8a..65df87c 100644
--- a/src/Utils/Uri.php
+++ b/src/Utils/Uri.php
@@ -11,26 +11,64 @@
namespace EcPhp\CasLib\Utils;
+use InvalidArgumentException;
use League\Uri\Components\Query;
use Psr\Http\Message\UriInterface;
+use Throwable;
+use TypeError;
final class Uri
{
- public static function getParam(UriInterface $uri, string $param, ?string $default = null): ?string
- {
+ /**
+ * Get a parameter from the URI query string.
+ *
+ * @param UriInterface $uri
+ * The URI.
+ * @param string $param
+ * The parameter key.
+ * @param string $default
+ * The default value if the parameter doesn't exist.
+ *
+ * @return string
+ * The value of the parameter to get.
+ */
+ public static function getParam(
+ UriInterface $uri,
+ string $param,
+ string $default = ''
+ ): string {
return self::getParams($uri)[$param] ?? $default;
}
/**
+ * Get the parameters from the URI query string.
+ *
+ * @param UriInterface $uri
+ * The URI.
+ *
* @return string[]
+ * The parameters, as "key/value" pairs.
*/
public static function getParams(UriInterface $uri): array
{
- return iterator_to_array(Query::createFromUri($uri)->pairs());
+ $pairs = [];
+
+ try {
+ $pairs = Query::createFromUri($uri)->pairs();
+ } catch (Throwable $exception) {
+ // Ignore the exception.
+ }
+
+ return iterator_to_array($pairs);
}
/**
+ * Check wether an URI has the requested parameters.
+ *
+ * @param UriInterface $uri
+ * The URI.
* @param string ...$keys
+ * The parameter keys to check.
*/
public static function hasParams(UriInterface $uri, string ...$keys): bool
{
@@ -40,16 +78,18 @@ public static function hasParams(UriInterface $uri, string ...$keys): bool
/**
* Remove one or more parameters from an URI.
*
- * @param \Psr\Http\Message\UriInterface $uri
+ * @param UriInterface $uri
* The URI.
* @param string ...$keys
* The parameter(s) to remove.
*
- * @return \Psr\Http\Message\UriInterface
+ * @return UriInterface
* A new URI without the parameter(s) to remove.
*/
- public static function removeParams(UriInterface $uri, string ...$keys): UriInterface
- {
+ public static function removeParams(
+ UriInterface $uri,
+ string ...$keys
+ ): UriInterface {
return $uri
->withQuery(
http_build_query(
@@ -61,6 +101,24 @@ public static function removeParams(UriInterface $uri, string ...$keys): UriInte
);
}
+ /**
+ * Add a parameter to an URI.
+ *
+ * @param UriInterface $uri
+ * The URI.
+ * @param string $key
+ * The key of the parameter to add to the URI.
+ * @param string $value
+ * The value of the parameter to add to the URI.
+ * @param bool $force
+ * If true, overwrite any existing parameter from the URI.
+ *
+ * @throws TypeError
+ * @throws InvalidArgumentException
+ *
+ * @return UriInterface
+ * A new URI with the added parameter.
+ */
public static function withParam(
UriInterface $uri,
string $key,
@@ -77,13 +135,29 @@ public static function withParam(
}
/**
+ * Add parameters to an URI.
+ *
+ * @param UriInterface $uri
+ * The URI.
* @param string[] $params
+ * The set of parameters to add.
+ * @param bool $force
+ * If true, overwrite any existing parameter from the URI.
+ *
+ * @throws TypeError
+ * @throws InvalidArgumentException
+ *
+ * @return UriInterface
+ * A new URI with the added parameters.
*/
public static function withParams(
UriInterface $uri,
array $params,
bool $force = true
): UriInterface {
+ // Reduce operation
+ // Cannot use `array_reduce` because it
+ // doesn't pass the key to the callback.
foreach ($params as $key => $value) {
$uri = self::withParam($uri, $key, $value, $force);
}
diff --git a/tests/Cas.php b/tests/Cas.php
index 6291b65..29662d9 100644
--- a/tests/Cas.php
+++ b/tests/Cas.php
@@ -11,18 +11,14 @@
namespace tests\EcPhp\CasLib;
-use EcPhp\CasLib\CasInterface;
-use EcPhp\CasLib\Configuration\PropertiesInterface;
-use EcPhp\CasLib\Introspection\Contract\IntrospectionInterface;
+use EcPhp\CasLib\Contract\CasInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
-class Cas implements CasInterface
+final class Cas implements CasInterface
{
- /**
- * @var \EcPhp\CasLib\Cas
- */
- private $cas;
+ private CasInterface $cas;
public function __construct(
CasInterface $cas
@@ -30,78 +26,56 @@ public function __construct(
$this->cas = $cas;
}
- public function authenticate(array $parameters = []): ?array
+ public function authenticate(ServerRequestInterface $request, array $parameters = []): array
{
- return $this->cas->authenticate($parameters);
+ return $this->cas->authenticate($request, $parameters);
}
- public function detect(
- ResponseInterface $response
- ): IntrospectionInterface {
- return $this->cas->detect($response);
+ public function handleProxyCallback(
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this->cas->handleProxyCallback($request, $parameters);
}
- public function getProperties(): PropertiesInterface
+ public function login(ServerRequestInterface $request, array $parameters = []): ResponseInterface
{
- return $this->cas->getProperties();
+ return $this->cas->login($request, $parameters);
}
- public function handleProxyCallback(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- return $this->cas->handleProxyCallback($parameters, $response);
- }
-
- public function login(array $parameters = []): ?ResponseInterface
+ public function logout(ServerRequestInterface $request, array $parameters = []): ResponseInterface
{
- return $this->cas->login($parameters);
+ return $this->cas->logout($request, $parameters);
}
- public function logout(array $parameters = []): ?ResponseInterface
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
- return $this->cas->logout($parameters);
+ return $this->cas->process($request, $handler);
}
public function requestProxyTicket(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- return $this->cas->requestProxyTicket($parameters, $response);
- }
-
- public function requestProxyValidate(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- return $this->cas->requestProxyValidate($parameters, $response);
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this->cas->requestProxyTicket($request, $parameters);
}
public function requestServiceValidate(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- return $this->cas->requestServiceValidate($parameters, $response);
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this->cas->requestServiceValidate($request, $parameters);
}
public function requestTicketValidation(
- array $parameters = [],
- ?ResponseInterface $response = null
- ): ?ResponseInterface {
- return $this->cas->requestTicketValidation($parameters, $response);
+ ServerRequestInterface $request,
+ array $parameters = []
+ ): ResponseInterface {
+ return $this->cas->requestTicketValidation($request, $parameters);
}
- public function supportAuthentication(array $parameters = []): bool
+ public function supportAuthentication(ServerRequestInterface $request, array $parameters = []): bool
{
- return $this->cas->supportAuthentication($parameters);
- }
-
- public function withServerRequest(
- ServerRequestInterface $serverRequest
- ): CasInterface {
- $clone = clone $this;
- $clone->cas = $clone->cas->withServerRequest($serverRequest);
-
- return $clone;
+ return $this->cas->supportAuthentication($request, $parameters);
}
}
diff --git a/tests/Service/ProxyValidate.php b/tests/Service/ProxyValidate.php
deleted file mode 100644
index 7b558e6..0000000
--- a/tests/Service/ProxyValidate.php
+++ /dev/null
@@ -1,114 +0,0 @@
-getProperties()['protocol']['proxyValidate'] ?? [];
-
- $protocolProperties['default_parameters'] += [
- 'service' => (string) $this->getServerRequest()->getUri(),
- 'ticket' => Uri::getParam($this->getServerRequest()->getUri(), 'ticket'),
- ];
-
- return $protocolProperties;
- }
-
- /**
- * Get the URI.
- */
- protected function getUri(): UriInterface
- {
- return $this->buildUri(
- $this->getServerRequest()->getUri(),
- 'proxyValidate',
- $this->formatProtocolParameters($this->getParameters())
- );
- }
-}