diff --git a/modules/core/config/routes/routes.yaml b/modules/core/config/routes/routes.yaml index 6bb06836eab8e67b4f44d040a53f43bfee7aa71a..75e62afa7d4a90ad26c29fd3515272cf62f3524f 100644 --- a/modules/core/config/routes/routes.yaml +++ b/modules/core/config/routes/routes.yaml @@ -16,3 +16,6 @@ core-cardinality: core-warning-shortssointerval: path: /warning/short_sso_interval defaults: { _controller: 'SimpleSAML\Module\core\Controller\ExceptionController:shortSsoInterval' } +core-post-redirect: + path: /postredirect + defaults: { _controller: 'SimpleSAML\Module\core\Controller\RedirectionController:postredirect' } diff --git a/modules/core/lib/Controller/RedirectionController.php b/modules/core/lib/Controller/RedirectionController.php new file mode 100644 index 0000000000000000000000000000000000000000..8fa0fca36b4c4391ed848074c00616cce5c90f0b --- /dev/null +++ b/modules/core/lib/Controller/RedirectionController.php @@ -0,0 +1,108 @@ +<?php + +namespace SimpleSAML\Module\core\Controller; + +use SimpleSAML\Auth; +use SimpleSAML\Configuration; +use SimpleSAML\Error; +use SimpleSAML\Logger; +use SimpleSAML\Module; +use SimpleSAML\Session; +use SimpleSAML\Utils; +use SimpleSAML\XHTML\Template; +use Symfony\Component\HttpFoundation\Request; + +/** + * Controller class for the core module. + * + * This class serves the different views available in the module. + * + * @package SimpleSAML\Module\core + */ +class RedirectionController +{ + /** @var \SimpleSAML\Configuration */ + protected $config; + + /** @var \SimpleSAML\Session */ + protected $session; + + + /** + * Controller constructor. + * + * It initializes the global configuration and auth source configuration for the controllers implemented here. + * + * @param \SimpleSAML\Configuration $config The configuration to use by the controllers. + * @param \SimpleSAML\Session $session The session to use by the controllers. + * + * @throws \Exception + */ + public function __construct( + Configuration $config, + Session $session + ) { + $this->config = $config; + $this->session = $session; + } + + + /** + * This controller provides a way to create a redirect to a POST request + * + * @param Request $request The request that lead to this login operation. + * @throws \SimpleSAML\Error\BadRequest + * @return \SimpleSAML\XHTML\Template|\Symfony\Component\HttpFoundation\RedirectResponse + * An HTML template or a redirection if we are not authenticated. + */ + public function postredirect(Request $request) + { + $redirId = $request->get('RedirId', false); + $redirInfo = $request->get('RedirInfo', false); + if ($redirId !== false) { + $postId = $redirId; + } elseif ($redirInfo !== false) { + $encData = base64_decode($redirInfo); + + if (empty($encData)) { + throw new Error\BadRequest('Invalid RedirInfo data.'); + } + + list($sessionId, $postId) = explode(':', \SimpleSAML\Utils\Crypto::aesDecrypt($encData)); + + if (empty($sessionId) || empty($postId)) { + throw new Error\BadRequest('Invalid session info data.'); + } + + } else { + throw new Error\BadRequest('Missing redirection info parameter.'); + } + + $session = $this->session; + if ($session === null) { + throw new \Exception('Unable to load session.'); + } + + $postData = $session->getData('core_postdatalink', $postId); + + if ($postData === null) { + // The post data is missing, probably because it timed out + throw new \Exception('The POST data we should restore was lost.'); + } + + $session->deleteData('core_postdatalink', $postId); + + assert(is_array($postData)); + assert(array_key_exists('url', $postData)); + assert(array_key_exists('post', $postData)); + + if (!Utils\HTTP::isValidURL($postData['url'])) { + throw new Error\Exception('Invalid destination URL.'); + } + + $t = new Template($this->config, 'post.php'); + $t->data['destination'] = $postData['url']; + $t->data['post'] = $postData['post']; + return $t; + } +}