Properly allow \OCP\Authentication\IApacheBackend to specify logout URL
Any `\OCP\Authentication\IApacheBackend` previously had to implement `getLogoutAttribute` which returns a string.
This string is directly injected into the logout `<a>` tag, so returning something like `href="foo"` would result
in `<a href="foo">`.
This is rather error prone and also in Nextcloud 12 broken as the logout entry has been moved with
054e161eb5
inside the navigation manager where one cannot simply inject attributes.
Thus this feature is broken in Nextcloud 12 which effectively leads to the bug described at nextcloud/user_saml#112,
people cannot logout anymore when using SAML using SLO. Basically in case of SAML you have a SLO url which redirects
you to the IdP and properly logs you out there as well.
Instead of monkey patching the Navigation manager I decided to instead change `\OCP\Authentication\IApacheBackend` to
use `\OCP\Authentication\IApacheBackend::getLogoutUrl` instead where it can return a string with the appropriate logout
URL. Since this functionality is only prominently used in the SAML plugin. Any custom app would need a small change but
I'm not aware of any and there's simply no way to fix this properly otherwise.
Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
This commit is contained in:
parent
231cffffb9
commit
a04feff9a7
|
@ -69,8 +69,8 @@ class TwoFactorChallengeController extends Controller {
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function getLogoutAttribute() {
|
protected function getLogoutUrl() {
|
||||||
return OC_User::getLogoutAttribute();
|
return OC_User::getLogoutUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,7 +89,7 @@ class TwoFactorChallengeController extends Controller {
|
||||||
'providers' => $providers,
|
'providers' => $providers,
|
||||||
'backupProvider' => $backupProvider,
|
'backupProvider' => $backupProvider,
|
||||||
'redirect_url' => $redirect_url,
|
'redirect_url' => $redirect_url,
|
||||||
'logout_attribute' => $this->getLogoutAttribute(),
|
'logout_url' => $this->getLogoutUrl(),
|
||||||
];
|
];
|
||||||
return new TemplateResponse($this->appName, 'twofactorselectchallenge', $data, 'guest');
|
return new TemplateResponse($this->appName, 'twofactorselectchallenge', $data, 'guest');
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ class TwoFactorChallengeController extends Controller {
|
||||||
'error_message' => $errorMessage,
|
'error_message' => $errorMessage,
|
||||||
'provider' => $provider,
|
'provider' => $provider,
|
||||||
'backupProvider' => $backupProvider,
|
'backupProvider' => $backupProvider,
|
||||||
'logout_attribute' => $this->getLogoutAttribute(),
|
'logout_url' => $this->getLogoutUrl(),
|
||||||
'redirect_url' => $redirect_url,
|
'redirect_url' => $redirect_url,
|
||||||
'template' => $tmpl->fetchPage(),
|
'template' => $tmpl->fetchPage(),
|
||||||
];
|
];
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
<p class="two-factor-link">
|
<p class="two-factor-link">
|
||||||
<a class="button" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel log in')) ?></a>
|
<a class="button" href="<?php print_unescaped($_['logout_url']); ?>"><?php p($l->t('Cancel log in')) ?></a>
|
||||||
<?php if (!is_null($_['backupProvider'])): ?>
|
<?php if (!is_null($_['backupProvider'])): ?>
|
||||||
<a class="button" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
|
<a class="button" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
|
||||||
[
|
[
|
||||||
|
|
|
@ -22,7 +22,7 @@ $template = $_['template'];
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php print_unescaped($template); ?>
|
<?php print_unescaped($template); ?>
|
||||||
<p class="two-factor-link">
|
<p class="two-factor-link">
|
||||||
<a class="button" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel log in')) ?></a>
|
<a class="button" href="<?php print_unescaped($_['logout_url']); ?>"><?php p($l->t('Cancel log in')) ?></a>
|
||||||
<?php if (!is_null($_['backupProvider'])): ?>
|
<?php if (!is_null($_['backupProvider'])): ?>
|
||||||
<a class="button" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
|
<a class="button" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
|
||||||
[
|
[
|
||||||
|
|
|
@ -187,18 +187,18 @@ class NavigationManager implements INavigationManager {
|
||||||
'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
|
'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Logout
|
$logoutUrl = \OC_User::getLogoutUrl();
|
||||||
$this->add([
|
if($logoutUrl !== '') {
|
||||||
'type' => 'settings',
|
// Logout
|
||||||
'id' => 'logout',
|
$this->add([
|
||||||
'order' => 99999,
|
'type' => 'settings',
|
||||||
'href' => $this->urlGenerator->linkToRouteAbsolute(
|
'id' => 'logout',
|
||||||
'core.login.logout',
|
'order' => 99999,
|
||||||
['requesttoken' => \OCP\Util::callRegister()]
|
'href' => $logoutUrl,
|
||||||
),
|
'name' => $l->t('Log out'),
|
||||||
'name' => $l->t('Log out'),
|
'icon' => $this->urlGenerator->imagePath('core', 'actions/logout.svg'),
|
||||||
'icon' => $this->urlGenerator->imagePath('core', 'actions/logout.svg'),
|
]);
|
||||||
]);
|
}
|
||||||
|
|
||||||
if ($this->isSubadmin()) {
|
if ($this->isSubadmin()) {
|
||||||
// User management
|
// User management
|
||||||
|
|
|
@ -281,16 +281,14 @@ class OC_User {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supplies an attribute to the logout hyperlink. The default behaviour
|
* Returns the current logout URL valid for the currently logged-in user
|
||||||
* is to return an href with '?logout=true' appended. However, it can
|
|
||||||
* supply any attribute(s) which are valid for <a>.
|
|
||||||
*
|
*
|
||||||
* @return string with one or more HTML attributes.
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function getLogoutAttribute() {
|
public static function getLogoutUrl() {
|
||||||
$backend = self::findFirstActiveUsedBackend();
|
$backend = self::findFirstActiveUsedBackend();
|
||||||
if ($backend) {
|
if ($backend) {
|
||||||
return $backend->getLogoutAttribute();
|
return $backend->getLogoutUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
$logoutUrl = \OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
$logoutUrl = \OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
||||||
|
@ -300,7 +298,7 @@ class OC_User {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
return 'href="'.$logoutUrl.'"';
|
return $logoutUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,21 +39,20 @@ namespace OCP\Authentication;
|
||||||
interface IApacheBackend {
|
interface IApacheBackend {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In case the user has been authenticated by Apache true is returned.
|
* In case the user has been authenticated by a module true is returned.
|
||||||
*
|
*
|
||||||
* @return boolean whether Apache reports a user as currently logged in.
|
* @return boolean whether the module reports a user as currently logged in.
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public function isSessionActive();
|
public function isSessionActive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an attribute which is added to the logout hyperlink. It can
|
* Gets the current logout URL
|
||||||
* supply any attribute(s) which are valid for <a>.
|
|
||||||
*
|
*
|
||||||
* @return string with one or more HTML attributes.
|
* @return string
|
||||||
* @since 6.0.0
|
* @since 12.0.3
|
||||||
*/
|
*/
|
||||||
public function getLogoutAttribute();
|
public function getLogoutUrl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the id of the current user
|
* Return the id of the current user
|
||||||
|
|
|
@ -76,10 +76,10 @@ class TwoFactorChallengeControllerTest extends TestCase {
|
||||||
$this->session,
|
$this->session,
|
||||||
$this->urlGenerator,
|
$this->urlGenerator,
|
||||||
])
|
])
|
||||||
->setMethods(['getLogoutAttribute'])
|
->setMethods(['getLogoutUrl'])
|
||||||
->getMock();
|
->getMock();
|
||||||
$this->controller->expects($this->any())
|
$this->controller->expects($this->any())
|
||||||
->method('getLogoutAttribute')
|
->method('getLogoutUrl')
|
||||||
->willReturn('logoutAttribute');
|
->willReturn('logoutAttribute');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ class TwoFactorChallengeControllerTest extends TestCase {
|
||||||
'providers' => $providers,
|
'providers' => $providers,
|
||||||
'backupProvider' => 'backup',
|
'backupProvider' => 'backup',
|
||||||
'redirect_url' => '/some/url',
|
'redirect_url' => '/some/url',
|
||||||
'logout_attribute' => 'logoutAttribute',
|
'logout_url' => 'logoutAttribute',
|
||||||
], 'guest');
|
], 'guest');
|
||||||
|
|
||||||
$this->assertEquals($expected, $this->controller->selectChallenge('/some/url'));
|
$this->assertEquals($expected, $this->controller->selectChallenge('/some/url'));
|
||||||
|
@ -155,7 +155,7 @@ class TwoFactorChallengeControllerTest extends TestCase {
|
||||||
'error' => true,
|
'error' => true,
|
||||||
'provider' => $provider,
|
'provider' => $provider,
|
||||||
'backupProvider' => $backupProvider,
|
'backupProvider' => $backupProvider,
|
||||||
'logout_attribute' => 'logoutAttribute',
|
'logout_url' => 'logoutAttribute',
|
||||||
'template' => '<html/>',
|
'template' => '<html/>',
|
||||||
'redirect_url' => '/re/dir/ect/url',
|
'redirect_url' => '/re/dir/ect/url',
|
||||||
'error_message' => null,
|
'error_message' => null,
|
||||||
|
|
|
@ -260,7 +260,7 @@ class NavigationManagerTest extends TestCase {
|
||||||
[
|
[
|
||||||
'id' => 'logout',
|
'id' => 'logout',
|
||||||
'order' => 99999,
|
'order' => 99999,
|
||||||
'href' => null,
|
'href' => \OC_User::getLogoutUrl(),
|
||||||
'icon' => '/apps/core/img/actions/logout.svg',
|
'icon' => '/apps/core/img/actions/logout.svg',
|
||||||
'name' => 'Log out',
|
'name' => 'Log out',
|
||||||
'active' => false,
|
'active' => false,
|
||||||
|
|
Loading…
Reference in New Issue