From 8efb228e7e5a3cf345200900ceb05f6b6bf6701e Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 3 May 2024 14:54:19 +0200 Subject: [PATCH 01/31] Added support for Key # Conflicts: # CHANGELOG.md # composer.json # os2forms_nemlogin_openid_connect.info.yml # src/Controller/OpenIDConnectController.php --- .github/workflows/pr.yaml | 4 +- .gitignore | 1 + .markdownlint.jsonc | 13 ++++ CHANGELOG.md | 3 + README.md | 32 ++++++++ composer.json | 65 ++++++++++------ os2forms_nemlogin_openid_connect.info.yml | 1 + src/Controller/OpenIDConnectController.php | 29 +++++-- .../NemloginAuthProvider/OpenIDConnect.php | 77 ++++++++++--------- 9 files changed, 158 insertions(+), 67 deletions(-) create mode 100644 .markdownlint.jsonc diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 01f9446..d85d90d 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -112,9 +112,9 @@ jobs: - name: Install Dependencies run: | composer install --no-interaction --no-progress - - name: twigcs + - name: twig-cs-fixer run: | - composer coding-standards-check/twigcs + composer coding-standards-check/twig-cs-fixer php-code-analysis: name: PHP code analysis diff --git a/.gitignore b/.gitignore index f782610..52dd39d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ vendor composer.lock node_modules yarn.lock +*.cache diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 0000000..a28c580 --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,13 @@ +{ + "default": true, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md + "line-length": { + "line_length": 120, + "code_blocks": false, + "tables": false + }, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md + "no-duplicate-heading": { + "siblings_only": true + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md index d2e0be7..9384ccc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +* [PR-19](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/19) + Added support for Key + ## [2.2.0] 2024-12-10 * Added audit logging via `os2web/os2web_audit`. diff --git a/README.md b/README.md index 87273af..3cb862e 100644 --- a/README.md +++ b/README.md @@ -94,5 +94,37 @@ $settings['os2forms_nemlogin_openid_connect']['another-plugin-id']['local_test_u 'name' => 'User 87', ], ]; +``` + +## Coding standards + +Our coding are checked by GitHub Actions (cf. [.github/workflows/pr.yml](.github/workflows/pr.yml)). Use the commands +below to run the checks locally. + +### PHP + +```shell +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer install +# Fix (some) coding standards issues +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-apply +# Check that code adheres to the coding standards +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check +``` + +### Markdown + +```shell +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' --fix +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' +``` + +## Code analysis + +We use [PHPStan](https://phpstan.org/) for static code analysis. + +Running statis code analysis on a standalone Drupal module is a bit tricky, so we use a helper script to run the +analysis: +```shell +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm ./scripts/code-analysis ``` diff --git a/composer.json b/composer.json index a14c028..e23f697 100644 --- a/composer.json +++ b/composer.json @@ -1,11 +1,25 @@ { "name": "itk-dev/os2forms_nemlogin_openid_connect", - "type": "drupal-module", - "license": "MIT", "description": "os2forms_nemlogin_openid_connect", + "license": "MIT", + "type": "drupal-module", "keywords": [], "homepage": "https://www.drupal.org/project/os2forms_nemlogin_openid_connect", - "minimum-stability": "dev", + "require": { + "drupal/webform": "^6.0", + "itk-dev/drupal_psr6_cache": "^1.0", + "itk-dev/openid-connect": "^3.1", + "os2web/os2web_key": "^1.0", + "os2web/os2web_nemlogin": "^1.2", + "symfony/options-resolver": "^5.4 || ^6.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "drupal/coder": "^8.3", + "ergebnis/composer-normalize": "^2.42", + "mglaman/drupal-check": "^1.4", + "vincentlanglet/twig-cs-fixer": "^2.8" + }, "repositories": [ { "type": "composer", @@ -27,37 +41,44 @@ "mglaman/phpstan-drupal": "~1.2.0", "friendsoftwig/twigcs": "^6.0" }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "allow-plugins": { + "cweagans/composer-patches": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "mglaman/composer-drupal-lenient": true, + "simplesamlphp/composer-module-installer": true, + "zaporylie/composer-drupal-optimizations": true + } + }, "scripts": { + "code-analysis": [ + "@code-analysis/drupal-check" + ], "code-analysis/drupal-check": [ "drupal-check --deprecations --analysis --exclude-dir=vendor *.* src" ], - "code-analysis": [ - "@code-analysis/drupal-check" + "coding-standards-apply": [ + "@coding-standards-apply/phpcbf", + "@coding-standards-apply/twig-cs-fixer" ], - "coding-standards-check/phpcs": [ - "phpcs --standard=phpcs.xml.dist" + "coding-standards-apply/twig-cs-fixer": [ + "twig-cs-fixer --fix" ], - "coding-standards-check/twigcs": [ - "twigcs templates" + "coding-standards-apply/phpcbf": [ + "phpcbf --standard=phpcs.xml.dist" ], "coding-standards-check": [ "@coding-standards-check/phpcs", "@coding-standards-check/twigcs" ], - "coding-standards-apply/phpcbf": [ - "phpcbf --standard=phpcs.xml.dist" + "coding-standards-check/phpcs": [ + "phpcs --standard=phpcs.xml.dist" ], - "coding-standards-apply": [ - "@coding-standards-apply/phpcbf" + "coding-standards-check/twig-cs-fixer": [ + "twig-cs-fixer" ] - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true, - "zaporylie/composer-drupal-optimizations": true, - "cweagans/composer-patches": true, - "simplesamlphp/composer-module-installer": true, - "mglaman/composer-drupal-lenient": true - } } } diff --git a/os2forms_nemlogin_openid_connect.info.yml b/os2forms_nemlogin_openid_connect.info.yml index c90eae1..51db3c4 100644 --- a/os2forms_nemlogin_openid_connect.info.yml +++ b/os2forms_nemlogin_openid_connect.info.yml @@ -11,5 +11,6 @@ dependencies: - drupal:os2forms_forloeb - drupal:os2web_nemlogin - os2web:os2web_audit + - os2web_key:os2web_key configure: os2forms_nemlogin_openid_connect.admin.settings diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index c9974fa..17248f8 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -12,8 +12,11 @@ use Drupal\Core\Site\Settings; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; +use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_nemlogin_openid_connect\Exception\AuthenticationException; use Drupal\os2forms_nemlogin_openid_connect\Plugin\os2web\NemloginAuthProvider\OpenIDConnect; +use Drupal\os2web_key\KeyHelper; +use Drupal\os2web_key\Plugin\KeyType\OidcKeyType; use Drupal\os2web_nemlogin\Service\AuthProviderService; use ItkDev\OpenIdConnect\Security\OpenIdConfigurationProvider; use Psr\Cache\CacheItemPoolInterface; @@ -77,6 +80,9 @@ public function __construct( private readonly SessionInterface $session, private readonly CacheItemPoolInterface $cacheItemPool, private readonly LanguageManagerInterface $languageManager, + private readonly RendererInterface $renderer, + private readonly KeyRepositoryInterface $keyRepository, + private readonly KeyHelper $keyHelper, LoggerInterface $logger, private readonly RendererInterface $renderer, ) { @@ -93,8 +99,9 @@ public static function create(ContainerInterface $container): self { $container->get('session'), $container->get('drupal_psr6_cache.cache_item_pool'), $container->get('language_manager'), - $container->get('logger.channel.os2forms_nemlogin_openid_connect'), $container->get('renderer'), + $container->get('key.repository'), + $container->get('logger.channel.os2forms_nemlogin_openid_connect'), ); } @@ -140,12 +147,24 @@ public function main(string $id) { private function getOpenIdConfigurationProvider(): OpenIdConfigurationProvider { $pluginConfiguration = $this->plugin->getConfiguration(); + try { + $key = $this->keyRepository->getKey($pluginConfiguration[OpenIDConnect::KEY] ?? ''); + [ + OidcKeyType::DISCOVERY_URL => $discoveryUrl, + OidcKeyType::CLIENT_ID => $clientId, + OidcKeyType::CLIENT_SECRET => $clientSecret, + ] = $this->keyHelper->getOidcValues($key); + } + catch (\Exception $e) { + throw new AuthenticationException('Cannot get client id and secret', $e->getCode(), $e); + } + $providerOptions = [ 'redirectUri' => $this->getRedirectUri(), - 'openIDConnectMetadataUrl' => $pluginConfiguration['nemlogin_openid_connect_discovery_url'], + 'openIDConnectMetadataUrl' => $discoveryUrl, 'cacheItemPool' => $this->cacheItemPool, - 'clientId' => $pluginConfiguration['nemlogin_openid_connect_client_id'], - 'clientSecret' => $pluginConfiguration['nemlogin_openid_connect_client_secret'], + 'clientId' => $clientId, + 'clientSecret' => $clientSecret, 'localTestMode' => FALSE, 'allowHttp' => (bool) ($this->getSettings()['allow_http'] ?? FALSE), ]; @@ -273,7 +292,7 @@ public function endSession(string $id): Response { private function getPostLogoutRedirectUri(): string { try { $pluginConfiguration = $this->plugin->getConfiguration(); - $url = $pluginConfiguration['nemlogin_openid_connect_post_logout_redirect_uri'] ?? '/'; + $url = $pluginConfiguration[self::POST_LOGOUT_REDIRECT_URI] ?? '/'; $options = [ 'absolute' => TRUE, 'path_processing' => FALSE, diff --git a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php index 5c9845a..e874cf7 100644 --- a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php +++ b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php @@ -265,6 +265,12 @@ public function fetchValue($key) { return $value; } + public const DISCOVERY_URL = 'nemlogin_openid_connect_discovery_url'; + public const KEY = 'nemlogin_openid_connect_key'; + public const FETCH_ONCE = 'nemlogin_openid_connect_fetch_once'; + public const POST_LOGOUT_REDIRECT_URI = 'nemlogin_openid_connect_post_logout_redirect_uri'; + public const USER_CLAIMS = 'nemlogin_openid_connect_user_claims'; + /** * {@inheritdoc} * @@ -275,12 +281,11 @@ public function fetchValue($key) { */ public function defaultConfiguration() { return parent::defaultConfiguration() + [ - 'nemlogin_openid_connect_discovery_url' => '', - 'nemlogin_openid_connect_client_id' => '', - 'nemlogin_openid_connect_client_secret' => '', - 'nemlogin_openid_connect_fetch_once' => '', - 'nemlogin_openid_connect_post_logout_redirect_uri' => '', - 'nemlogin_openid_connect_user_claims' => '', + self::DISCOVERY_URL => '', + self::KEY => '', + self::FETCH_ONCE => '', + self::POST_LOGOUT_REDIRECT_URI => '', + self::USER_CLAIMS => '', ]; } @@ -291,47 +296,44 @@ public function defaultConfiguration() { * @phpstan-return array */ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { - $form['nemlogin_openid_connect_discovery_url'] = [ + $form[self::DISCOVERY_URL] = [ '#type' => 'textfield', '#title' => $this->t('OpenID Connect Discovery url'), // Our urls are very long. '#maxlength' => 256, '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_discovery_url'] ?? NULL, + '#default_value' => $this->configuration[self::DISCOVERY_URL] ?? NULL, '#description' => $this->t('OpenID Connect Discovery url (cf. https://swagger.io/docs/specification/authentication/openid-connect-discovery/)'), ]; - $form['nemlogin_openid_connect_client_id'] = [ - '#type' => 'textfield', - '#title' => $this->t('Client id'), - '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_client_id'] ?? NULL, - ]; - $form['nemlogin_openid_connect_client_secret'] = [ - '#type' => 'textfield', - '#title' => $this->t('Client secret'), + $form[self::KEY] = [ + '#type' => 'key_select', + '#key_filters' => [ + 'type' => 'os2web_key_oidc', + ], + '#title' => $this->t('Key'), '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_client_secret'] ?? NULL, + '#default_value' => $this->configuration[self::KEY] ?? NULL, ]; - $form['nemlogin_openid_connect_fetch_once'] = [ + $form[self::FETCH_ONCE] = [ '#type' => 'checkbox', '#title' => $this->t('Use fetch only mode.'), - '#default_value' => $this->configuration['nemlogin_openid_connect_fetch_once'] ?? FALSE, + '#default_value' => $this->configuration[self::FETCH_ONCE] ?? FALSE, '#description' => $this->t('User will be logged out immediately after login. User data will be removed from session after first retrieving'), ]; - $form['nemlogin_openid_connect_post_logout_redirect_uri'] = [ + $form[self::POST_LOGOUT_REDIRECT_URI] = [ '#type' => 'textfield', '#title' => $this->t('Post logout redirect url'), '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_post_logout_redirect_uri'] ?? NULL, + '#default_value' => $this->configuration[self::POST_LOGOUT_REDIRECT_URI] ?? NULL, '#description' => $this->t('Url to redirect to after logout. Can be an internal path, e.g. /node/87, or an external url, e.g. https://aarhus.dk'), ]; - $form['nemlogin_openid_connect_user_claims'] = [ + $form[self::USER_CLAIMS] = [ '#type' => 'textarea', '#title' => $this->t('User claims'), '#description' => $this->t('Describe user claims for use when comparing user values.
Each line must be on the form «claim»: «display name», e.g.

