neos / flow-development-collection

The unified repository containing the Flow core packages, used for Flow development.
https://flow.neos.io/
MIT License
138 stars 188 forks source link

Extensible "intercepted request" handling #1693

Open bwaidelich opened 5 years ago

bwaidelich commented 5 years ago

Description

When Authentication triggers an EntryPoint the current request is considered "intercepted" and is stored in the session so that the application can redirect the user to the intended action after successful authentication. For sessionless authentications this process doesn't work, so we don't store the intercepted request for those (see #1615). In those cases it would be useful to be able to "hook into" the storage mechanism to make the initial feature available for sessionless authentication, too.

See discussion in #1615 for some ideas.

bwaidelich commented 5 years ago

Related: #1694

bwaidelich commented 5 years ago

BTW: Currently we intercept the ActionRequest but we should probably consider intercepting the HTTP request if we rework this

bwaidelich commented 1 year ago

In the meantime, I usually create a custom EntryPoint that appends the intercepted URI as query parameter such that I don't have to use a session at all (especially useful for sessionless auth tokens):

<?php

declare(strict_types=1);

namespace Some\Package\Security\Authentication;

use GuzzleHttp\Psr7\Query;
use GuzzleHttp\Psr7\Uri;
use Neos\Flow\Security\Authentication\EntryPointInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

final class EntryPoint implements EntryPointInterface
{

    /**
     * @var array<string, mixed>
     */
    private array $options = [];

    /**
     * @param array<string, mixed> $options
     * @return void
     */
    public function setOptions(array $options): void
    {
        $this->options = $options;
    }

    /**
     * @return array<string, mixed>
     */
    public function getOptions(): array
    {
        return $this->options;
    }

    public function startAuthentication(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $redirectUri = $request->getUri()->withPath($this->options['defaultRedirectUriPath'] ?? '/login');
        if ($request->getMethod() === 'GET') {
            $interceptedUri = new Uri($request->getUri()->getPath());
            if ($request->getUri()->getQuery() !== '') {
                $interceptedUri = $interceptedUri->withQuery($request->getUri()->getQuery());
            }
            $redirectUri = $redirectUri->withQuery(Query::build(['redirect' => (string)$interceptedUri]));
        } else {
            $redirectUri = $redirectUri->withQuery('');
        }
        return $response
            ->withStatus(303)
            ->withHeader('Location', (string)$redirectUri);
    }
}