Skip to content
Snippets Groups Projects
Commit faf9e61c authored by Marko Ivancic's avatar Marko Ivancic
Browse files

Enable revoking OIDC tokens

parent 70141eda
No related branches found
No related tags found
1 merge request!5Enable revoking OIDC tokens
Showing
with 2891 additions and 517 deletions
...@@ -35,7 +35,7 @@ jobs: ...@@ -35,7 +35,7 @@ jobs:
test-latest: test-latest:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: cicnavi/dap:08 image: cicnavi/dap:81
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Validate composer.json and composer.lock - name: Validate composer.json and composer.lock
......
...@@ -20,10 +20,10 @@ test-74: ...@@ -20,10 +20,10 @@ test-74:
- composer install --prefer-dist --no-progress --no-suggest - composer install --prefer-dist --no-progress --no-suggest
- composer run-script pre-commit - composer run-script pre-commit
# PHP latest # PHP v8.1
test-08: test-81:
stage: test stage: test
image: cicnavi/dap:08 image: cicnavi/dap:81
script: script:
- composer install --prefer-dist --no-progress --no-suggest - composer install --prefer-dist --no-progress --no-suggest
- composer run-script pre-commit - composer run-script pre-commit
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
"php": "^7.4 || ^8.0", "php": "^7.4 || ^8.0",
"ext-pdo": "*", "ext-pdo": "*",
"ext-pdo_sqlite": "*", "ext-pdo_sqlite": "*",
"composer-runtime-api": "^2.0",
"doctrine/dbal": "^3", "doctrine/dbal": "^3",
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"simplesamlphp/composer-module-installer": "^1", "simplesamlphp/composer-module-installer": "^1",
...@@ -37,8 +38,9 @@ ...@@ -37,8 +38,9 @@
"vimeo/psalm": "^5", "vimeo/psalm": "^5",
"phpunit/phpunit": "^9", "phpunit/phpunit": "^9",
"squizlabs/php_codesniffer": "^3", "squizlabs/php_codesniffer": "^3",
"simplesamlphp/simplesamlphp": "^2@beta", "simplesamlphp/simplesamlphp": "^2",
"simplesamlphp/simplesamlphp-test-framework": "^1" "simplesamlphp/simplesamlphp-test-framework": "^1",
"simplesamlphp/simplesamlphp-module-oidc": "^3"
}, },
"suggest": { "suggest": {
"ext-pcntl": "Enables job runner to gracefully respond to SIGTERM signal.", "ext-pcntl": "Enables job runner to gracefully respond to SIGTERM signal.",
......
This diff is collapsed.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
use SimpleSAML\Locale\Translate; use SimpleSAML\Locale\Translate;
use SimpleSAML\Module\accounting\Helpers\ModuleRoutes; use SimpleSAML\Module\accounting\Helpers\Routes;
use SimpleSAML\Module\accounting\ModuleConfiguration; use SimpleSAML\Module\accounting\ModuleConfiguration;
use SimpleSAML\XHTML\Template; use SimpleSAML\XHTML\Template;
...@@ -12,11 +12,11 @@ function accounting_hook_adminmenu(Template &$template): void ...@@ -12,11 +12,11 @@ function accounting_hook_adminmenu(Template &$template): void
{ {
$menuKey = 'menu'; $menuKey = 'menu';
$moduleRoutesHelper = new ModuleRoutes(); $moduleRoutesHelper = new Routes();
$profilePageEntry = [ $profilePageEntry = [
ModuleConfiguration::MODULE_NAME => [ ModuleConfiguration::MODULE_NAME => [
'url' => $moduleRoutesHelper->getUrl(ModuleRoutes::PATH_USER_PERSONAL_DATA), 'url' => $moduleRoutesHelper->getUrl(Routes::PATH_USER_PERSONAL_DATA),
'name' => Translate::noop('Profile Page'), 'name' => Translate::noop('Profile Page'),
], ],
]; ];
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
declare(strict_types=1); declare(strict_types=1);
use SimpleSAML\Locale\Translate; use SimpleSAML\Locale\Translate;
use SimpleSAML\Module\accounting\Helpers\ModuleRoutes; use SimpleSAML\Module\accounting\Helpers\Routes;
use SimpleSAML\Module\accounting\ModuleConfiguration; use SimpleSAML\Module\accounting\ModuleConfiguration;
use SimpleSAML\XHTML\Template; use SimpleSAML\XHTML\Template;
/** @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection Reference is used by SimpleSAMLphp */ /** @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection Reference is used by SimpleSAMLphp */
function accounting_hook_configpage(Template &$template): void function accounting_hook_configpage(Template &$template): void
{ {
$moduleRoutesHelper = new ModuleRoutes(); $moduleRoutesHelper = new Routes();
$dataLinksKey = 'links'; $dataLinksKey = 'links';
...@@ -19,7 +19,7 @@ function accounting_hook_configpage(Template &$template): void ...@@ -19,7 +19,7 @@ function accounting_hook_configpage(Template &$template): void
} }
$template->data[$dataLinksKey][] = [ $template->data[$dataLinksKey][] = [
'href' => $moduleRoutesHelper->getUrl(ModuleRoutes::PATH_ADMIN_CONFIGURATION_STATUS), 'href' => $moduleRoutesHelper->getUrl(Routes::PATH_ADMIN_CONFIGURATION_STATUS),
'text' => Translate::noop('Accounting configuration status'), 'text' => Translate::noop('Accounting configuration status'),
]; ];
......
...@@ -39,4 +39,4 @@ ...@@ -39,4 +39,4 @@
max-height: 0; max-height: 0;
overflow: hidden; overflow: hidden;
transition: max-height 0.2s ease-out; transition: max-height 0.2s ease-out;
} }
\ No newline at end of file
...@@ -458,4 +458,30 @@ ...@@ -458,4 +458,30 @@
display: none; display: none;
} }
} }
\ No newline at end of file
/** Alerts */
/* The alert message box */
.alerts .alert {
padding: 20px;
margin-bottom: 15px;
}
/* The close button */
.close-btn {
margin-left: 15px;
color: white;
font-weight: bold;
float: right;
font-size: 22px;
line-height: 20px;
cursor: pointer;
transition: 0.3s;
}
/* When moving the mouse over the close button */
.close-btn:hover {
color: black;
}
accounting-admin-configuration-status: accounting-admin-configuration-status:
path: /admin/configuration/status path: /admin/configuration/status
defaults: { _controller: 'SimpleSAML\Module\accounting\Http\Controllers\Admin\Configuration::status' } controller: SimpleSAML\Module\accounting\Http\Controllers\Admin\Configuration::status
accounting-user-personal-data: accounting-user-personal-data:
path: /user/personal-data path: /user/personal-data
defaults: { _controller: 'SimpleSAML\Module\accounting\Http\Controllers\User\Profile::personalData' } controller: SimpleSAML\Module\accounting\Http\Controllers\User\Profile::personalData
accounting-user-connected-organizations: accounting-user-connected-organizations:
path: /user/connected-organizations path: /user/connected-organizations
defaults: { _controller: 'SimpleSAML\Module\accounting\Http\Controllers\User\Profile::connectedOrganizations' } controller: SimpleSAML\Module\accounting\Http\Controllers\User\Profile::connectedOrganizations
accounting-user-activity: accounting-user-activity:
path: /user/activity path: /user/activity
defaults: { _controller: 'SimpleSAML\Module\accounting\Http\Controllers\User\Profile::activity' } controller: SimpleSAML\Module\accounting\Http\Controllers\User\Profile::activity
accounting-user-oidc-tokens:
path: /user/oidc-tokens
controller: SimpleSAML\Module\accounting\Http\Controllers\User\Profile::oidcTokens
accounting-user-oidc-token-revoke:
path: /user/oidc-tokens/revoke
controller: SimpleSAML\Module\accounting\Http\Controllers\User\Profile::oidcTokenRevoke
methods: POST
accounting-user-oidc-token-revoke-xhr:
path: /user/oidc-tokens/revoke-xhr
controller: SimpleSAML\Module\accounting\Http\Controllers\User\Profile::oidcTokenRevokeXhr
methods: POST
accounting-user-logout: accounting-user-logout:
path: /user/logout path: /user/logout
controller: SimpleSAML\Module\accounting\Http\Controllers\User\Profile::logout
methods: methods:
- GET - GET
- POST - POST
defaults: { _controller: 'SimpleSAML\Module\accounting\Http\Controllers\User\Profile::logout' }
...@@ -4,6 +4,7 @@ declare(strict_types=1); ...@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SimpleSAML\Module\accounting\Entities\Bases; namespace SimpleSAML\Module\accounting\Entities\Bases;
use SimpleSAML\Module\accounting\Entities\Interfaces\AuthenticationProtocolInterface;
use SimpleSAML\Module\accounting\Entities\Interfaces\ProviderInterface; use SimpleSAML\Module\accounting\Entities\Interfaces\ProviderInterface;
abstract class AbstractProvider implements ProviderInterface abstract class AbstractProvider implements ProviderInterface
...@@ -52,4 +53,5 @@ abstract class AbstractProvider implements ProviderInterface ...@@ -52,4 +53,5 @@ abstract class AbstractProvider implements ProviderInterface
abstract public function getName(string $locale = 'en'): ?string; abstract public function getName(string $locale = 'en'): ?string;
abstract public function getDescription(string $locale = 'en'): ?string; abstract public function getDescription(string $locale = 'en'): ?string;
abstract protected function resolveEntityId(): string; abstract protected function resolveEntityId(): string;
abstract public function getProtocol(): AuthenticationProtocolInterface;
} }
...@@ -9,10 +9,13 @@ use SimpleSAML\Module\accounting\Entities\Interfaces\StateInterface; ...@@ -9,10 +9,13 @@ use SimpleSAML\Module\accounting\Entities\Interfaces\StateInterface;
use SimpleSAML\Module\accounting\Exceptions\UnexpectedValueException; use SimpleSAML\Module\accounting\Exceptions\UnexpectedValueException;
use SimpleSAML\Module\accounting\Services\HelpersManager; use SimpleSAML\Module\accounting\Services\HelpersManager;
use DateTimeImmutable; use DateTimeImmutable;
use SimpleSAML\Module\accounting\Traits\HasUserAttributesTrait;
use Throwable; use Throwable;
abstract class AbstractState implements StateInterface abstract class AbstractState implements StateInterface
{ {
use HasUserAttributesTrait;
public const KEY_ATTRIBUTES = 'Attributes'; public const KEY_ATTRIBUTES = 'Attributes';
public const KEY_ACCOUNTING = 'accounting'; public const KEY_ACCOUNTING = 'accounting';
public const ACCOUNTING_KEY_CLIENT_IP_ADDRESS = 'client_ip_address'; public const ACCOUNTING_KEY_CLIENT_IP_ADDRESS = 'client_ip_address';
...@@ -20,7 +23,6 @@ abstract class AbstractState implements StateInterface ...@@ -20,7 +23,6 @@ abstract class AbstractState implements StateInterface
protected string $identityProviderEntityId; protected string $identityProviderEntityId;
protected string $serviceProviderEntityId; protected string $serviceProviderEntityId;
protected array $attributes;
protected DateTimeImmutable $createdAt; protected DateTimeImmutable $createdAt;
protected ?DateTimeImmutable $authenticationInstant; protected ?DateTimeImmutable $authenticationInstant;
protected array $identityProviderMetadata; protected array $identityProviderMetadata;
...@@ -99,29 +101,6 @@ abstract class AbstractState implements StateInterface ...@@ -99,29 +101,6 @@ abstract class AbstractState implements StateInterface
return $this->serviceProviderEntityId; return $this->serviceProviderEntityId;
} }
public function getAttributes(): array
{
return $this->attributes;
}
public function getFirstAttributeValue(string $attributeName): ?string
{
if (($value = $this->getAttributeValue($attributeName)) !== null) {
return (string)reset($value);
}
return null;
}
public function getAttributeValue(string $attributeName): ?array
{
if (!empty($this->attributes[$attributeName]) && is_array($this->attributes[$attributeName])) {
return $this->attributes[$attributeName];
}
return null;
}
public function getCreatedAt(): DateTimeImmutable public function getCreatedAt(): DateTimeImmutable
{ {
return $this->createdAt; return $this->createdAt;
......
...@@ -13,4 +13,5 @@ interface ProviderInterface ...@@ -13,4 +13,5 @@ interface ProviderInterface
public function getName(string $locale = 'en'): ?string; public function getName(string $locale = 'en'): ?string;
public function getEntityId(): string; public function getEntityId(): string;
public function getDescription(string $locale = 'en'): ?string; public function getDescription(string $locale = 'en'): ?string;
public function getProtocol(): AuthenticationProtocolInterface;
} }
...@@ -4,7 +4,9 @@ declare(strict_types=1); ...@@ -4,7 +4,9 @@ declare(strict_types=1);
namespace SimpleSAML\Module\accounting\Entities\Providers\Identity; namespace SimpleSAML\Module\accounting\Entities\Providers\Identity;
use SimpleSAML\Module\accounting\Entities\Authentication;
use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider; use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider;
use SimpleSAML\Module\accounting\Entities\Interfaces\AuthenticationProtocolInterface;
use SimpleSAML\Module\accounting\Entities\Interfaces\IdentityProviderInterface; use SimpleSAML\Module\accounting\Entities\Interfaces\IdentityProviderInterface;
use SimpleSAML\Module\accounting\Exceptions\MetadataException; use SimpleSAML\Module\accounting\Exceptions\MetadataException;
...@@ -36,4 +38,9 @@ class Oidc extends AbstractProvider implements IdentityProviderInterface ...@@ -36,4 +38,9 @@ class Oidc extends AbstractProvider implements IdentityProviderInterface
throw new MetadataException('OpenID Provider metadata does not contain entity ID.'); throw new MetadataException('OpenID Provider metadata does not contain entity ID.');
} }
public function getProtocol(): AuthenticationProtocolInterface
{
return new Authentication\Protocol\Oidc();
}
} }
...@@ -4,7 +4,9 @@ declare(strict_types=1); ...@@ -4,7 +4,9 @@ declare(strict_types=1);
namespace SimpleSAML\Module\accounting\Entities\Providers\Identity; namespace SimpleSAML\Module\accounting\Entities\Providers\Identity;
use SimpleSAML\Module\accounting\Entities\Authentication;
use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider; use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider;
use SimpleSAML\Module\accounting\Entities\Interfaces\AuthenticationProtocolInterface;
use SimpleSAML\Module\accounting\Entities\Interfaces\IdentityProviderInterface; use SimpleSAML\Module\accounting\Entities\Interfaces\IdentityProviderInterface;
use SimpleSAML\Module\accounting\Exceptions\MetadataException; use SimpleSAML\Module\accounting\Exceptions\MetadataException;
...@@ -38,4 +40,9 @@ class Saml2 extends AbstractProvider implements IdentityProviderInterface ...@@ -38,4 +40,9 @@ class Saml2 extends AbstractProvider implements IdentityProviderInterface
throw new MetadataException('Identity provider metadata does not contain entity ID.'); throw new MetadataException('Identity provider metadata does not contain entity ID.');
} }
public function getProtocol(): AuthenticationProtocolInterface
{
return new Authentication\Protocol\Saml2();
}
} }
...@@ -4,7 +4,9 @@ declare(strict_types=1); ...@@ -4,7 +4,9 @@ declare(strict_types=1);
namespace SimpleSAML\Module\accounting\Entities\Providers\Service; namespace SimpleSAML\Module\accounting\Entities\Providers\Service;
use SimpleSAML\Module\accounting\Entities\Authentication;
use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider; use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider;
use SimpleSAML\Module\accounting\Entities\Interfaces\AuthenticationProtocolInterface;
use SimpleSAML\Module\accounting\Entities\Interfaces\ServiceProviderInterface; use SimpleSAML\Module\accounting\Entities\Interfaces\ServiceProviderInterface;
use SimpleSAML\Module\accounting\Exceptions\MetadataException; use SimpleSAML\Module\accounting\Exceptions\MetadataException;
...@@ -38,4 +40,9 @@ class Oidc extends AbstractProvider implements ServiceProviderInterface ...@@ -38,4 +40,9 @@ class Oidc extends AbstractProvider implements ServiceProviderInterface
throw new MetadataException('Relying Provider metadata does not contain entity ID.'); throw new MetadataException('Relying Provider metadata does not contain entity ID.');
} }
public function getProtocol(): AuthenticationProtocolInterface
{
return new Authentication\Protocol\Oidc();
}
} }
...@@ -4,7 +4,9 @@ declare(strict_types=1); ...@@ -4,7 +4,9 @@ declare(strict_types=1);
namespace SimpleSAML\Module\accounting\Entities\Providers\Service; namespace SimpleSAML\Module\accounting\Entities\Providers\Service;
use SimpleSAML\Module\accounting\Entities\Authentication;
use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider; use SimpleSAML\Module\accounting\Entities\Bases\AbstractProvider;
use SimpleSAML\Module\accounting\Entities\Interfaces\AuthenticationProtocolInterface;
use SimpleSAML\Module\accounting\Entities\Interfaces\ServiceProviderInterface; use SimpleSAML\Module\accounting\Entities\Interfaces\ServiceProviderInterface;
use SimpleSAML\Module\accounting\Exceptions\MetadataException; use SimpleSAML\Module\accounting\Exceptions\MetadataException;
...@@ -38,4 +40,9 @@ class Saml2 extends AbstractProvider implements ServiceProviderInterface ...@@ -38,4 +40,9 @@ class Saml2 extends AbstractProvider implements ServiceProviderInterface
throw new MetadataException('Service provider metadata does not contain entity ID.'); throw new MetadataException('Service provider metadata does not contain entity ID.');
} }
public function getProtocol(): AuthenticationProtocolInterface
{
return new Authentication\Protocol\Saml2();
}
} }
...@@ -4,20 +4,14 @@ declare(strict_types=1); ...@@ -4,20 +4,14 @@ declare(strict_types=1);
namespace SimpleSAML\Module\accounting\Entities; namespace SimpleSAML\Module\accounting\Entities;
use SimpleSAML\Module\accounting\Traits\HasUserAttributesTrait;
class User class User
{ {
protected array $attributes; use HasUserAttributesTrait;
public function __construct(array $attributes) public function __construct(array $attributes)
{ {
$this->attributes = $attributes; $this->attributes = $attributes;
} }
/**
* @return array
*/
public function getAttributes(): array
{
return $this->attributes;
}
} }
...@@ -17,4 +17,24 @@ class Arr ...@@ -17,4 +17,24 @@ class Arr
ksort($array); ksort($array);
} }
/**
* @param array $array
* @param int|string $key
* @return array
*/
public function groupByValue(array $array, $key): array
{
return array_reduce($array, function (array $carry, array $item) use ($key) {
/** @psalm-suppress MixedArrayOffset, MixedArrayAssignment */
$carry[$item[$key]][] = $item;
return $carry;
}, []);
}
public function isAssociative(array $array): bool
{
$keys = array_keys($array);
return $keys !== array_keys($keys);
}
} }
...@@ -9,6 +9,7 @@ use DateTimeImmutable; ...@@ -9,6 +9,7 @@ use DateTimeImmutable;
class DateTime class DateTime
{ {
public const FORMAT_MYSQL = 'Y-m-d H:i:s';
/** /**
* Convert date interval to seconds, interval being minimum 1 second. * Convert date interval to seconds, interval being minimum 1 second.
* @param DateInterval $dateInterval Minimum is 1 second. * @param DateInterval $dateInterval Minimum is 1 second.
...@@ -27,4 +28,13 @@ class DateTime ...@@ -27,4 +28,13 @@ class DateTime
return $duration; return $duration;
} }
public function toFormattedString(
\DateTimeInterface $dateTime = null,
string $format = self::FORMAT_MYSQL
): string {
$dateTime = $dateTime ?? new DateTimeImmutable();
return $dateTime->format($format);
}
} }
...@@ -8,7 +8,7 @@ use Throwable; ...@@ -8,7 +8,7 @@ use Throwable;
class Random class Random
{ {
public function getRandomInt(int $minimum = PHP_INT_MIN, int $maximum = PHP_INT_MAX): int public function getInt(int $minimum = PHP_INT_MIN, int $maximum = PHP_INT_MAX): int
{ {
try { try {
return random_int($minimum, $maximum); return random_int($minimum, $maximum);
...@@ -18,4 +18,15 @@ class Random ...@@ -18,4 +18,15 @@ class Random
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
} }
} }
public function getString(int $length = 16): string
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[$this->getInt(0, $charactersLength - 1)];
}
return $randomString;
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment