Open jirinapravnik opened 1 year ago
There is a workaround you could to on your side.
When user clicks /saml/login
you can save to session their current route.
You can then extend the DefaultAuthenticationSuccessHandler
if you don't have your own.
Then load the route from session and return a RedirectResponse
@jirinapravnik hi!
If your /account/me
page there is behind the firewall that use this bundle, you'll be redirected for it automatically after successful log in.
\Symfony\Component\Security\Http\Firewall\ExceptionListener
persist the request URI at the moment when redirects you for login and then we pass this URI to the SAML server, which returns it in RelayState
(if not, this URI will still be used by SamlAuthenticationSuccessHandler).
I had the same sort of requirement. My application allows anonymous browsing of many pages and provides extra functionality (bookmarking items) when a user is logged in. I wish to provide login links on each page that bring the user back to the previous page they were looking at after login.
I was able to do this by adding a controller to my application that creates a session and then executes the bundle's login controller:
<?php
namespace App\Controller;
use Nbgrp\OneloginSamlBundle\Controller\Login as NbgrpLogin;
use OneLogin\Saml2\Auth;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\FirewallMapInterface;
class Login extends AbstractController
{
public function __construct(
private readonly FirewallMapInterface $firewallMap,
) {}
#[Route('/login', name: 'login')]
public function __invoke(Request $request, Auth $auth): RedirectResponse
{
if ($request->get('returnTo')) {
$returnTo = $request->get('returnTo');
// Ensure that returnTo is the same as our host.
// This could be more thorough checking to ensure that the URL
// is below the application's base URL or take into account
// other routing details, but this seems like a basic sanity check.
if ($request->getHttpHost() != parse_url($returnTo, PHP_URL_HOST)) {
throw new \InvalidArgumentException("returnTo must match the current host");
}
// Set the session variable that the Nbgrp/OneloginSamlBundle is
// looking for.
$firewallName = $this->firewallMap->getFirewallConfig($request)?->getName();
if (!$firewallName) {
throw new ServiceUnavailableHttpException(message: 'Unknown firewall.');
}
$request->getSession()->set('_security.'.$firewallName.'.target_path', $returnTo);
}
// Execute the Nbgrp/OneloginSamlBundle's login action.
$nbgrpLogin = new NbgrpLogin($this->firewallMap);
return $nbgrpLogin($request, $auth);
}
}
I can then put links in my template like the following:
{% if is_granted('IS_AUTHENTICATED_FULLY') %}
<h4>Bookmark this item</h4>
...
{% else %}
<a href="{{ url("login", {returnTo: app.request.uri }) }}">Log-in to save</a>
{% endif %}
This technique has the desired effect of redirecting the user back to their previous page after login.
The one downside to this technique (and reliance on the session generally) is that if a user follows a login link but fails the authentication process and returns to the application, they will have a session cookie set which will prevent them from utilizing cached responses for anonymous visitors as stored in a reverse-proxy cache.
Maybe there are alternative ways of passing a return-URL into the RelayState
that gets sent to the IdP....
Is it possible to set returnTo parametr via $_GET or something like that?
I have url /saml/login. I want to redirect always from page, where I click on login button. I would like to set something like /saml/login?returnTo=/account/me and after login (or logout) get to page /account/me etc.