mirror of
https://github.com/netzbegruenung/user_saml.git
synced 2024-05-08 03:53:41 +02:00
7f7def4b7f
Some people seem to want to have a custom direct login text. This allows them to set it. For now only via occ. But maybe some day we also add a GUI component to it. Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
614 lines
19 KiB
PHP
614 lines
19 KiB
PHP
<?php
|
|
/**
|
|
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
|
|
* @copyright Copyright (c) 2018 Jean-Baptiste Pin <jibet.pin@gmail.com>
|
|
*
|
|
* @license GNU AGPL version 3 or any later version
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
namespace OCA\User_SAML\Controller;
|
|
|
|
use Firebase\JWT\JWT;
|
|
use OC\Core\Controller\ClientFlowLoginController;
|
|
use OC\Core\Controller\ClientFlowLoginV2Controller;
|
|
use OCA\User_SAML\Exceptions\NoUserFoundException;
|
|
use OCA\User_SAML\SAMLSettings;
|
|
use OCA\User_SAML\UserBackend;
|
|
use OCP\AppFramework\Controller;
|
|
use OCP\AppFramework\Http;
|
|
use OCP\IConfig;
|
|
use OCP\IL10N;
|
|
use OCP\ILogger;
|
|
use OCP\IRequest;
|
|
use OCP\ISession;
|
|
use OCP\IURLGenerator;
|
|
use OCP\IUser;
|
|
use OCP\IUserManager;
|
|
use OCP\IUserSession;
|
|
use OCP\Security\ICrypto;
|
|
use OneLogin\Saml2\Auth;
|
|
use OneLogin\Saml2\Error;
|
|
use OneLogin\Saml2\Settings;
|
|
use OneLogin\Saml2\ValidationError;
|
|
|
|
class SAMLController extends Controller {
|
|
/** @var ISession */
|
|
private $session;
|
|
/** @var IUserSession */
|
|
private $userSession;
|
|
/** @var SAMLSettings */
|
|
private $SAMLSettings;
|
|
/** @var UserBackend */
|
|
private $userBackend;
|
|
/** @var IConfig */
|
|
private $config;
|
|
/** @var IURLGenerator */
|
|
private $urlGenerator;
|
|
/** @var IUserManager */
|
|
private $userManager;
|
|
/** @var ILogger */
|
|
private $logger;
|
|
/** @var IL10N */
|
|
private $l;
|
|
/**
|
|
* @var ICrypto
|
|
*/
|
|
private $crypto;
|
|
|
|
/**
|
|
* @param string $appName
|
|
* @param IRequest $request
|
|
* @param ISession $session
|
|
* @param IUserSession $userSession
|
|
* @param SAMLSettings $SAMLSettings
|
|
* @param UserBackend $userBackend
|
|
* @param IConfig $config
|
|
* @param IURLGenerator $urlGenerator
|
|
* @param IUserManager $userManager
|
|
* @param ILogger $logger
|
|
* @param IL10N $l
|
|
*/
|
|
public function __construct($appName,
|
|
IRequest $request,
|
|
ISession $session,
|
|
IUserSession $userSession,
|
|
SAMLSettings $SAMLSettings,
|
|
UserBackend $userBackend,
|
|
IConfig $config,
|
|
IURLGenerator $urlGenerator,
|
|
IUserManager $userManager,
|
|
ILogger $logger,
|
|
IL10N $l,
|
|
ICrypto $crypto) {
|
|
parent::__construct($appName, $request);
|
|
$this->session = $session;
|
|
$this->userSession = $userSession;
|
|
$this->SAMLSettings = $SAMLSettings;
|
|
$this->userBackend = $userBackend;
|
|
$this->config = $config;
|
|
$this->urlGenerator = $urlGenerator;
|
|
$this->userManager = $userManager;
|
|
$this->logger = $logger;
|
|
$this->l = $l;
|
|
$this->crypto = $crypto;
|
|
}
|
|
|
|
/**
|
|
* @param array $auth
|
|
* @throws NoUserFoundException
|
|
*/
|
|
private function autoprovisionIfPossible(array $auth) {
|
|
|
|
$prefix = $this->SAMLSettings->getPrefix();
|
|
$uidMapping = $this->config->getAppValue('user_saml', $prefix . 'general-uid_mapping');
|
|
if(isset($auth[$uidMapping])) {
|
|
if(is_array($auth[$uidMapping])) {
|
|
$uid = $auth[$uidMapping][0];
|
|
} else {
|
|
$uid = $auth[$uidMapping];
|
|
}
|
|
|
|
// make sure that a valid UID is given
|
|
if (empty($uid)) {
|
|
$this->logger->error('Uid "' . $uid . '" is not a valid uid please check your attribute mapping', ['app' => $this->appName]);
|
|
throw new \InvalidArgumentException('No valid uid given, please check your attribute mapping. Given uid: ' . $uid);
|
|
}
|
|
|
|
$uid = $this->userBackend->testEncodedObjectGUID($uid);
|
|
|
|
// if this server acts as a global scale master and the user is not
|
|
// a local admin of the server we just create the user and continue
|
|
// no need to update additional attributes
|
|
$isGsEnabled = $this->config->getSystemValue('gs.enabled', false);
|
|
$isGsMaster = $this->config->getSystemValue('gss.mode', 'slave') === 'master';
|
|
$isGsMasterAdmin = in_array($uid, $this->config->getSystemValue('gss.master.admin', []));
|
|
if ($isGsEnabled && $isGsMaster && !$isGsMasterAdmin) {
|
|
$this->userBackend->createUserIfNotExists($uid);
|
|
return;
|
|
}
|
|
$userExists = $this->userManager->userExists($uid);
|
|
$autoProvisioningAllowed = $this->userBackend->autoprovisionAllowed();
|
|
if($userExists === true) {
|
|
if($autoProvisioningAllowed) {
|
|
$this->userBackend->updateAttributes($uid, $auth);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(!$userExists && !$autoProvisioningAllowed) {
|
|
// it is possible that the user was not logged in before and
|
|
// thus is not known to the original backend. A search can
|
|
// help with it and make the user known
|
|
$this->userManager->search($uid);
|
|
if($this->userManager->userExists($uid)) {
|
|
return;
|
|
}
|
|
throw new NoUserFoundException('Auto provisioning not allowed and user ' . $uid . ' does not exist');
|
|
} elseif(!$userExists && $autoProvisioningAllowed) {
|
|
$this->userBackend->createUserIfNotExists($uid, $auth);
|
|
$this->userBackend->updateAttributes($uid, $auth);
|
|
return;
|
|
}
|
|
}
|
|
|
|
throw new NoUserFoundException('IDP parameter for the UID (' . $uidMapping . ') not found. Possible parameters are: ' . json_encode(array_keys($auth)));
|
|
}
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @UseSession
|
|
* @OnlyUnauthenticatedUsers
|
|
* @NoCSRFRequired
|
|
*
|
|
* @param int $idp id of the idp
|
|
* @return Http\RedirectResponse
|
|
* @throws \Exception
|
|
*/
|
|
public function login($idp) {
|
|
$type = $this->config->getAppValue($this->appName, 'type');
|
|
switch($type) {
|
|
case 'saml':
|
|
$auth = new Auth($this->SAMLSettings->getOneLoginSettingsArray($idp));
|
|
$ssoUrl = $auth->login(null, [], false, false, true);
|
|
$response = new Http\RedirectResponse($ssoUrl);
|
|
|
|
// Small hack to make user_saml work with the loginflows
|
|
$flowData = [];
|
|
|
|
if ($this->session->get(ClientFlowLoginController::STATE_NAME) !== null) {
|
|
$flowData['cf1'] = $this->session->get(ClientFlowLoginController::STATE_NAME);
|
|
} else if ($this->session->get(ClientFlowLoginV2Controller::TOKEN_NAME) !== null) {
|
|
$flowData['cf2'] = [
|
|
'token' => $this->session->get(ClientFlowLoginV2Controller::TOKEN_NAME),
|
|
'state' => $this->session->get(ClientFlowLoginV2Controller::STATE_NAME),
|
|
];
|
|
}
|
|
|
|
// Pack data as JSON so we can properly extract it later
|
|
$data = json_encode([
|
|
'AuthNRequestID' => $auth->getLastRequestID(),
|
|
'OriginalUrl' => $this->request->getParam('originalUrl', ''),
|
|
'Idp' => $idp,
|
|
'flow' => $flowData,
|
|
]);
|
|
|
|
// Encrypt it
|
|
$data = $this->crypto->encrypt($data);
|
|
|
|
// And base64 encode it
|
|
$data = base64_encode($data);
|
|
|
|
$response->addCookie('saml_data', $data, null, 'None');
|
|
break;
|
|
case 'environment-variable':
|
|
$ssoUrl = $this->request->getParam('originalUrl', '');
|
|
if (empty($ssoUrl)) {
|
|
$ssoUrl = $this->urlGenerator->getAbsoluteURL('/');
|
|
}
|
|
$this->session->set('user_saml.samlUserData', $_SERVER);
|
|
try {
|
|
$this->autoprovisionIfPossible($this->session->get('user_saml.samlUserData'));
|
|
$user = $this->userManager->get($this->userBackend->getCurrentUserId());
|
|
if(!($user instanceof IUser)) {
|
|
throw new NoUserFoundException('User' . $this->userBackend->getCurrentUserId() . ' not valid or not found');
|
|
}
|
|
$user->updateLastLoginTimestamp();
|
|
} catch (NoUserFoundException $e) {
|
|
if ($e->getMessage()) {
|
|
$this->logger->warning('Error while trying to login using sso environment variable: ' . $e->getMessage(), ['app' => 'user_saml']);
|
|
}
|
|
$ssoUrl = $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned');
|
|
}
|
|
$response = new Http\RedirectResponse($ssoUrl);
|
|
break;
|
|
default:
|
|
throw new \Exception(
|
|
sprintf(
|
|
'Type of "%s" is not supported for user_saml',
|
|
$type
|
|
)
|
|
);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @NoCSRFRequired
|
|
* @param int $idp
|
|
* @return Http\DataDownloadResponse
|
|
* @throws Error
|
|
*/
|
|
public function getMetadata($idp) {
|
|
$settings = new Settings($this->SAMLSettings->getOneLoginSettingsArray($idp));
|
|
$metadata = $settings->getSPMetadata();
|
|
$errors = $settings->validateMetadata($metadata);
|
|
if (empty($errors)) {
|
|
return new Http\DataDownloadResponse($metadata, 'metadata.xml', 'text/xml');
|
|
} else {
|
|
throw new Error(
|
|
'Invalid SP metadata: '.implode(', ', $errors),
|
|
Error::METADATA_SP_INVALID
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @NoCSRFRequired
|
|
* @UseSession
|
|
* @OnlyUnauthenticatedUsers
|
|
* @NoSameSiteCookieRequired
|
|
*
|
|
* @return Http\RedirectResponse
|
|
* @throws Error
|
|
* @throws ValidationError
|
|
*/
|
|
public function assertionConsumerService(): Http\RedirectResponse {
|
|
// Fetch and decrypt the cookie
|
|
$cookie = $this->request->getCookie('saml_data');
|
|
if ($cookie === null) {
|
|
$this->logger->debug('Cookie was not present', ['app' => 'user_saml']);
|
|
return new Http\RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
|
|
}
|
|
|
|
// Base64 decode
|
|
$cookie = base64_decode($cookie);
|
|
|
|
// Decrypt and deserialize
|
|
try {
|
|
$cookie = $this->crypto->decrypt($cookie);
|
|
} catch (\Exception $e) {
|
|
$this->logger->debug('Could not decrypt SAML cookie', ['app' => 'user_saml']);
|
|
return new Http\RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
|
|
}
|
|
$data = json_decode($cookie, true);
|
|
|
|
if (isset($data['flow'])) {
|
|
if (isset($data['flow']['cf1'])) {
|
|
$this->session->set(ClientFlowLoginController::STATE_NAME, $data['flow']['cf1']);
|
|
} else if (isset($data['flow']['cf2'])) {
|
|
$this->session->set(ClientFlowLoginV2Controller::TOKEN_NAME, $data['flow']['cf2']['token']);
|
|
$this->session->set(ClientFlowLoginV2Controller::STATE_NAME, $data['flow']['cf2']['state']);
|
|
}
|
|
|
|
}
|
|
|
|
$AuthNRequestID = $data['AuthNRequestID'];
|
|
$idp = $data['Idp'];
|
|
// need to keep the IdP config ID during session lifetime (SAMLSettings::getPrefix)
|
|
$this->session->set('user_saml.Idp', $idp);
|
|
if(is_null($AuthNRequestID) || $AuthNRequestID === '' || is_null($idp)) {
|
|
$this->logger->debug('Invalid auth payload', ['app' => 'user_saml']);
|
|
return new Http\RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
|
|
}
|
|
|
|
$auth = new Auth($this->SAMLSettings->getOneLoginSettingsArray($idp));
|
|
$auth->processResponse($AuthNRequestID);
|
|
|
|
$this->logger->debug('Attributes send by the IDP: ' . json_encode($auth->getAttributes()));
|
|
|
|
$errors = $auth->getErrors();
|
|
|
|
if (!empty($errors)) {
|
|
foreach($errors as $error) {
|
|
$this->logger->error($error, ['app' => $this->appName]);
|
|
}
|
|
$this->logger->error($auth->getLastErrorReason(), ['app' => $this->appName]);
|
|
}
|
|
|
|
if (!$auth->isAuthenticated()) {
|
|
$this->logger->info('Auth failed', ['app' => $this->appName]);
|
|
$response = new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
|
|
$response->invalidateCookie('saml_data');
|
|
return $response;
|
|
}
|
|
|
|
// Check whether the user actually exists, if not redirect to an error page
|
|
// explaining the issue.
|
|
try {
|
|
$this->autoprovisionIfPossible($auth->getAttributes());
|
|
} catch (NoUserFoundException $e) {
|
|
$this->logger->error($e->getMessage(), ['app' => $this->appName]);
|
|
$response = new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
|
|
$response->invalidateCookie('saml_data');
|
|
return $response;
|
|
}
|
|
|
|
$this->session->set('user_saml.samlUserData', $auth->getAttributes());
|
|
$this->session->set('user_saml.samlNameId', $auth->getNameId());
|
|
$this->session->set('user_saml.samlNameIdFormat', $auth->getNameIdFormat());
|
|
$this->session->set('user_saml.samlNameIdNameQualifier', $auth->getNameIdNameQualifier());
|
|
$this->session->set('user_saml.samlNameIdSPNameQualifier', $auth->getNameIdSPNameQualifier());
|
|
$this->session->set('user_saml.samlSessionIndex', $auth->getSessionIndex());
|
|
$this->session->set('user_saml.samlSessionExpiration', $auth->getSessionExpiration());
|
|
try {
|
|
$user = $this->userManager->get($this->userBackend->getCurrentUserId());
|
|
if (!($user instanceof IUser)) {
|
|
throw new \InvalidArgumentException('User "' . $this->userBackend->getCurrentUserId() . '" is not valid');
|
|
}
|
|
$firstLogin = $user->updateLastLoginTimestamp();
|
|
if($firstLogin) {
|
|
$this->userBackend->initializeHomeDir($user->getUID());
|
|
}
|
|
} catch (\Exception $e) {
|
|
$this->logger->logException($e, ['app' => $this->appName]);
|
|
$response = new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
|
|
$response->invalidateCookie('saml_data');
|
|
return $response;
|
|
}
|
|
|
|
$originalUrl = $data['OriginalUrl'];
|
|
if($originalUrl !== null && $originalUrl !== '') {
|
|
$response = new Http\RedirectResponse($originalUrl);
|
|
} else {
|
|
$response = new Http\RedirectResponse(\OC::$server->getURLGenerator()->getAbsoluteURL('/'));
|
|
}
|
|
// The Nextcloud desktop client expects a cookie with the key of "_shibsession"
|
|
// to be there.
|
|
if($this->request->isUserAgent(['/^.*(mirall|csyncoC)\/.*$/'])) {
|
|
$response->addCookie('_shibsession_', 'authenticated');
|
|
}
|
|
|
|
$response->invalidateCookie('saml_data');
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @NoAdminRequired
|
|
* @NoCSRFRequired
|
|
*
|
|
* @return Http\RedirectResponse
|
|
* @throws Error
|
|
*/
|
|
public function singleLogoutService() {
|
|
$isFromGS = ($this->config->getSystemValue('gs.enabled', false) &&
|
|
$this->config->getSystemValue('gss.mode', '') === 'master');
|
|
|
|
// Some IDPs send the SLO request via POST, but OneLogin php-saml only handles GET.
|
|
// To hack around this issue we copy the request from _POST to _GET.
|
|
if(!empty($_POST['SAMLRequest'])) {
|
|
$_GET['SAMLRequest'] = $_POST['SAMLRequest'];
|
|
}
|
|
|
|
$isFromIDP = !$isFromGS && !empty($_GET['SAMLRequest']);
|
|
|
|
if($isFromIDP) {
|
|
// requests comes from the IDP so let it manage the logout
|
|
// (or raise Error if request is invalid)
|
|
$pass = True ;
|
|
} elseif($isFromGS) {
|
|
// Request is from master GlobalScale
|
|
// Request validity is check via a JSON Web Token
|
|
$jwt = $this->request->getParam('jwt', '');
|
|
$pass = $this->isValidJwt($jwt);
|
|
} else {
|
|
// standard request : need read CRSF check
|
|
$pass = $this->request->passesCSRFCheck();
|
|
}
|
|
|
|
if($pass) {
|
|
$idp = $this->session->get('user_saml.Idp');
|
|
$auth = new Auth($this->SAMLSettings->getOneLoginSettingsArray($idp));
|
|
$stay = true ; // $auth will return the redirect URL but won't perform the redirect himself
|
|
if($isFromIDP){
|
|
$keepLocalSession = true ; // do not let processSLO to delete the entire session. Let userSession->logout do the job
|
|
$targetUrl = $auth->processSLO($keepLocalSession, null, false, null, $stay);
|
|
} else {
|
|
// If request is not from IDP, we must send him the logout request
|
|
$parameters = array();
|
|
$nameId = $this->session->get('user_saml.samlNameId');
|
|
$nameIdFormat = $this->session->get('user_saml.samlNameIdFormat');
|
|
$nameIdNameQualifier = $this->session->get('user_saml.samlNameIdNameQualifier');
|
|
$nameIdSPNameQualifier = $this->session->get('user_saml.samlNameIdSPNameQualifier');
|
|
$sessionIndex = $this->session->get('user_saml.samlSessionIndex');
|
|
try {
|
|
$targetUrl = $auth->logout(null, [], $nameId, $sessionIndex, $stay, $nameIdFormat, $nameIdNameQualifier, $nameIdSPNameQualifier);
|
|
} catch (Error $e) {
|
|
$this->logger->logException($e, ['level' => ILogger::WARN]);
|
|
$this->userSession->logout();
|
|
}
|
|
}
|
|
if(!empty($targetUrl) && !$auth->getLastErrorReason()){
|
|
$this->userSession->logout();
|
|
}
|
|
}
|
|
if(empty($targetUrl)){
|
|
$targetUrl = $this->urlGenerator->getAbsoluteURL('/');
|
|
}
|
|
|
|
return new Http\RedirectResponse($targetUrl);
|
|
}
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @NoCSRFRequired
|
|
* @OnlyUnauthenticatedUsers
|
|
*/
|
|
public function notProvisioned() {
|
|
return new Http\TemplateResponse($this->appName, 'notProvisioned', [], 'guest');
|
|
}
|
|
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @NoCSRFRequired
|
|
* @OnlyUnauthenticatedUsers
|
|
* @param string $message
|
|
* @return Http\TemplateResponse
|
|
*/
|
|
public function genericError($message) {
|
|
if (empty($message)) {
|
|
$message = $this->l->t('Unknown error, please check the log file for more details.');
|
|
}
|
|
return new Http\TemplateResponse($this->appName, 'error', ['message' => $message], 'guest');
|
|
}
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @NoCSRFRequired
|
|
* @OnlyUnauthenticatedUsers
|
|
* @param string $redirectUrl
|
|
* @return Http\TemplateResponse
|
|
*/
|
|
public function selectUserBackEnd($redirectUrl) {
|
|
|
|
$attributes = ['loginUrls' => []];
|
|
|
|
if ($this->SAMLSettings->allowMultipleUserBackEnds()) {
|
|
$displayName = $this->l->t('Direct log in');
|
|
|
|
$customDisplayName = $this->config->getAppValue('user_saml', 'directLoginName', '');
|
|
if ($customDisplayName !== '') {
|
|
$displayName = $customDisplayName;
|
|
}
|
|
|
|
$attributes['loginUrls']['directLogin'] = [
|
|
'url' => $this->getDirectLoginUrl($redirectUrl),
|
|
'display-name' => $displayName,
|
|
];
|
|
}
|
|
|
|
$attributes['loginUrls']['ssoLogin'] = $this->getIdps($redirectUrl);
|
|
|
|
$attributes['useCombobox'] = count($attributes['loginUrls']['ssoLogin']) > 4 ? true : false;
|
|
|
|
|
|
return new Http\TemplateResponse($this->appName, 'selectUserBackEnd', $attributes, 'guest');
|
|
}
|
|
|
|
/**
|
|
* get the IdPs showed at the login page
|
|
*
|
|
* @param $redirectUrl
|
|
* @return array
|
|
*/
|
|
private function getIdps($redirectUrl) {
|
|
$result = [];
|
|
$idps = $this->SAMLSettings->getListOfIdps();
|
|
foreach ($idps as $idpId => $displayName) {
|
|
$result[] = [
|
|
'url' => $this->getSSOUrl($redirectUrl, $idpId),
|
|
'display-name' => $this->getSSODisplayName($displayName),
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* get SSO URL
|
|
*
|
|
* @param $redirectUrl
|
|
* @param idp identifier
|
|
* @return string
|
|
*/
|
|
private function getSSOUrl($redirectUrl, $idp) {
|
|
|
|
$originalUrl = '';
|
|
if(!empty($redirectUrl)) {
|
|
$originalUrl = $this->urlGenerator->getAbsoluteURL($redirectUrl);
|
|
}
|
|
|
|
|
|
$csrfToken = \OC::$server->getCsrfTokenManager()->getToken();
|
|
$ssoUrl = $this->urlGenerator->linkToRouteAbsolute(
|
|
'user_saml.SAML.login',
|
|
[
|
|
'requesttoken' => $csrfToken->getEncryptedValue(),
|
|
'originalUrl' => $originalUrl,
|
|
'idp' => $idp
|
|
]
|
|
);
|
|
|
|
return $ssoUrl;
|
|
|
|
}
|
|
|
|
/**
|
|
* return the display name of the SSO identity provider
|
|
*
|
|
* @param $displayName
|
|
* @return string
|
|
*/
|
|
protected function getSSODisplayName($displayName) {
|
|
if (empty($displayName)) {
|
|
$displayName = $this->l->t('SSO & SAML log in');
|
|
}
|
|
|
|
return $displayName;
|
|
}
|
|
|
|
/**
|
|
* get Nextcloud login URL
|
|
*
|
|
* @return string
|
|
*/
|
|
private function getDirectLoginUrl($redirectUrl) {
|
|
$directUrl = $this->urlGenerator->linkToRouteAbsolute('core.login.tryLogin', [
|
|
'direct' => '1',
|
|
'redirect_url' => $redirectUrl,
|
|
]);
|
|
return $directUrl;
|
|
}
|
|
|
|
private function isValidJwt($jwt) {
|
|
try {
|
|
$key = $this->config->getSystemValue('gss.jwt.key', '');
|
|
JWT::decode($jwt, $key, ['HS256']);
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @PublicPage
|
|
* @NoCSRFRequired
|
|
*
|
|
* @return Http\TemplateResponse
|
|
*/
|
|
public function base() {
|
|
$message = $this->l->t('This page should not be visited directly.');
|
|
return new Http\TemplateResponse($this->appName, 'error', ['message' => $message], 'guest');
|
|
}
|
|
|
|
}
|