cpr: CPR-nummer
email: E-mailadresse
'), - '#default_value' => $this->configuration['nemlogin_openid_connect_user_claims'] ?? NULL, + '#default_value' => $this->configuration[self::USER_CLAIMS] ?? NULL, ]; return $form; @@ -343,27 +345,27 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta * @phpstan-param array $form */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void { - $url = $form_state->getValue('nemlogin_openid_connect_discovery_url'); + $url = $form_state->getValue(self::DISCOVERY_URL); if (!UrlHelper::isValid($url, TRUE)) { - $form_state->setErrorByName('nemlogin_openid_connect_discovery_url', $this->t('Url is not valid')); + $form_state->setErrorByName(self::DISCOVERY_URL, $this->t('Url is not valid')); } - $url = $form_state->getValue('nemlogin_openid_connect_post_logout_redirect_uri'); + $url = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); try { UrlHelper::isExternal($url) ? Url::fromUri($url) : Url::fromUserInput($url); } catch (\Exception $exception) { - $form_state->setErrorByName('nemlogin_openid_connect_post_logout_redirect_uri', $this->t('Post logout redirect url is not valid (@message)', ['@message' => $exception->getMessage()])); + $form_state->setErrorByName(self::POST_LOGOUT_REDIRECT_URI, $this->t('Post logout redirect url is not valid (@message)', ['@message' => $exception->getMessage()])); } - $claims = $form_state->getValue('nemlogin_openid_connect_user_claims'); + $claims = $form_state->getValue(self::USER_CLAIMS); try { $values = Yaml::parse($claims); foreach ($values as $name => $value) { if (!is_string($name)) { $form_state->setErrorByName( - 'nemlogin_openid_connect_user_claims', + self::USER_CLAIMS, $this->t('Name (@name) must be a string; found @type.', [ '@name' => $name, '@type' => gettype($name), @@ -373,7 +375,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form } if (!is_string($value)) { $form_state->setErrorByName( - 'nemlogin_openid_connect_user_claims', + self::USER_CLAIMS, $this->t('Value for “@name” must be a string; found @type.', [ '@name' => $name, '@type' => gettype($value), @@ -384,7 +386,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form } } catch (ParseException $exception) { - $form_state->setErrorByName('nemlogin_openid_connect_user_claims', $this->t('Invalid claims (@message)', ['@message' => $exception->getMessage()])); + $form_state->setErrorByName(self::USER_CLAIMS, $this->t('Invalid claims (@message)', ['@message' => $exception->getMessage()])); } } @@ -396,12 +398,11 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { $configuration = $this->getConfiguration(); - $configuration['nemlogin_openid_connect_discovery_url'] = $form_state->getValue('nemlogin_openid_connect_discovery_url'); - $configuration['nemlogin_openid_connect_client_id'] = $form_state->getValue('nemlogin_openid_connect_client_id'); - $configuration['nemlogin_openid_connect_client_secret'] = $form_state->getValue('nemlogin_openid_connect_client_secret'); - $configuration['nemlogin_openid_connect_fetch_once'] = $form_state->getValue('nemlogin_openid_connect_fetch_once'); - $configuration['nemlogin_openid_connect_post_logout_redirect_uri'] = $form_state->getValue('nemlogin_openid_connect_post_logout_redirect_uri'); - $configuration['nemlogin_openid_connect_user_claims'] = $form_state->getValue('nemlogin_openid_connect_user_claims'); + $configuration[self::DISCOVERY_URL] = $form_state->getValue(self::DISCOVERY_URL); + $configuration[self::KEY] = $form_state->getValue(self::KEY); + $configuration[self::FETCH_ONCE] = $form_state->getValue(self::FETCH_ONCE); + $configuration[self::POST_LOGOUT_REDIRECT_URI] = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); + $configuration[self::USER_CLAIMS] = $form_state->getValue(self::USER_CLAIMS); $this->setConfiguration($configuration); } From 1e8d1e010daba9d82e0672b22619a4093cc948dd Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Mon, 13 May 2024 12:46:50 +0200 Subject: [PATCH 02/31] Fixed reference to constant --- src/Controller/OpenIDConnectController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index 17248f8..0db4237 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -292,7 +292,7 @@ public function endSession(string $id): Response { private function getPostLogoutRedirectUri(): string { try { $pluginConfiguration = $this->plugin->getConfiguration(); - $url = $pluginConfiguration[self::POST_LOGOUT_REDIRECT_URI] ?? '/'; + $url = $pluginConfiguration[OpenIDConnect::POST_LOGOUT_REDIRECT_URI] ?? '/'; $options = [ 'absolute' => TRUE, 'path_processing' => FALSE, From 790fd4cf23319748834e88115593c6158323b4dc Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 16 May 2024 15:00:10 +0200 Subject: [PATCH 03/31] Cleaned up --- src/Controller/OpenIDConnectController.php | 7 ++++++- .../NemloginAuthProvider/OpenIDConnect.php | 18 ------------------ 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index 0db4237..c5323de 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -101,6 +101,7 @@ public static function create(ContainerInterface $container): self { $container->get('language_manager'), $container->get('renderer'), $container->get('key.repository'), + $container->get(KeyHelper::class), $container->get('logger.channel.os2forms_nemlogin_openid_connect'), ); } @@ -148,7 +149,11 @@ private function getOpenIdConfigurationProvider(): OpenIdConfigurationProvider { $pluginConfiguration = $this->plugin->getConfiguration(); try { - $key = $this->keyRepository->getKey($pluginConfiguration[OpenIDConnect::KEY] ?? ''); + $keyId = $pluginConfiguration[OpenIDConnect::KEY] ?? ''; + $key = $this->keyRepository->getKey($keyId); + if (NULL === $key) { + throw new \RuntimeException(sprintf('Cannot get key %s', $keyId)); + } [ OidcKeyType::DISCOVERY_URL => $discoveryUrl, OidcKeyType::CLIENT_ID => $clientId, diff --git a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php index e874cf7..11eb130 100644 --- a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php +++ b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php @@ -265,7 +265,6 @@ public function fetchValue($key) { return $value; } - public const DISCOVERY_URL = 'nemlogin_openid_connect_discovery_url'; public const KEY = 'nemlogin_openid_connect_key'; public const FETCH_ONCE = 'nemlogin_openid_connect_fetch_once'; public const POST_LOGOUT_REDIRECT_URI = 'nemlogin_openid_connect_post_logout_redirect_uri'; @@ -281,7 +280,6 @@ public function fetchValue($key) { */ public function defaultConfiguration() { return parent::defaultConfiguration() + [ - self::DISCOVERY_URL => '', self::KEY => '', self::FETCH_ONCE => '', self::POST_LOGOUT_REDIRECT_URI => '', @@ -296,15 +294,6 @@ public function defaultConfiguration() { * @phpstan-return array */ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { - $form[self::DISCOVERY_URL] = [ - '#type' => 'textfield', - '#title' => $this->t('OpenID Connect Discovery url'), - // Our urls are very long. - '#maxlength' => 256, - '#required' => TRUE, - '#default_value' => $this->configuration[self::DISCOVERY_URL] ?? NULL, - '#description' => $this->t('OpenID Connect Discovery url (cf. https://swagger.io/docs/specification/authentication/openid-connect-discovery/)'), - ]; $form[self::KEY] = [ '#type' => 'key_select', '#key_filters' => [ @@ -345,12 +334,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta * @phpstan-param array $form */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void { - $url = $form_state->getValue(self::DISCOVERY_URL); - - if (!UrlHelper::isValid($url, TRUE)) { - $form_state->setErrorByName(self::DISCOVERY_URL, $this->t('Url is not valid')); - } - $url = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); try { UrlHelper::isExternal($url) ? Url::fromUri($url) : Url::fromUserInput($url); @@ -398,7 +381,6 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { $configuration = $this->getConfiguration(); - $configuration[self::DISCOVERY_URL] = $form_state->getValue(self::DISCOVERY_URL); $configuration[self::KEY] = $form_state->getValue(self::KEY); $configuration[self::FETCH_ONCE] = $form_state->getValue(self::FETCH_ONCE); $configuration[self::POST_LOGOUT_REDIRECT_URI] = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); From 4c59755042ba2cac428bd16f01e48f451ef83ddc Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 16 May 2024 16:24:50 +0200 Subject: [PATCH 04/31] Fixed name change in interface implementation --- src/Form/SettingsForm.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php index 0189fc4..6793142 100644 --- a/src/Form/SettingsForm.php +++ b/src/Form/SettingsForm.php @@ -81,9 +81,8 @@ public function buildForm(array $form, FormStateInterface $form_state): array { * * @phpstan-param array $form */ - public function validateForm(array &$form, FormStateInterface $formState): void { - - $providers = $formState->getValue(self::PROVIDERS); + public function validateForm(array &$form, FormStateInterface $form_state): void { + $providers = $form_state->getValue(self::PROVIDERS); try { $values = Yaml::parse($providers); @@ -92,7 +91,7 @@ public function validateForm(array &$form, FormStateInterface $formState): void } foreach ($values as $name => $value) { if (!is_string($name)) { - $formState->setErrorByName( + $form_state->setErrorByName( self::PROVIDERS, $this->t('Name (@name) must be a string; found @type.', [ '@name' => $name, @@ -102,7 +101,7 @@ public function validateForm(array &$form, FormStateInterface $formState): void break; } if (!is_string($value)) { - $formState->setErrorByName( + $form_state->setErrorByName( self::PROVIDERS, $this->t('Value for “@name” must be a string; found @type.', [ '@name' => $name, @@ -114,7 +113,7 @@ public function validateForm(array &$form, FormStateInterface $formState): void } } catch (ParseException $exception) { - $formState->setErrorByName(self::PROVIDERS, $this->t('Invalid providers (@message)', ['@message' => $exception->getMessage()])); + $form_state->setErrorByName(self::PROVIDERS, $this->t('Invalid providers (@message)', ['@message' => $exception->getMessage()])); } } @@ -123,10 +122,9 @@ public function validateForm(array &$form, FormStateInterface $formState): void * * @phpstan-param array $form */ - public function submitForm(array &$form, FormStateInterface $formState): void { - + public function submitForm(array &$form, FormStateInterface $form_state): void { try { - $settings[self::PROVIDERS] = $formState->getValue(self::PROVIDERS); + $settings[self::PROVIDERS] = $form_state->getValue(self::PROVIDERS); $this->settings->setSettings($settings); $this->messenger()->addStatus($this->t('Settings saved')); From fee6ccb0ef43aa4d5f27a1bd29cacc91255d8d35 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 16 May 2024 16:25:26 +0200 Subject: [PATCH 05/31] Added OIDC redirect URI display --- src/Form/SettingsForm.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php index 6793142..1ac0eb3 100644 --- a/src/Form/SettingsForm.php +++ b/src/Form/SettingsForm.php @@ -4,6 +4,7 @@ use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Link; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\os2forms_nemlogin_openid_connect\Helper\Settings; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -73,6 +74,41 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#value' => $this->t('Save settings'), ]; + try { + $providers = Yaml::parse($providers); + + $form['info'] = [ + '#type' => 'details', + '#open' => TRUE, + '#title' => $this->t('Provider details'), + '#weight' => 9999, + ]; + + $form['info']['table'] = [ + '#theme' => 'table', + '#header' => [ + ['data' => 'Id'], + ['data' => 'Label'], + ['data' => 'Redirect URI'], + ['data' => ''], + ], + '#rows' => array_map(fn ($id, $provider) => [ + 'data' => [ + ['data' => $id], + ['data' => $provider], + ['data' => Link::createFromRoute($provider, 'os2forms_nemlogin_openid_connect.openid_connect_authenticate', ['id' => $id])->toRenderable()], + ['data' => Link::createFromRoute($this->t('Edit'), 'os2web_nemlogin.auth_provider.' . $id)->toRenderable()], + ], + ], + array_keys($providers), + $providers + ), + ]; + } + catch (\Exception $e) { + // Ignore all exception. + } + return $form; } From afc6896cb5569c898acc062c3638e9e5e82c5901 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 17 May 2024 12:31:30 +0200 Subject: [PATCH 06/31] Update CHANGELOG.md Co-authored-by: Jeppe Kuhlmann Andersen <78410897+jekuaitk@users.noreply.github.com> --- CHANGELOG.md | 2 +- src/Controller/OpenIDConnectController.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9384ccc..abfe59c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -* [PR-19](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/19) +* [PR-20](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/20) Added support for Key ## [2.2.0] 2024-12-10 diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index c5323de..873fe4e 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -84,7 +84,6 @@ public function __construct( private readonly KeyRepositoryInterface $keyRepository, private readonly KeyHelper $keyHelper, LoggerInterface $logger, - private readonly RendererInterface $renderer, ) { $this->setLogger($logger); } From e7f81fa798bb936f8e5cf77299f81583e9100960 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 23 Jan 2025 19:33:43 +0100 Subject: [PATCH 07/31] Allowed both key and form configuration of providers --- src/Controller/OpenIDConnectController.php | 34 ++++-- .../NemloginAuthProvider/OpenIDConnect.php | 112 +++++++++++++++--- 2 files changed, 119 insertions(+), 27 deletions(-) diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index 873fe4e..78ad89d 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -147,22 +147,30 @@ public function main(string $id) { private function getOpenIdConfigurationProvider(): OpenIdConfigurationProvider { $pluginConfiguration = $this->plugin->getConfiguration(); - try { - $keyId = $pluginConfiguration[OpenIDConnect::KEY] ?? ''; - $key = $this->keyRepository->getKey($keyId); - if (NULL === $key) { - throw new \RuntimeException(sprintf('Cannot get key %s', $keyId)); - } - [ - OidcKeyType::DISCOVERY_URL => $discoveryUrl, - OidcKeyType::CLIENT_ID => $clientId, - OidcKeyType::CLIENT_SECRET => $clientSecret, - ] = $this->keyHelper->getOidcValues($key); + if (OpenIDConnect::PROVIDER_TYPE_KEY === $pluginConfiguration[OpenIDConnect::PROVIDER_TYPE_KEY]) { + $discoveryUrl = $pluginConfiguration[OpenIDConnect::DISCOVERY_URL]; + $clientId = $pluginConfiguration[OpenIDConnect::CLIENT_ID]; + $clientSecret = $pluginConfiguration[OpenIDConnect::CLIENT_SECRET]; } - catch (\Exception $e) { - throw new AuthenticationException('Cannot get client id and secret', $e->getCode(), $e); + else { + try { + $keyId = $pluginConfiguration[OpenIDConnect::KEY] ?? ''; + $key = $this->keyRepository->getKey($keyId); + if (NULL === $key) { + throw new \RuntimeException(sprintf('Cannot get key %s', $keyId)); + } + [ + OidcKeyType::DISCOVERY_URL => $discoveryUrl, + OidcKeyType::CLIENT_ID => $clientId, + OidcKeyType::CLIENT_SECRET => $clientSecret, + ] = $this->keyHelper->getOidcValues($key); + } + catch (\Exception $e) { + throw new AuthenticationException('Cannot get client id and secret', $e->getCode(), $e); + } } + $providerOptions = [ 'redirectUri' => $this->getRedirectUri(), 'openIDConnectMetadataUrl' => $discoveryUrl, diff --git a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php index 11eb130..07bbe51 100644 --- a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php +++ b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php @@ -32,10 +32,17 @@ class OpenIDConnect extends AuthProviderBase { use LoggerTrait; use LoggerAwareTrait; - /** - * Session name for storing OIDC user token. - */ - private const SESSION_TOKEN = 'os2forms_nemlogin_openid_connect.user_token'; + public const SESSION_TOKEN = 'os2forms_nemlogin_openid_connect.user_token'; + public const KEY = 'nemlogin_openid_connect_key'; + public const SECRET_PROVIDER = 'secret_provider'; + public const PROVIDER_TYPE_FORM = 'form'; + public const PROVIDER_TYPE_KEY = 'key'; + public const FETCH_ONCE = 'nemlogin_openid_connect_fetch_once'; + public const POST_LOGOUT_REDIRECT_URI = 'nemlogin_openid_connect_post_logout_redirect_uri'; + public const USER_CLAIMS = 'nemlogin_openid_connect_user_claims'; + public const DISCOVERY_URL = 'nemlogin_openid_connect_discovery_url'; + public const CLIENT_ID = 'nemlogin_openid_connect_client_id'; + public const CLIENT_SECRET = 'nemlogin_openid_connect_client_secret'; /** * Fetch only mode flag. @@ -115,8 +122,8 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public function isInitialized() { - $configuration = $configuration = $this->getConfiguration(); - if (!empty($configuration['nemlogin_openid_connect_discovery_url'])) { + $configuration = $this->getConfiguration(); + if (!empty($configuration[self::DISCOVERY_URL])) { return TRUE; } @@ -265,11 +272,6 @@ public function fetchValue($key) { return $value; } - public const KEY = 'nemlogin_openid_connect_key'; - public const FETCH_ONCE = 'nemlogin_openid_connect_fetch_once'; - public const POST_LOGOUT_REDIRECT_URI = 'nemlogin_openid_connect_post_logout_redirect_uri'; - public const USER_CLAIMS = 'nemlogin_openid_connect_user_claims'; - /** * {@inheritdoc} * @@ -280,6 +282,10 @@ public function fetchValue($key) { */ public function defaultConfiguration() { return parent::defaultConfiguration() + [ + self::SECRET_PROVIDER => self::PROVIDER_TYPE_FORM, + self::DISCOVERY_URL => '', + self::CLIENT_ID => '', + self::CLIENT_SECRET => '', self::KEY => '', self::FETCH_ONCE => '', self::POST_LOGOUT_REDIRECT_URI => '', @@ -294,15 +300,79 @@ public function defaultConfiguration() { * @phpstan-return array */ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { + + $form[self::SECRET_PROVIDER] = [ + '#type' => 'select', + '#title' => $this->t('Provider'), + '#options' => [ + self::PROVIDER_TYPE_FORM => $this->t('Form'), + self::PROVIDER_TYPE_KEY => $this->t('Key'), + ], + '#default_value' => $this->configuration[self::SECRET_PROVIDER] ?? self::PROVIDER_TYPE_FORM, + ]; + + $form[self::DISCOVERY_URL] = [ + '#type' => 'textfield', + '#title' => $this->t('OpenID Connect Discovery url'), + // Our urls are very long. + '#maxlength' => 256, + '#default_value' => $this->configuration[self::DISCOVERY_URL] ?? NULL, + '#description' => $this->t('OpenID Connect Discovery url (cf. https://swagger.io/docs/specification/authentication/openid-connect-discovery/)'), + '#states' => [ + 'visible' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]], + ], + 'required' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]], + ], + ], + ]; + + $form[self::CLIENT_ID] = [ + '#type' => 'textfield', + '#title' => $this->t('Client id'), + '#default_value' => $this->configuration[self::CLIENT_ID] ?? NULL, + '#states' => [ + 'visible' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]], + ], + 'required' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]], + ], + ], + ]; + + $form[self::CLIENT_SECRET] = [ + '#type' => 'textfield', + '#title' => $this->t('Client secret'), + '#default_value' => $this->configuration[self::CLIENT_SECRET] ?? NULL, + '#states' => [ + 'visible' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]], + ], + 'required' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]], + ], + ], + ]; + $form[self::KEY] = [ '#type' => 'key_select', '#key_filters' => [ 'type' => 'os2web_key_oidc', ], '#title' => $this->t('Key'), - '#required' => TRUE, '#default_value' => $this->configuration[self::KEY] ?? NULL, + '#states' => [ + 'visible' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_KEY]], + ], + 'required' => [ + [':input[name="secret_provider"]' => ['value' => self::PROVIDER_TYPE_KEY]], + ], + ], ]; + $form[self::FETCH_ONCE] = [ '#type' => 'checkbox', '#title' => $this->t('Use fetch only mode.'), @@ -334,9 +404,19 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta * @phpstan-param array $form */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void { - $url = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); + + if (self::PROVIDER_TYPE_FORM === $form_state->getValue(self::SECRET_PROVIDER)) { + + $discoveryUrl = $form_state->getValue(self::DISCOVERY_URL); + + if (!UrlHelper::isValid($discoveryUrl, TRUE)) { + $form_state->setErrorByName(self::DISCOVERY_URL, $this->t('Discovery url is not valid')); + } + } + + $redirectUrl = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); try { - UrlHelper::isExternal($url) ? Url::fromUri($url) : Url::fromUserInput($url); + UrlHelper::isExternal($redirectUrl) ? Url::fromUri($redirectUrl) : Url::fromUserInput($redirectUrl); } catch (\Exception $exception) { $form_state->setErrorByName(self::POST_LOGOUT_REDIRECT_URI, $this->t('Post logout redirect url is not valid (@message)', ['@message' => $exception->getMessage()])); @@ -381,6 +461,10 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { $configuration = $this->getConfiguration(); + $configuration[self::SECRET_PROVIDER] = $form_state->getValue(self::SECRET_PROVIDER); + $configuration[self::DISCOVERY_URL] = $form_state->getValue(self::DISCOVERY_URL); + $configuration[self::CLIENT_ID] = $form_state->getValue(self::CLIENT_ID); + $configuration[self::CLIENT_SECRET] = $form_state->getValue(self::CLIENT_SECRET); $configuration[self::KEY] = $form_state->getValue(self::KEY); $configuration[self::FETCH_ONCE] = $form_state->getValue(self::FETCH_ONCE); $configuration[self::POST_LOGOUT_REDIRECT_URI] = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); From c5ae31382c044b7dd29c73c3c86ad5418b5d755e Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 23 Jan 2025 19:42:28 +0100 Subject: [PATCH 08/31] Clean up --- README.md | 8 ++++---- composer.json | 21 +++------------------ src/Controller/OpenIDConnectController.php | 1 - 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 3cb862e..c0123eb 100644 --- a/README.md +++ b/README.md @@ -104,11 +104,11 @@ below to run the checks locally. ### PHP ```shell -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer install +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer install # Fix (some) coding standards issues -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-apply +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer coding-standards-apply # Check that code adheres to the coding standards -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer coding-standards-check ``` ### Markdown @@ -126,5 +126,5 @@ Running statis code analysis on a standalone Drupal module is a bit tricky, so w analysis: ```shell -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm ./scripts/code-analysis +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm ./scripts/code-analysis ``` diff --git a/composer.json b/composer.json index e23f697..54fedf7 100644 --- a/composer.json +++ b/composer.json @@ -26,21 +26,6 @@ "url": "https://packages.drupal.org/8" } ], - "require": { - "itk-dev/openid-connect": "^3.1", - "itk-dev/drupal_psr6_cache": "^1.0", - "os2forms/os2forms": "^3.17", - "os2web/os2web_nemlogin": "^1.2", - "drupal/webform": "^6.0", - "symfony/options-resolver": "^5.4 || ^6.0" - }, - "require-dev": { - "drupal/coder": "^8.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", - "mglaman/drupal-check": "^1.4", - "mglaman/phpstan-drupal": "~1.2.0", - "friendsoftwig/twigcs": "^6.0" - }, "minimum-stability": "dev", "prefer-stable": true, "config": { @@ -64,12 +49,12 @@ "@coding-standards-apply/phpcbf", "@coding-standards-apply/twig-cs-fixer" ], - "coding-standards-apply/twig-cs-fixer": [ - "twig-cs-fixer --fix" - ], "coding-standards-apply/phpcbf": [ "phpcbf --standard=phpcs.xml.dist" ], + "coding-standards-apply/twig-cs-fixer": [ + "twig-cs-fixer --fix" + ], "coding-standards-check": [ "@coding-standards-check/phpcs", "@coding-standards-check/twigcs" diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index 78ad89d..b77088b 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -170,7 +170,6 @@ private function getOpenIdConfigurationProvider(): OpenIdConfigurationProvider { } } - $providerOptions = [ 'redirectUri' => $this->getRedirectUri(), 'openIDConnectMetadataUrl' => $discoveryUrl, From a397b2c47b883f3a589ad18155cd526c4d34286d Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 23 Jan 2025 19:43:16 +0100 Subject: [PATCH 09/31] Updated CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abfe59c..ef1fd78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] * [PR-20](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/20) - Added support for Key + Added support for Key. ## [2.2.0] 2024-12-10 From e05d1dae5a138525882094aa7b09c29e5e23ca67 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 23 Jan 2025 19:45:30 +0100 Subject: [PATCH 10/31] Downgraded phpstan drupal --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 54fedf7..1fb643f 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "drupal/coder": "^8.3", "ergebnis/composer-normalize": "^2.42", "mglaman/drupal-check": "^1.4", + "mglaman/phpstan-drupal": "~1.2.0", "vincentlanglet/twig-cs-fixer": "^2.8" }, "repositories": [ From 08d206be788eee9c720d411cb7db7db7d2899ab5 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 23 Jan 2025 19:59:24 +0100 Subject: [PATCH 11/31] Added missing requirement --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 1fb643f..73db39d 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "drupal/webform": "^6.0", "itk-dev/drupal_psr6_cache": "^1.0", "itk-dev/openid-connect": "^3.1", + "os2web/os2web_audit": "^0.1", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.2", "symfony/options-resolver": "^5.4 || ^6.0" From 7d3bcc80a71d4171b351fe2e4cbb4ec720410f81 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 24 Jan 2025 14:45:50 +0100 Subject: [PATCH 12/31] Reverted change in package requirements --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 73db39d..5b7b2d3 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "drupal/webform": "^6.0", "itk-dev/drupal_psr6_cache": "^1.0", "itk-dev/openid-connect": "^3.1", - "os2web/os2web_audit": "^0.1", + "os2forms/os2forms": "^3.17", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.2", "symfony/options-resolver": "^5.4 || ^6.0" From c4c3f14519b7fda03449644ef9f8b3cdfb674c36 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 3 May 2024 14:54:19 +0200 Subject: [PATCH 13/31] Added support for Key # Conflicts: # CHANGELOG.md # composer.json # os2forms_nemlogin_openid_connect.info.yml # src/Controller/OpenIDConnectController.php # Conflicts: # CHANGELOG.md --- .github/workflows/pr.yaml | 4 +- .gitignore | 1 + .markdownlint.jsonc | 13 ++++ CHANGELOG.md | 3 + README.md | 32 ++++++++ composer.json | 65 ++++++++++------ os2forms_nemlogin_openid_connect.info.yml | 1 + src/Controller/OpenIDConnectController.php | 29 +++++-- .../NemloginAuthProvider/OpenIDConnect.php | 77 ++++++++++--------- 9 files changed, 158 insertions(+), 67 deletions(-) create mode 100644 .markdownlint.jsonc diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 8bdcc22..1c62631 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -112,9 +112,9 @@ jobs: - name: Install Dependencies run: | composer install --no-interaction --no-progress - - name: twigcs + - name: twig-cs-fixer run: | - composer coding-standards-check/twigcs + composer coding-standards-check/twig-cs-fixer php-code-analysis: name: PHP code analysis diff --git a/.gitignore b/.gitignore index f782610..52dd39d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ vendor composer.lock node_modules yarn.lock +*.cache diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 0000000..a28c580 --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,13 @@ +{ + "default": true, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md + "line-length": { + "line_length": 120, + "code_blocks": false, + "tables": false + }, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md + "no-duplicate-heading": { + "siblings_only": true + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md index fb4fbab..6fcd1b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +* [PR-19](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/19) + Added support for Key + ## [2.2.1] * Allowed `os2forms/os2forms` 4.0. diff --git a/README.md b/README.md index 87273af..3cb862e 100644 --- a/README.md +++ b/README.md @@ -94,5 +94,37 @@ $settings['os2forms_nemlogin_openid_connect']['another-plugin-id']['local_test_u 'name' => 'User 87', ], ]; +``` + +## Coding standards + +Our coding are checked by GitHub Actions (cf. [.github/workflows/pr.yml](.github/workflows/pr.yml)). Use the commands +below to run the checks locally. + +### PHP + +```shell +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer install +# Fix (some) coding standards issues +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-apply +# Check that code adheres to the coding standards +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check +``` + +### Markdown + +```shell +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' --fix +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' +``` + +## Code analysis + +We use [PHPStan](https://phpstan.org/) for static code analysis. + +Running statis code analysis on a standalone Drupal module is a bit tricky, so we use a helper script to run the +analysis: +```shell +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm ./scripts/code-analysis ``` diff --git a/composer.json b/composer.json index fd0cba9..703f96f 100644 --- a/composer.json +++ b/composer.json @@ -1,11 +1,25 @@ { "name": "itk-dev/os2forms_nemlogin_openid_connect", - "type": "drupal-module", - "license": "MIT", "description": "os2forms_nemlogin_openid_connect", + "license": "MIT", + "type": "drupal-module", "keywords": [], "homepage": "https://www.drupal.org/project/os2forms_nemlogin_openid_connect", - "minimum-stability": "dev", + "require": { + "drupal/webform": "^6.0", + "itk-dev/drupal_psr6_cache": "^1.0", + "itk-dev/openid-connect": "^3.1", + "os2web/os2web_key": "^1.0", + "os2web/os2web_nemlogin": "^1.2", + "symfony/options-resolver": "^5.4 || ^6.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "drupal/coder": "^8.3", + "ergebnis/composer-normalize": "^2.42", + "mglaman/drupal-check": "^1.4", + "vincentlanglet/twig-cs-fixer": "^2.8" + }, "repositories": [ { "type": "composer", @@ -27,37 +41,44 @@ "mglaman/phpstan-drupal": "~1.2.0", "friendsoftwig/twigcs": "^6.0" }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "allow-plugins": { + "cweagans/composer-patches": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "mglaman/composer-drupal-lenient": true, + "simplesamlphp/composer-module-installer": true, + "zaporylie/composer-drupal-optimizations": true + } + }, "scripts": { + "code-analysis": [ + "@code-analysis/drupal-check" + ], "code-analysis/drupal-check": [ "drupal-check --deprecations --analysis --exclude-dir=vendor *.* src" ], - "code-analysis": [ - "@code-analysis/drupal-check" + "coding-standards-apply": [ + "@coding-standards-apply/phpcbf", + "@coding-standards-apply/twig-cs-fixer" ], - "coding-standards-check/phpcs": [ - "phpcs --standard=phpcs.xml.dist" + "coding-standards-apply/twig-cs-fixer": [ + "twig-cs-fixer --fix" ], - "coding-standards-check/twigcs": [ - "twigcs templates" + "coding-standards-apply/phpcbf": [ + "phpcbf --standard=phpcs.xml.dist" ], "coding-standards-check": [ "@coding-standards-check/phpcs", "@coding-standards-check/twigcs" ], - "coding-standards-apply/phpcbf": [ - "phpcbf --standard=phpcs.xml.dist" + "coding-standards-check/phpcs": [ + "phpcs --standard=phpcs.xml.dist" ], - "coding-standards-apply": [ - "@coding-standards-apply/phpcbf" + "coding-standards-check/twig-cs-fixer": [ + "twig-cs-fixer" ] - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true, - "zaporylie/composer-drupal-optimizations": true, - "cweagans/composer-patches": true, - "simplesamlphp/composer-module-installer": true, - "mglaman/composer-drupal-lenient": true - } } } diff --git a/os2forms_nemlogin_openid_connect.info.yml b/os2forms_nemlogin_openid_connect.info.yml index c90eae1..51db3c4 100644 --- a/os2forms_nemlogin_openid_connect.info.yml +++ b/os2forms_nemlogin_openid_connect.info.yml @@ -11,5 +11,6 @@ dependencies: - drupal:os2forms_forloeb - drupal:os2web_nemlogin - os2web:os2web_audit + - os2web_key:os2web_key configure: os2forms_nemlogin_openid_connect.admin.settings diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index c9974fa..17248f8 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -12,8 +12,11 @@ use Drupal\Core\Site\Settings; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; +use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_nemlogin_openid_connect\Exception\AuthenticationException; use Drupal\os2forms_nemlogin_openid_connect\Plugin\os2web\NemloginAuthProvider\OpenIDConnect; +use Drupal\os2web_key\KeyHelper; +use Drupal\os2web_key\Plugin\KeyType\OidcKeyType; use Drupal\os2web_nemlogin\Service\AuthProviderService; use ItkDev\OpenIdConnect\Security\OpenIdConfigurationProvider; use Psr\Cache\CacheItemPoolInterface; @@ -77,6 +80,9 @@ public function __construct( private readonly SessionInterface $session, private readonly CacheItemPoolInterface $cacheItemPool, private readonly LanguageManagerInterface $languageManager, + private readonly RendererInterface $renderer, + private readonly KeyRepositoryInterface $keyRepository, + private readonly KeyHelper $keyHelper, LoggerInterface $logger, private readonly RendererInterface $renderer, ) { @@ -93,8 +99,9 @@ public static function create(ContainerInterface $container): self { $container->get('session'), $container->get('drupal_psr6_cache.cache_item_pool'), $container->get('language_manager'), - $container->get('logger.channel.os2forms_nemlogin_openid_connect'), $container->get('renderer'), + $container->get('key.repository'), + $container->get('logger.channel.os2forms_nemlogin_openid_connect'), ); } @@ -140,12 +147,24 @@ public function main(string $id) { private function getOpenIdConfigurationProvider(): OpenIdConfigurationProvider { $pluginConfiguration = $this->plugin->getConfiguration(); + try { + $key = $this->keyRepository->getKey($pluginConfiguration[OpenIDConnect::KEY] ?? ''); + [ + OidcKeyType::DISCOVERY_URL => $discoveryUrl, + OidcKeyType::CLIENT_ID => $clientId, + OidcKeyType::CLIENT_SECRET => $clientSecret, + ] = $this->keyHelper->getOidcValues($key); + } + catch (\Exception $e) { + throw new AuthenticationException('Cannot get client id and secret', $e->getCode(), $e); + } + $providerOptions = [ 'redirectUri' => $this->getRedirectUri(), - 'openIDConnectMetadataUrl' => $pluginConfiguration['nemlogin_openid_connect_discovery_url'], + 'openIDConnectMetadataUrl' => $discoveryUrl, 'cacheItemPool' => $this->cacheItemPool, - 'clientId' => $pluginConfiguration['nemlogin_openid_connect_client_id'], - 'clientSecret' => $pluginConfiguration['nemlogin_openid_connect_client_secret'], + 'clientId' => $clientId, + 'clientSecret' => $clientSecret, 'localTestMode' => FALSE, 'allowHttp' => (bool) ($this->getSettings()['allow_http'] ?? FALSE), ]; @@ -273,7 +292,7 @@ public function endSession(string $id): Response { private function getPostLogoutRedirectUri(): string { try { $pluginConfiguration = $this->plugin->getConfiguration(); - $url = $pluginConfiguration['nemlogin_openid_connect_post_logout_redirect_uri'] ?? '/'; + $url = $pluginConfiguration[self::POST_LOGOUT_REDIRECT_URI] ?? '/'; $options = [ 'absolute' => TRUE, 'path_processing' => FALSE, diff --git a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php index 5c9845a..e874cf7 100644 --- a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php +++ b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php @@ -265,6 +265,12 @@ public function fetchValue($key) { return $value; } + public const DISCOVERY_URL = 'nemlogin_openid_connect_discovery_url'; + public const KEY = 'nemlogin_openid_connect_key'; + public const FETCH_ONCE = 'nemlogin_openid_connect_fetch_once'; + public const POST_LOGOUT_REDIRECT_URI = 'nemlogin_openid_connect_post_logout_redirect_uri'; + public const USER_CLAIMS = 'nemlogin_openid_connect_user_claims'; + /** * {@inheritdoc} * @@ -275,12 +281,11 @@ public function fetchValue($key) { */ public function defaultConfiguration() { return parent::defaultConfiguration() + [ - 'nemlogin_openid_connect_discovery_url' => '', - 'nemlogin_openid_connect_client_id' => '', - 'nemlogin_openid_connect_client_secret' => '', - 'nemlogin_openid_connect_fetch_once' => '', - 'nemlogin_openid_connect_post_logout_redirect_uri' => '', - 'nemlogin_openid_connect_user_claims' => '', + self::DISCOVERY_URL => '', + self::KEY => '', + self::FETCH_ONCE => '', + self::POST_LOGOUT_REDIRECT_URI => '', + self::USER_CLAIMS => '', ]; } @@ -291,47 +296,44 @@ public function defaultConfiguration() { * @phpstan-return array */ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { - $form['nemlogin_openid_connect_discovery_url'] = [ + $form[self::DISCOVERY_URL] = [ '#type' => 'textfield', '#title' => $this->t('OpenID Connect Discovery url'), // Our urls are very long. '#maxlength' => 256, '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_discovery_url'] ?? NULL, + '#default_value' => $this->configuration[self::DISCOVERY_URL] ?? NULL, '#description' => $this->t('OpenID Connect Discovery url (cf. https://swagger.io/docs/specification/authentication/openid-connect-discovery/)'), ]; - $form['nemlogin_openid_connect_client_id'] = [ - '#type' => 'textfield', - '#title' => $this->t('Client id'), - '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_client_id'] ?? NULL, - ]; - $form['nemlogin_openid_connect_client_secret'] = [ - '#type' => 'textfield', - '#title' => $this->t('Client secret'), + $form[self::KEY] = [ + '#type' => 'key_select', + '#key_filters' => [ + 'type' => 'os2web_key_oidc', + ], + '#title' => $this->t('Key'), '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_client_secret'] ?? NULL, + '#default_value' => $this->configuration[self::KEY] ?? NULL, ]; - $form['nemlogin_openid_connect_fetch_once'] = [ + $form[self::FETCH_ONCE] = [ '#type' => 'checkbox', '#title' => $this->t('Use fetch only mode.'), - '#default_value' => $this->configuration['nemlogin_openid_connect_fetch_once'] ?? FALSE, + '#default_value' => $this->configuration[self::FETCH_ONCE] ?? FALSE, '#description' => $this->t('User will be logged out immediately after login. User data will be removed from session after first retrieving'), ]; - $form['nemlogin_openid_connect_post_logout_redirect_uri'] = [ + $form[self::POST_LOGOUT_REDIRECT_URI] = [ '#type' => 'textfield', '#title' => $this->t('Post logout redirect url'), '#required' => TRUE, - '#default_value' => $this->configuration['nemlogin_openid_connect_post_logout_redirect_uri'] ?? NULL, + '#default_value' => $this->configuration[self::POST_LOGOUT_REDIRECT_URI] ?? NULL, '#description' => $this->t('Url to redirect to after logout. Can be an internal path, e.g. /node/87, or an external url, e.g. https://aarhus.dk'), ]; - $form['nemlogin_openid_connect_user_claims'] = [ + $form[self::USER_CLAIMS] = [ '#type' => 'textarea', '#title' => $this->t('User claims'), '#description' => $this->t('Describe user claims for use when comparing user values.
Each line must be on the form «claim»: «display name», e.g.

