mirror of
https://github.com/netzbegruenung/user_saml.git
synced 2024-05-02 17:14:53 +02:00
Make work with posts and cookies again
Requires https://github.com/nextcloud/server/pull/21479 to fully work. Basically don't save this info in the session (which is lax by default starting with NC19 but also soon with new chromes and firefox). We now save it is a cookie that is set to None. This is the best we can do I think. Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
parent
a15bc52cbb
commit
f5304f6757
|
@ -37,6 +37,7 @@ use OCP\IURLGenerator;
|
||||||
use OCP\IUser;
|
use OCP\IUser;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
use OCP\IUserSession;
|
use OCP\IUserSession;
|
||||||
|
use OCP\Security\ICrypto;
|
||||||
use OneLogin\Saml2\Auth;
|
use OneLogin\Saml2\Auth;
|
||||||
use OneLogin\Saml2\Error;
|
use OneLogin\Saml2\Error;
|
||||||
use OneLogin\Saml2\Settings;
|
use OneLogin\Saml2\Settings;
|
||||||
|
@ -61,6 +62,10 @@ class SAMLController extends Controller {
|
||||||
private $logger;
|
private $logger;
|
||||||
/** @var IL10N */
|
/** @var IL10N */
|
||||||
private $l;
|
private $l;
|
||||||
|
/**
|
||||||
|
* @var ICrypto
|
||||||
|
*/
|
||||||
|
private $crypto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $appName
|
* @param string $appName
|
||||||
|
@ -85,7 +90,8 @@ class SAMLController extends Controller {
|
||||||
IURLGenerator $urlGenerator,
|
IURLGenerator $urlGenerator,
|
||||||
IUserManager $userManager,
|
IUserManager $userManager,
|
||||||
ILogger $logger,
|
ILogger $logger,
|
||||||
IL10N $l) {
|
IL10N $l,
|
||||||
|
ICrypto $crypto) {
|
||||||
parent::__construct($appName, $request);
|
parent::__construct($appName, $request);
|
||||||
$this->session = $session;
|
$this->session = $session;
|
||||||
$this->userSession = $userSession;
|
$this->userSession = $userSession;
|
||||||
|
@ -96,6 +102,7 @@ class SAMLController extends Controller {
|
||||||
$this->userManager = $userManager;
|
$this->userManager = $userManager;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->l = $l;
|
$this->l = $l;
|
||||||
|
$this->crypto = $crypto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,9 +182,22 @@ class SAMLController extends Controller {
|
||||||
case 'saml':
|
case 'saml':
|
||||||
$auth = new Auth($this->SAMLSettings->getOneLoginSettingsArray($idp));
|
$auth = new Auth($this->SAMLSettings->getOneLoginSettingsArray($idp));
|
||||||
$ssoUrl = $auth->login(null, [], false, false, true);
|
$ssoUrl = $auth->login(null, [], false, false, true);
|
||||||
$this->session->set('user_saml.AuthNRequestID', $auth->getLastRequestID());
|
$response = new Http\RedirectResponse($ssoUrl);
|
||||||
$this->session->set('user_saml.OriginalUrl', $this->request->getParam('originalUrl', ''));
|
|
||||||
$this->session->set('user_saml.Idp', $idp);
|
// Pack data as JSON so we can properly extract it later
|
||||||
|
$data = json_encode([
|
||||||
|
'AuthNRequestID' => $auth->getLastRequestID(),
|
||||||
|
'OriginalUrl' => $this->request->getParam('originalUrl', ''),
|
||||||
|
'Idp' => $idp
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Encrypt it
|
||||||
|
$data = $this->crypto->encrypt($data);
|
||||||
|
|
||||||
|
// And base64 encode it
|
||||||
|
$data = base64_encode($data);
|
||||||
|
|
||||||
|
$response->addCookie('saml_data', $data, null, 'None');
|
||||||
break;
|
break;
|
||||||
case 'environment-variable':
|
case 'environment-variable':
|
||||||
$ssoUrl = $this->request->getParam('originalUrl', '');
|
$ssoUrl = $this->request->getParam('originalUrl', '');
|
||||||
|
@ -198,6 +218,7 @@ class SAMLController extends Controller {
|
||||||
}
|
}
|
||||||
$ssoUrl = $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned');
|
$ssoUrl = $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned');
|
||||||
}
|
}
|
||||||
|
$response = new Http\RedirectResponse($ssoUrl);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \Exception(
|
throw new \Exception(
|
||||||
|
@ -208,7 +229,7 @@ class SAMLController extends Controller {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Http\RedirectResponse($ssoUrl);
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -244,8 +265,26 @@ class SAMLController extends Controller {
|
||||||
* @throws ValidationError
|
* @throws ValidationError
|
||||||
*/
|
*/
|
||||||
public function assertionConsumerService() {
|
public function assertionConsumerService() {
|
||||||
$AuthNRequestID = $this->session->get('user_saml.AuthNRequestID');
|
// Fetch and decrypt the cookie
|
||||||
$idp = $this->session->get('user_saml.Idp');
|
$cookie = $this->request->getCookie('saml_data');
|
||||||
|
if ($cookie === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base64 decode
|
||||||
|
$cookie = base64_decode($cookie);
|
||||||
|
|
||||||
|
// Decrypt and deserialize
|
||||||
|
try {
|
||||||
|
$cookie = $this->crypto->decrypt($cookie);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$data = json_decode($cookie, true);
|
||||||
|
|
||||||
|
|
||||||
|
$AuthNRequestID = $data['AuthNRequestID'];
|
||||||
|
$idp = $data['Idp'];
|
||||||
if(is_null($AuthNRequestID) || $AuthNRequestID === '' || is_null($idp)) {
|
if(is_null($AuthNRequestID) || $AuthNRequestID === '' || is_null($idp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -299,18 +338,19 @@ class SAMLController extends Controller {
|
||||||
return new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
|
return new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$originalUrl = $this->session->get('user_saml.OriginalUrl');
|
$originalUrl = $data['OriginalUrl'];
|
||||||
if($originalUrl !== null && $originalUrl !== '') {
|
if($originalUrl !== null && $originalUrl !== '') {
|
||||||
$response = new Http\RedirectResponse($originalUrl);
|
$response = new Http\RedirectResponse($originalUrl);
|
||||||
} else {
|
} else {
|
||||||
$response = new Http\RedirectResponse(\OC::$server->getURLGenerator()->getAbsoluteURL('/'));
|
$response = new Http\RedirectResponse(\OC::$server->getURLGenerator()->getAbsoluteURL('/'));
|
||||||
}
|
}
|
||||||
$this->session->remove('user_saml.OriginalUrl');
|
|
||||||
// The Nextcloud desktop client expects a cookie with the key of "_shibsession"
|
// The Nextcloud desktop client expects a cookie with the key of "_shibsession"
|
||||||
// to be there.
|
// to be there.
|
||||||
if($this->request->isUserAgent(['/^.*(mirall|csyncoC)\/.*$/'])) {
|
if($this->request->isUserAgent(['/^.*(mirall|csyncoC)\/.*$/'])) {
|
||||||
$response->addCookie('_shibsession_', 'authenticated');
|
$response->addCookie('_shibsession_', 'authenticated');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$response->invalidateCookie('saml_data');
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ use OCP\IURLGenerator;
|
||||||
use OCP\IUser;
|
use OCP\IUser;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
use OCP\IUserSession;
|
use OCP\IUserSession;
|
||||||
|
use OCP\Security\ICrypto;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use Test\TestCase;
|
use Test\TestCase;
|
||||||
|
|
||||||
class SAMLControllerTest extends TestCase {
|
class SAMLControllerTest extends TestCase {
|
||||||
|
@ -58,6 +60,8 @@ class SAMLControllerTest extends TestCase {
|
||||||
private $logger;
|
private $logger;
|
||||||
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
|
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $l;
|
private $l;
|
||||||
|
/** @var ICrypto|MockObject */
|
||||||
|
private $crypto;
|
||||||
/** @var SAMLController */
|
/** @var SAMLController */
|
||||||
private $samlController;
|
private $samlController;
|
||||||
|
|
||||||
|
@ -77,6 +81,7 @@ class SAMLControllerTest extends TestCase {
|
||||||
$this->userManager = $this->createMock(IUserManager::class);
|
$this->userManager = $this->createMock(IUserManager::class);
|
||||||
$this->logger = $this->createMock(ILogger::class);
|
$this->logger = $this->createMock(ILogger::class);
|
||||||
$this->l = $this->createMock(IL10N::class);
|
$this->l = $this->createMock(IL10N::class);
|
||||||
|
$this->crypto = $this->createMock(ICrypto::class);
|
||||||
|
|
||||||
$this->l->expects($this->any())->method('t')->willReturnCallback(
|
$this->l->expects($this->any())->method('t')->willReturnCallback(
|
||||||
function($param) {
|
function($param) {
|
||||||
|
@ -100,7 +105,8 @@ class SAMLControllerTest extends TestCase {
|
||||||
$this->urlGenerator,
|
$this->urlGenerator,
|
||||||
$this->userManager,
|
$this->userManager,
|
||||||
$this->logger,
|
$this->logger,
|
||||||
$this->l
|
$this->l,
|
||||||
|
$this->crypto
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue