diff --git a/controller/Auth/BaseAuthInterface.php b/controller/Auth/BaseAuthInterface.php new file mode 100644 index 000000000..4c3918b4b --- /dev/null +++ b/controller/Auth/BaseAuthInterface.php @@ -0,0 +1,46 @@ +" ; + * skosmos:authProviderAuthEntity "" . + */ +class SimpleSamlPHP implements BaseAuthInterface { + + /** + * @var Model + */ + private $model; + + /** + * Placeholder of the SimpleSamlPHP authentication entity. + * + * @var string|null + */ + private $authEntity; + + /** + * The configured application URL + * + * @var string + */ + private $baseHref; + + /** + * @param Model $model + */ + public function __construct(Controller $controller) { + $this->model = $controller->model; + $this->baseHref = $controller->getBaseHref(); + } + + /** + * @inheritDoc + */ + public function validate(): bool { + $authDirectory = $this->model->getConfig()->getLiteral( 'skosmos:authProviderIncludeDirectory' ); + if (!$authDirectory) { + return false; + } + + $authEntity = $this->model->getConfig()->getLiteral( 'skosmos:authProviderAuthEntity' ); + if (!$authEntity) { + return false; + } else { + $this->authEntity = $authEntity; + } + + $sspAutoloader = $authDirectory . DIRECTORY_SEPARATOR . 'lib/_autoload.php'; + if (!file_exists($sspAutoloader)) { + return false; + } else { + require $sspAutoloader; + } + + return true; + } + + /** + * @inheritDoc + */ + public function isSignedIn(): bool { + return $this->getSessionFromRequest()->isValid($this->authEntity); + } + + /** + * @inheritDoc + */ + public function signIn() { + $this->getAuthenticationSource()->requireAuth([ + 'ReturnTo' => $this->baseHref + ]); + } + + /** + * @inheritDoc + */ + public function signOut() { + $this->getAuthenticationSource()->logout([ + 'ReturnTo' => $this->baseHref + ]); + } + + /** + * @inheritDoc + */ + public function getUserAttributes(): array { + if ($this->isSignedIn()) { + return []; + } + return [ + 'auth_source' => $this->authEntity, + 'attributes' => $this->getAuthenticationSource()->getAttributes() + ]; + } + + /** + * @return \SimpleSAML\Auth\Simple + */ + private function getAuthenticationSource() { + return new SimpleSAML\Auth\Simple($this->authEntity); + } + + /** + * @return SimpleSAML\Session::getSessionFromRequest() + */ + private function getSessionFromRequest() { + return SimpleSAML\Session::getSessionFromRequest(); + } + +} \ No newline at end of file diff --git a/controller/Controller.php b/controller/Controller.php index bb0e09485..78cfa113a 100644 --- a/controller/Controller.php +++ b/controller/Controller.php @@ -45,8 +45,47 @@ public function __construct($model) $this->languages[$langcode]['name'] = gettext('in_this_language'); $this->languages[$langcode]['lemma'] = Punic\Language::getName($langcode, $langcode); } + + // Check if we have an authentication provider configured + // If so; check if the configured provider is actually a class we can use + if (($authProvider = $this->model->getConfig()->getAuthenticationProvider()) && class_exists($authProvider)) { + $this->invokeAuthenticationLayer(new $authProvider($this)); + } } + /** + * Invokes the authentication layer + * + * @param BaseAuthInterface $provider + * @return void + */ + private function invokeAuthenticationLayer(BaseAuthInterface $authProvider) { + + // Validate the authentication provider's configuration parameters + if ($authProvider->validate()) { + + // We don't have a valid user session; so sign in the user + if (!$authProvider->isSignedIn()) { + $authProvider->signIn(); + + // We have a valid session for this user; see if it wants to do anything.. + } elseif (isset($_GET['auth_do'])) { + $action = $_GET['auth_do']; + + // Signout + if ($action === 'signout') { + $authProvider->signOut(); + + // Retrieve user info + } else if ($action === 'info') { + echo json_encode($authProvider->getUserAttributes()); + $this->sendHeader('Content-Type: application/json'); + exit(); + } + } + } + } + /** * Sets the locale language properties from the parameter (used by gettext and some Model classes). * @param string $lang language parameter eg. 'fi' for Finnish. diff --git a/model/BaseConfig.php b/model/BaseConfig.php index befa2b8aa..e79ad7faf 100644 --- a/model/BaseConfig.php +++ b/model/BaseConfig.php @@ -13,7 +13,7 @@ abstract class BaseConfig extends DataObject * @param boolean $default the default value if the value is not set in configuration * @return boolean the boolean value for the given property, or the default value if not found */ - protected function getBoolean($property, $default = false) + public function getBoolean($property, $default = false) { $val = $this->getResource()->getLiteral($property); if ($val) { @@ -44,7 +44,7 @@ protected function getResources($property) * @param string $lang preferred language for the literal * @return string string value for the given property, or the default value if not found */ - protected function getLiteral($property, $default=null, $lang=null) + public function getLiteral($property, $default=null, $lang=null) { if (!isset($lang)) { $lang = $this->getEnvLang(); diff --git a/model/GlobalConfig.php b/model/GlobalConfig.php index 7a1719262..24e2e7616 100644 --- a/model/GlobalConfig.php +++ b/model/GlobalConfig.php @@ -360,4 +360,11 @@ public function getCollationEnabled() { return $this->getBoolean('skosmos:sparqlCollationEnabled', FALSE); } + + /** + * @return string|null + */ + public function getAuthenticationProvider() { + return $this->getLiteral('skosmos:authenticationProvider', false); + } }