cpr: CPR-nummer
email: E-mailadresse
'), - '#default_value' => $this->configuration['nemlogin_openid_connect_user_claims'] ?? NULL, + '#default_value' => $this->configuration[self::USER_CLAIMS] ?? NULL, ]; return $form; @@ -343,27 +345,27 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta * @phpstan-param array $form */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void { - $url = $form_state->getValue('nemlogin_openid_connect_discovery_url'); + $url = $form_state->getValue(self::DISCOVERY_URL); if (!UrlHelper::isValid($url, TRUE)) { - $form_state->setErrorByName('nemlogin_openid_connect_discovery_url', $this->t('Url is not valid')); + $form_state->setErrorByName(self::DISCOVERY_URL, $this->t('Url is not valid')); } - $url = $form_state->getValue('nemlogin_openid_connect_post_logout_redirect_uri'); + $url = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); try { UrlHelper::isExternal($url) ? Url::fromUri($url) : Url::fromUserInput($url); } catch (\Exception $exception) { - $form_state->setErrorByName('nemlogin_openid_connect_post_logout_redirect_uri', $this->t('Post logout redirect url is not valid (@message)', ['@message' => $exception->getMessage()])); + $form_state->setErrorByName(self::POST_LOGOUT_REDIRECT_URI, $this->t('Post logout redirect url is not valid (@message)', ['@message' => $exception->getMessage()])); } - $claims = $form_state->getValue('nemlogin_openid_connect_user_claims'); + $claims = $form_state->getValue(self::USER_CLAIMS); try { $values = Yaml::parse($claims); foreach ($values as $name => $value) { if (!is_string($name)) { $form_state->setErrorByName( - 'nemlogin_openid_connect_user_claims', + self::USER_CLAIMS, $this->t('Name (@name) must be a string; found @type.', [ '@name' => $name, '@type' => gettype($name), @@ -373,7 +375,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form } if (!is_string($value)) { $form_state->setErrorByName( - 'nemlogin_openid_connect_user_claims', + self::USER_CLAIMS, $this->t('Value for “@name” must be a string; found @type.', [ '@name' => $name, '@type' => gettype($value), @@ -384,7 +386,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form } } catch (ParseException $exception) { - $form_state->setErrorByName('nemlogin_openid_connect_user_claims', $this->t('Invalid claims (@message)', ['@message' => $exception->getMessage()])); + $form_state->setErrorByName(self::USER_CLAIMS, $this->t('Invalid claims (@message)', ['@message' => $exception->getMessage()])); } } @@ -396,12 +398,11 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { $configuration = $this->getConfiguration(); - $configuration['nemlogin_openid_connect_discovery_url'] = $form_state->getValue('nemlogin_openid_connect_discovery_url'); - $configuration['nemlogin_openid_connect_client_id'] = $form_state->getValue('nemlogin_openid_connect_client_id'); - $configuration['nemlogin_openid_connect_client_secret'] = $form_state->getValue('nemlogin_openid_connect_client_secret'); - $configuration['nemlogin_openid_connect_fetch_once'] = $form_state->getValue('nemlogin_openid_connect_fetch_once'); - $configuration['nemlogin_openid_connect_post_logout_redirect_uri'] = $form_state->getValue('nemlogin_openid_connect_post_logout_redirect_uri'); - $configuration['nemlogin_openid_connect_user_claims'] = $form_state->getValue('nemlogin_openid_connect_user_claims'); + $configuration[self::DISCOVERY_URL] = $form_state->getValue(self::DISCOVERY_URL); + $configuration[self::KEY] = $form_state->getValue(self::KEY); + $configuration[self::FETCH_ONCE] = $form_state->getValue(self::FETCH_ONCE); + $configuration[self::POST_LOGOUT_REDIRECT_URI] = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); + $configuration[self::USER_CLAIMS] = $form_state->getValue(self::USER_CLAIMS); $this->setConfiguration($configuration); } From b86718bbbf0f79b829cb8843762e96fdbc5559d8 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Mon, 13 May 2024 12:46:50 +0200 Subject: [PATCH 14/31] Fixed reference to constant --- src/Controller/OpenIDConnectController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index 17248f8..0db4237 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -292,7 +292,7 @@ public function endSession(string $id): Response { private function getPostLogoutRedirectUri(): string { try { $pluginConfiguration = $this->plugin->getConfiguration(); - $url = $pluginConfiguration[self::POST_LOGOUT_REDIRECT_URI] ?? '/'; + $url = $pluginConfiguration[OpenIDConnect::POST_LOGOUT_REDIRECT_URI] ?? '/'; $options = [ 'absolute' => TRUE, 'path_processing' => FALSE, From 47425a9055436c2419c10e18b56f6eec4cd47c66 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 16 May 2024 15:00:10 +0200 Subject: [PATCH 15/31] Cleaned up --- src/Controller/OpenIDConnectController.php | 7 ++++++- .../NemloginAuthProvider/OpenIDConnect.php | 18 ------------------ 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index 0db4237..c5323de 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -101,6 +101,7 @@ public static function create(ContainerInterface $container): self { $container->get('language_manager'), $container->get('renderer'), $container->get('key.repository'), + $container->get(KeyHelper::class), $container->get('logger.channel.os2forms_nemlogin_openid_connect'), ); } @@ -148,7 +149,11 @@ private function getOpenIdConfigurationProvider(): OpenIdConfigurationProvider { $pluginConfiguration = $this->plugin->getConfiguration(); try { - $key = $this->keyRepository->getKey($pluginConfiguration[OpenIDConnect::KEY] ?? ''); + $keyId = $pluginConfiguration[OpenIDConnect::KEY] ?? ''; + $key = $this->keyRepository->getKey($keyId); + if (NULL === $key) { + throw new \RuntimeException(sprintf('Cannot get key %s', $keyId)); + } [ OidcKeyType::DISCOVERY_URL => $discoveryUrl, OidcKeyType::CLIENT_ID => $clientId, diff --git a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php index e874cf7..11eb130 100644 --- a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php +++ b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php @@ -265,7 +265,6 @@ public function fetchValue($key) { return $value; } - public const DISCOVERY_URL = 'nemlogin_openid_connect_discovery_url'; public const KEY = 'nemlogin_openid_connect_key'; public const FETCH_ONCE = 'nemlogin_openid_connect_fetch_once'; public const POST_LOGOUT_REDIRECT_URI = 'nemlogin_openid_connect_post_logout_redirect_uri'; @@ -281,7 +280,6 @@ public function fetchValue($key) { */ public function defaultConfiguration() { return parent::defaultConfiguration() + [ - self::DISCOVERY_URL => '', self::KEY => '', self::FETCH_ONCE => '', self::POST_LOGOUT_REDIRECT_URI => '', @@ -296,15 +294,6 @@ public function defaultConfiguration() { * @phpstan-return array */ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { - $form[self::DISCOVERY_URL] = [ - '#type' => 'textfield', - '#title' => $this->t('OpenID Connect Discovery url'), - // Our urls are very long. - '#maxlength' => 256, - '#required' => TRUE, - '#default_value' => $this->configuration[self::DISCOVERY_URL] ?? NULL, - '#description' => $this->t('OpenID Connect Discovery url (cf. https://swagger.io/docs/specification/authentication/openid-connect-discovery/)'), - ]; $form[self::KEY] = [ '#type' => 'key_select', '#key_filters' => [ @@ -345,12 +334,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta * @phpstan-param array $form */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void { - $url = $form_state->getValue(self::DISCOVERY_URL); - - if (!UrlHelper::isValid($url, TRUE)) { - $form_state->setErrorByName(self::DISCOVERY_URL, $this->t('Url is not valid')); - } - $url = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); try { UrlHelper::isExternal($url) ? Url::fromUri($url) : Url::fromUserInput($url); @@ -398,7 +381,6 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { $configuration = $this->getConfiguration(); - $configuration[self::DISCOVERY_URL] = $form_state->getValue(self::DISCOVERY_URL); $configuration[self::KEY] = $form_state->getValue(self::KEY); $configuration[self::FETCH_ONCE] = $form_state->getValue(self::FETCH_ONCE); $configuration[self::POST_LOGOUT_REDIRECT_URI] = $form_state->getValue(self::POST_LOGOUT_REDIRECT_URI); From 2f49b452353c951290d689b96640045ac13c578c Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 16 May 2024 16:24:50 +0200 Subject: [PATCH 16/31] Fixed name change in interface implementation --- src/Form/SettingsForm.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php index 0189fc4..6793142 100644 --- a/src/Form/SettingsForm.php +++ b/src/Form/SettingsForm.php @@ -81,9 +81,8 @@ public function buildForm(array $form, FormStateInterface $form_state): array { * * @phpstan-param array $form */ - public function validateForm(array &$form, FormStateInterface $formState): void { - - $providers = $formState->getValue(self::PROVIDERS); + public function validateForm(array &$form, FormStateInterface $form_state): void { + $providers = $form_state->getValue(self::PROVIDERS); try { $values = Yaml::parse($providers); @@ -92,7 +91,7 @@ public function validateForm(array &$form, FormStateInterface $formState): void } foreach ($values as $name => $value) { if (!is_string($name)) { - $formState->setErrorByName( + $form_state->setErrorByName( self::PROVIDERS, $this->t('Name (@name) must be a string; found @type.', [ '@name' => $name, @@ -102,7 +101,7 @@ public function validateForm(array &$form, FormStateInterface $formState): void break; } if (!is_string($value)) { - $formState->setErrorByName( + $form_state->setErrorByName( self::PROVIDERS, $this->t('Value for “@name” must be a string; found @type.', [ '@name' => $name, @@ -114,7 +113,7 @@ public function validateForm(array &$form, FormStateInterface $formState): void } } catch (ParseException $exception) { - $formState->setErrorByName(self::PROVIDERS, $this->t('Invalid providers (@message)', ['@message' => $exception->getMessage()])); + $form_state->setErrorByName(self::PROVIDERS, $this->t('Invalid providers (@message)', ['@message' => $exception->getMessage()])); } } @@ -123,10 +122,9 @@ public function validateForm(array &$form, FormStateInterface $formState): void * * @phpstan-param array $form */ - public function submitForm(array &$form, FormStateInterface $formState): void { - + public function submitForm(array &$form, FormStateInterface $form_state): void { try { - $settings[self::PROVIDERS] = $formState->getValue(self::PROVIDERS); + $settings[self::PROVIDERS] = $form_state->getValue(self::PROVIDERS); $this->settings->setSettings($settings); $this->messenger()->addStatus($this->t('Settings saved')); From 89af923ede7b712223a95ee5bf62b15b9e49d5f4 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 16 May 2024 16:25:26 +0200 Subject: [PATCH 17/31] Added OIDC redirect URI display --- src/Form/SettingsForm.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php index 6793142..1ac0eb3 100644 --- a/src/Form/SettingsForm.php +++ b/src/Form/SettingsForm.php @@ -4,6 +4,7 @@ use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Link; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\os2forms_nemlogin_openid_connect\Helper\Settings; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -73,6 +74,41 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#value' => $this->t('Save settings'), ]; + try { + $providers = Yaml::parse($providers); + + $form['info'] = [ + '#type' => 'details', + '#open' => TRUE, + '#title' => $this->t('Provider details'), + '#weight' => 9999, + ]; + + $form['info']['table'] = [ + '#theme' => 'table', + '#header' => [ + ['data' => 'Id'], + ['data' => 'Label'], + ['data' => 'Redirect URI'], + ['data' => ''], + ], + '#rows' => array_map(fn ($id, $provider) => [ + 'data' => [ + ['data' => $id], + ['data' => $provider], + ['data' => Link::createFromRoute($provider, 'os2forms_nemlogin_openid_connect.openid_connect_authenticate', ['id' => $id])->toRenderable()], + ['data' => Link::createFromRoute($this->t('Edit'), 'os2web_nemlogin.auth_provider.' . $id)->toRenderable()], + ], + ], + array_keys($providers), + $providers + ), + ]; + } + catch (\Exception $e) { + // Ignore all exception. + } + return $form; } From 0332522da9d0d37d8d769a0968c8fca488386043 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 17 May 2024 12:31:30 +0200 Subject: [PATCH 18/31] Update CHANGELOG.md Co-authored-by: Jeppe Kuhlmann Andersen <78410897+jekuaitk@users.noreply.github.com> --- CHANGELOG.md | 2 +- src/Controller/OpenIDConnectController.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fcd1b5..dc8a0fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -* [PR-19](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/19) +* [PR-20](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/20) Added support for Key ## [2.2.1] diff --git a/src/Controller/OpenIDConnectController.php b/src/Controller/OpenIDConnectController.php index c5323de..873fe4e 100644 --- a/src/Controller/OpenIDConnectController.php +++ b/src/Controller/OpenIDConnectController.php @@ -84,7 +84,6 @@ public function __construct( private readonly KeyRepositoryInterface $keyRepository, private readonly KeyHelper $keyHelper, LoggerInterface $logger, - private readonly RendererInterface $renderer, ) { $this->setLogger($logger); } From 80770d52d3f253923412c344a4ae86ef7bb0ddf4 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 2 May 2025 15:34:54 +0200 Subject: [PATCH 19/31] Added os2forms/os2forms --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 703f96f..388fa88 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "drupal/webform": "^6.0", "itk-dev/drupal_psr6_cache": "^1.0", "itk-dev/openid-connect": "^3.1", + "os2forms/os2forms": "^4.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.2", "symfony/options-resolver": "^5.4 || ^6.0" From b05c7cc65bf7af34bb63ace21f9d18253f6d7325 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 2 May 2025 15:49:47 +0200 Subject: [PATCH 20/31] Cleaned up --- README.md | 8 ++++---- composer.json | 28 ++++++---------------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 3cb862e..c0123eb 100644 --- a/README.md +++ b/README.md @@ -104,11 +104,11 @@ below to run the checks locally. ### PHP ```shell -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer install +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer install # Fix (some) coding standards issues -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-apply +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer coding-standards-apply # Check that code adheres to the coding standards -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer coding-standards-check ``` ### Markdown @@ -126,5 +126,5 @@ Running statis code analysis on a standalone Drupal module is a bit tricky, so w analysis: ```shell -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm ./scripts/code-analysis +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm ./scripts/code-analysis ``` diff --git a/composer.json b/composer.json index 388fa88..9525b2d 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,6 @@ "description": "os2forms_nemlogin_openid_connect", "license": "MIT", "type": "drupal-module", - "keywords": [], "homepage": "https://www.drupal.org/project/os2forms_nemlogin_openid_connect", "require": { "drupal/webform": "^6.0", @@ -17,9 +16,9 @@ "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "drupal/coder": "^8.3", - "ergebnis/composer-normalize": "^2.42", - "mglaman/drupal-check": "^1.4", - "vincentlanglet/twig-cs-fixer": "^2.8" + "ergebnis/composer-normalize": "^2.47", + "friendsoftwig/twigcs": "^6.5", + "mglaman/drupal-check": "^1.5" }, "repositories": [ { @@ -27,21 +26,6 @@ "url": "https://packages.drupal.org/8" } ], - "require": { - "itk-dev/openid-connect": "^3.1", - "itk-dev/drupal_psr6_cache": "^1.0", - "os2forms/os2forms": "^3.17 || ^4.0", - "os2web/os2web_nemlogin": "^1.2", - "drupal/webform": "^6.0", - "symfony/options-resolver": "^5.4 || ^6.0" - }, - "require-dev": { - "drupal/coder": "^8.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", - "mglaman/drupal-check": "^1.4", - "mglaman/phpstan-drupal": "~1.2.0", - "friendsoftwig/twigcs": "^6.0" - }, "minimum-stability": "dev", "prefer-stable": true, "config": { @@ -65,12 +49,12 @@ "@coding-standards-apply/phpcbf", "@coding-standards-apply/twig-cs-fixer" ], - "coding-standards-apply/twig-cs-fixer": [ - "twig-cs-fixer --fix" - ], "coding-standards-apply/phpcbf": [ "phpcbf --standard=phpcs.xml.dist" ], + "coding-standards-apply/twig-cs-fixer": [ + "twig-cs-fixer --fix" + ], "coding-standards-check": [ "@coding-standards-check/phpcs", "@coding-standards-check/twigcs" From aade3242fa857a881fbf5d8d002e2ee2bee774a9 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 2 May 2025 16:10:59 +0200 Subject: [PATCH 21/31] Drupal lenient --- composer.json | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 9525b2d..ced818e 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "homepage": "https://www.drupal.org/project/os2forms_nemlogin_openid_connect", "require": { "drupal/webform": "^6.0", - "itk-dev/drupal_psr6_cache": "^1.0", + "itk-dev/drupal_psr6_cache": "^1.1", "itk-dev/openid-connect": "^3.1", "os2forms/os2forms": "^4.0", "os2web/os2web_key": "^1.0", @@ -17,8 +17,9 @@ "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "drupal/coder": "^8.3", "ergebnis/composer-normalize": "^2.47", - "friendsoftwig/twigcs": "^6.5", - "mglaman/drupal-check": "^1.5" + "mglaman/drupal-check": "^1.5", + "mglaman/phpstan-drupal": "~1.2.0", + "vincentlanglet/twig-cs-fixer": "^3.5" }, "repositories": [ { @@ -35,9 +36,18 @@ "ergebnis/composer-normalize": true, "mglaman/composer-drupal-lenient": true, "simplesamlphp/composer-module-installer": true, + "simplesamlphp/composer-xmlprovider-installer": true, "zaporylie/composer-drupal-optimizations": true } }, + "extra": { + "drupal-lenient": { + "allowed-list": [ + "drupal/coc_forms_auto_export", + "drupal/webform_node_element" + ] + } + }, "scripts": { "code-analysis": [ "@code-analysis/drupal-check" From 5bf226c07e0ab124f2b39ac42f508f25cab95ab3 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 2 May 2025 16:26:55 +0200 Subject: [PATCH 22/31] Added debug stuff --- .github/workflows/pr.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 1c62631..cfc8c50 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -76,6 +76,14 @@ jobs: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- + + # https://github.com/mxschmitt/action-tmate?tab=readme-ov-file#manually-triggered-debug + # Enable tmate debugging if debug logging is enabled (cf. + # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#runner-context) + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: 1 == runner.debug + - name: Install Dependencies run: | composer install --no-interaction --no-progress From 89ce83c59e88ae6723ca8ac3468e7d0e4ff0eddc Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 2 May 2025 16:32:57 +0200 Subject: [PATCH 23/31] Cleaned up workflow steps --- .github/workflows/pr.yaml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index cfc8c50..0657dbd 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -8,7 +8,7 @@ jobs: fail-fast: false steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 2 @@ -26,7 +26,7 @@ jobs: php-versions: [ '8.3' ] dependency-version: [ prefer-lowest, prefer-stable ] steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: @@ -56,9 +56,8 @@ jobs: strategy: matrix: php-versions: [ '8.3' ] - dependency-version: [ prefer-lowest, prefer-stable ] steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: @@ -97,9 +96,8 @@ jobs: strategy: matrix: php-versions: [ '8.3' ] - dependency-version: [ prefer-lowest, prefer-stable ] steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: @@ -130,9 +128,8 @@ jobs: strategy: matrix: php-versions: [ '8.3' ] - dependency-version: [ prefer-lowest, prefer-stable ] steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: @@ -191,7 +188,7 @@ jobs: name: Markdown coding standards steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn cache dir)" From 39d42e74a547c6612fe667f16b74ebc87627979a Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 2 May 2025 16:35:59 +0200 Subject: [PATCH 24/31] Moved debug stuff --- .github/workflows/pr.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 0657dbd..dead165 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -58,6 +58,14 @@ jobs: php-versions: [ '8.3' ] steps: - uses: actions/checkout@v4 + + # https://github.com/mxschmitt/action-tmate?tab=readme-ov-file#manually-triggered-debug + # Enable tmate debugging if debug logging is enabled (cf. + # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#runner-context) + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: 1 == runner.debug + - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: @@ -76,13 +84,6 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - # https://github.com/mxschmitt/action-tmate?tab=readme-ov-file#manually-triggered-debug - # Enable tmate debugging if debug logging is enabled (cf. - # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#runner-context) - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - if: 1 == runner.debug - - name: Install Dependencies run: | composer install --no-interaction --no-progress From 8660ba7bcefb1cff236d8900be06c6154656f66c Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 2 May 2025 16:57:09 +0200 Subject: [PATCH 25/31] Removed os2forms/os2forms --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index ced818e..06a475d 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,6 @@ "drupal/webform": "^6.0", "itk-dev/drupal_psr6_cache": "^1.1", "itk-dev/openid-connect": "^3.1", - "os2forms/os2forms": "^4.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.2", "symfony/options-resolver": "^5.4 || ^6.0" From cfe950002b16bc761f1105f0e469215b000abbed Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 5 May 2025 15:10:01 +0200 Subject: [PATCH 26/31] Added os2web_audit --- .github/workflows/pr.yaml | 8 -------- composer.json | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index dead165..7fb5f8a 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -58,14 +58,6 @@ jobs: php-versions: [ '8.3' ] steps: - uses: actions/checkout@v4 - - # https://github.com/mxschmitt/action-tmate?tab=readme-ov-file#manually-triggered-debug - # Enable tmate debugging if debug logging is enabled (cf. - # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#runner-context) - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - if: 1 == runner.debug - - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: diff --git a/composer.json b/composer.json index 06a475d..f4bb594 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,7 @@ "drupal/webform": "^6.0", "itk-dev/drupal_psr6_cache": "^1.1", "itk-dev/openid-connect": "^3.1", + "os2web/os2web_audit": "^1.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.2", "symfony/options-resolver": "^5.4 || ^6.0" From 594501d673b6f936a2a5386f8808e5b4513f322d Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 15 May 2025 15:00:51 +0200 Subject: [PATCH 27/31] Removed diff file --- _misc_diff.txt | 64 -------------------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 _misc_diff.txt diff --git a/_misc_diff.txt b/_misc_diff.txt deleted file mode 100644 index a9b83db..0000000 --- a/_misc_diff.txt +++ /dev/null @@ -1,64 +0,0 @@ -diff --git a/composer.json b/composer.json -index 388fa88..f4b8d4c 100644 ---- a/composer.json -+++ b/composer.json -@@ -7,7 +7,7 @@ - "homepage": "https://www.drupal.org/project/os2forms_nemlogin_openid_connect", - "require": { - "drupal/webform": "^6.0", -- "itk-dev/drupal_psr6_cache": "^1.0", -+ "itk-dev/drupal_psr6_cache": "^1.1", - "itk-dev/openid-connect": "^3.1", - "os2forms/os2forms": "^4.0", - "os2web/os2web_key": "^1.0", -@@ -19,7 +19,8 @@ - "drupal/coder": "^8.3", - "ergebnis/composer-normalize": "^2.42", - "mglaman/drupal-check": "^1.4", -- "vincentlanglet/twig-cs-fixer": "^2.8" -+ "mglaman/phpstan-drupal": "~1.2.0", -+ "vincentlanglet/twig-cs-fixer": "^3.5" - }, - "repositories": [ - { -@@ -27,21 +28,6 @@ - "url": "https://packages.drupal.org/8" - } - ], -- "require": { -- "itk-dev/openid-connect": "^3.1", -- "itk-dev/drupal_psr6_cache": "^1.0", -- "os2forms/os2forms": "^3.17 || ^4.0", -- "os2web/os2web_nemlogin": "^1.2", -- "drupal/webform": "^6.0", -- "symfony/options-resolver": "^5.4 || ^6.0" -- }, -- "require-dev": { -- "drupal/coder": "^8.3", -- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", -- "mglaman/drupal-check": "^1.4", -- "mglaman/phpstan-drupal": "~1.2.0", -- "friendsoftwig/twigcs": "^6.0" -- }, - "minimum-stability": "dev", - "prefer-stable": true, - "config": { -@@ -51,9 +37,18 @@ - "ergebnis/composer-normalize": true, - "mglaman/composer-drupal-lenient": true, - "simplesamlphp/composer-module-installer": true, -+ "simplesamlphp/composer-xmlprovider-installer": true, - "zaporylie/composer-drupal-optimizations": true - } - }, -+ "extra": { -+ "drupal-lenient": { -+ "allowed-list": [ -+ "drupal/coc_forms_auto_export", -+ "drupal/webform_node_element" -+ ] -+ } -+ }, - "scripts": { - "code-analysis": [ - "@code-analysis/drupal-check" From 9318ed3439f0e5c7bb3ed65932c2d558a62e4f89 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 15 May 2025 15:09:25 +0200 Subject: [PATCH 28/31] Applied coding standards --- src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php index f116167..6ecbaa7 100644 --- a/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php +++ b/src/Plugin/os2web/NemloginAuthProvider/OpenIDConnect.php @@ -45,7 +45,7 @@ class OpenIDConnect extends AuthProviderBase { public const CLIENT_SECRET = 'nemlogin_openid_connect_client_secret'; - /** + /** * Fetch only mode flag. * * @var bool From 831c25aa79f2f48d368134b14eb72720d66cad7c Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 8 Dec 2025 11:11:07 +0100 Subject: [PATCH 29/31] Prepared release --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14d3358..be89c72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [2.3.0] 2025-12-08 + * [PR-20](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/20) Added support for Key. -## [2.2.1] +## [2.2.1] 2025-03-13 * Allowed `os2forms/os2forms` 4.0. * Updated GitHub action dependencies. @@ -35,7 +37,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). * Allowed multiple providers. -[Unreleased]: https://github.com/itk-dev/os2forms_nemlogin_openid_connect/compare/2.2.1...HEAD +[Unreleased]: https://github.com/itk-dev/os2forms_nemlogin_openid_connect/compare/2.3.0...HEAD +[2.3.0]: https://github.com/itk-dev/os2forms_nemlogin_openid_connect/compare/2.2.1...2.3.0 [2.2.1]: https://github.com/itk-dev/os2forms_nemlogin_openid_connect/compare/2.2.0...2.2.1 [2.2.0]: https://github.com/itk-dev/os2forms_nemlogin_openid_connect/compare/2.1.0...2.2.0 [2.1.0]: https://github.com/itk-dev/os2forms_nemlogin_openid_connect/compare/2.0.1...2.1.0 From 5492d5f7f7224900342b09c0f6347be35d302fe9 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 8 Dec 2025 11:12:11 +0100 Subject: [PATCH 30/31] Applied coding standards --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be89c72..4db4519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [2.3.0] 2025-12-08 +## [2.3.0] 2025-12-08 * [PR-20](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/20) Added support for Key. From 40af15fb8d3ab42c6f3495fb84a5953ecd94ec4c Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 11 Dec 2025 15:24:17 +0100 Subject: [PATCH 31/31] Releae 2.3.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db4519..b5fc4b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [2.3.0] 2025-12-08 +## [2.3.0] 2025-12-11 * [PR-20](https://github.com/itk-dev/os2forms_nemlogin_openid_connect/pull/20) Added support for Key.