diff --git a/README.md b/README.md
index b122b509..f09c0c59 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,10 @@ The module comes with some default SQL migrations which set up needed tables in
open the _Federation_ tab from your _SimpleSAMLphp_ installation and select the option _OpenID Connect Installation_
inside the _Tools_ section. Once there, all you need to do is press the _Install_ button and the schema will be created.
+Alternatively, in case of automatic / scripted deployments, you can run the 'install.php' script from the command line:
+
+ php modules/oidc/bin/install.php
+
### Relying Party (RP) Administration
The module lets you manage (create, read, update and delete) approved RPs from the module user interface itself.
diff --git a/bin/install.php b/bin/install.php
new file mode 100755
index 00000000..6028c7ec
--- /dev/null
+++ b/bin/install.php
@@ -0,0 +1,39 @@
+#!/usr/bin/env php
+isUpdated()) {
+ echo 'Database is up to date, skipping.' . PHP_EOL;
+ return 0;
+ }
+
+ echo 'Running database migrations.' . PHP_EOL;
+
+ $databaseMigration->migrate();
+
+ echo 'Done running migrations.';
+ return 0;
+} catch (Throwable $exception) {
+ echo 'There was an error while trying run database migrations: ' . $exception->getMessage();
+ return 1;
+}
diff --git a/composer.json b/composer.json
index 14530243..39f8b63b 100644
--- a/composer.json
+++ b/composer.json
@@ -50,7 +50,8 @@
},
"sort-packages": true,
"allow-plugins": {
- "simplesamlphp/composer-module-installer": true
+ "simplesamlphp/composer-module-installer": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true
},
"cache-dir": "build/composer"
},
diff --git a/psalm.xml b/psalm.xml
index ddac7608..0eb366f7 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -44,6 +44,9 @@
+
+
+
diff --git a/src/Forms/ClientForm.php b/src/Forms/ClientForm.php
index 5387e316..9b43be51 100644
--- a/src/Forms/ClientForm.php
+++ b/src/Forms/ClientForm.php
@@ -17,12 +17,16 @@
namespace SimpleSAML\Module\oidc\Forms;
use Exception;
+use Nette\Forms\Container;
use Nette\Forms\Form;
use SimpleSAML\Auth\Source;
use SimpleSAML\Module\oidc\ModuleConfig;
use SimpleSAML\Module\oidc\Forms\Controls\CsrfProtection;
use Traversable;
+/**
+ * @psalm-suppress PropertyNotSetInConstructor Raised for $httpRequest which is marked as internal, so won't handle.
+ */
class ClientForm extends Form
{
protected const TYPE_ARRAY = 'array';
@@ -123,7 +127,7 @@ protected function validateByMatchingRegex(
}
}
- public function getValues($returnType = null, ?array $controls = null): array
+ public function getValues(string|object|bool|null $returnType = null, ?array $controls = null): array
{
/** @var array $values */
$values = parent::getValues(self::TYPE_ARRAY);
@@ -157,7 +161,7 @@ public function getValues($returnType = null, ?array $controls = null): array
/**
* @throws Exception
*/
- public function setDefaults($data, bool $erase = false): ClientForm
+ public function setDefaults(object|array $data, bool $erase = false): static
{
if (! is_array($data)) {
if ($data instanceof Traversable) {
@@ -187,7 +191,9 @@ public function setDefaults($data, bool $erase = false): ClientForm
$scopes = is_array($data['scopes']) ? $data['scopes'] : [];
$data['scopes'] = array_intersect($scopes, array_keys($this->getScopes()));
- return parent::setDefaults($data, $erase);
+ parent::setDefaults($data, $erase);
+
+ return $this;
}
/**
@@ -203,7 +209,7 @@ protected function buildForm(): void
$this->onValidate[] = $this->validateBackChannelLogoutUri(...);
$this->setMethod('POST');
- $this->addComponent(new CsrfProtection('{oidc:client:csrf_error}'), Form::PROTECTOR_ID);
+ $this->addComponent(new CsrfProtection('{oidc:client:csrf_error}'), Form::ProtectorId);
$this->addText('name', '{oidc:client:name}')
->setMaxLength(255)
diff --git a/src/Forms/Controls/CsrfProtection.php b/src/Forms/Controls/CsrfProtection.php
index f7b81dd6..1935b4a9 100644
--- a/src/Forms/Controls/CsrfProtection.php
+++ b/src/Forms/Controls/CsrfProtection.php
@@ -21,6 +21,7 @@
use Nette\InvalidStateException;
use Nette\Utils\Random;
use SimpleSAML\Session;
+use Stringable;
class CsrfProtection extends BaseCsrfProtection
{
@@ -32,7 +33,7 @@ class CsrfProtection extends BaseCsrfProtection
/**
* @throws Exception
*/
- public function __construct(object|string $errorMessage)
+ public function __construct(string|Stringable|null $errorMessage)
{
// Instead of calling CsrfProtection parent class constructor, go to it's parent (HiddenField), and call
// its constructor. This is to avoid setting a Nette session in CsrfProtection parent, and use the SSP one.
diff --git a/src/Utils/ClaimTranslatorExtractor.php b/src/Utils/ClaimTranslatorExtractor.php
index fee1ebfb..e52fc404 100644
--- a/src/Utils/ClaimTranslatorExtractor.php
+++ b/src/Utils/ClaimTranslatorExtractor.php
@@ -197,7 +197,7 @@ public function addClaimSet(ClaimSetEntityInterface $claimSet): self
{
$scope = $claimSet->getScope();
- if (in_array($scope, $this->protectedClaims) && !empty($this->claimSets[$scope])) {
+ if (in_array($scope, $this->protectedClaims) && isset($this->claimSets[$scope])) {
throw OidcServerException::serverError(
sprintf("%s is a protected scope and is pre-defined by the OpenID Connect specification.", $scope)
);