Skip to content

Commit

Permalink
[Security] SwitchUser: add dynamic redirection path
Browse files Browse the repository at this point in the history
  • Loading branch information
94noni committed Aug 22, 2024
1 parent 4f21f7c commit 75fb520
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Symfony/Component/Security/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ CHANGELOG

The CHANGELOG for version 5.4 and newer can be found in the security sub-packages (e.g. `Http/`).

7.2
---

* Add a request query string `_redirect_path` handled in `SwitchUserListener` to allow controlling the redirection path post switching user. It takes precedence over the `SwitchUserListener $targetRoute` configured value if any.

5.3
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ public function supports(Request $request): ?bool

$request->attributes->set('_switch_user_username', $username);

$redirectPath = $request->query->get('_redirect_path', '');
if (!str_starts_with($redirectPath, '/')) {
$redirectPath = null;
}
$request->attributes->set('_switch_user_redirect_path', $redirectPath);

return true;
}

Expand All @@ -92,6 +98,9 @@ public function authenticate(RequestEvent $event): void
$username = $request->attributes->get('_switch_user_username');
$request->attributes->remove('_switch_user_username');

$redirectPath = $request->attributes->get('_switch_user_redirect_path');
$request->attributes->remove('_switch_user_redirect_path');

if (null === $this->tokenStorage->getToken()) {
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
}
Expand All @@ -109,8 +118,9 @@ public function authenticate(RequestEvent $event): void

if (!$this->stateless) {
$request->query->remove($this->usernameParameter);
$request->query->remove('_redirect_path');
$request->server->set('QUERY_STRING', http_build_query($request->query->all(), '', '&'));
$response = new RedirectResponse($this->urlGenerator && $this->targetRoute ? $this->urlGenerator->generate($this->targetRoute) : $request->getUri(), 302);
$response = new RedirectResponse($redirectPath ?? ($this->urlGenerator && $this->targetRoute ? $this->urlGenerator->generate($this->targetRoute) : $request->getUri()), 302);

$event->setResponse($response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,4 +369,27 @@ public function testSwitchUserRefreshesOriginalToken()
$listener = new SwitchUserListener($this->tokenStorage, $userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager, null, '_switch_user', 'ROLE_ALLOWED_TO_SWITCH', $dispatcher);
$listener($this->event);
}

public function testSwitchUserWithQueryRedirectionPath()
{
$token = new UsernamePasswordToken(new InMemoryUser('username', '', ['ROLE_FOO']), 'key', ['ROLE_FOO']);

$this->tokenStorage->setToken($token);
$this->request->query->set('_switch_user', 'kuba');
$this->request->query->set('_redirect_path', '/my-account/kuba');

$this->accessDecisionManager->expects($this->once())
->method('decide')->with($token, ['ROLE_ALLOWED_TO_SWITCH'], $this->callback(fn ($user) => 'kuba' === $user->getUserIdentifier()))
->willReturn(true);

$this->userChecker->expects($this->once())
->method('checkPostAuth')->with($this->callback(fn ($user) => 'kuba' === $user->getUserIdentifier()));

$listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
$listener($this->event);

$this->assertSame([], $this->request->query->all());
$this->assertInstanceOf(RedirectResponse::class, $this->event->getResponse());
$this->assertSame('/my-account/kuba', $this->event->getResponse()->getTargetUrl());
}
}

0 comments on commit 75fb520

Please sign in to comment.