Skip to content

Commit fd78470

Browse files
committed
Publish Status List Tokens and serve them from an endpoint
1 parent 9d5dc2b commit fd78470

33 files changed

Lines changed: 3548 additions & 4 deletions

config/module_oidc.php.dist

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,30 @@ $config = [
16391639
// ],
16401640
// ],
16411641

1642+
/**
1643+
* (optional) How many requests per minute a single client may make to
1644+
* the Status List endpoint. The default, 0, means no limit at all.
1645+
*
1646+
* The endpoint is unauthenticated and one response can reach a couple of
1647+
* hundred kilobytes, so putting a ceiling on how much a single client can
1648+
* pull is worth considering. There are two things to check before you do.
1649+
*
1650+
* First, clients are told apart only by the IP address that reaches PHP
1651+
* (REMOTE_ADDR). If a reverse proxy, load balancer or CDN sits in front
1652+
* of SimpleSAMLphp, then that address is the proxy's own, and it is the
1653+
* same one for every request. All clients would share a single counter,
1654+
* which their combined traffic exhausts quickly, and the endpoint would
1655+
* start refusing legitimate requests. That matters more here than on
1656+
* other endpoints: wallets and verifiers read this endpoint to tell a
1657+
* valid credential from a revoked one, so refusing them makes already
1658+
* issued credentials unverifiable. Confirm which address actually
1659+
* arrives at PHP before setting a limit.
1660+
*
1661+
* Second, counting requires a protocol cache. If none is configured this
1662+
* option has no effect: nothing is counted and no request is refused.
1663+
*/
1664+
// ModuleConfig::OPTION_VCI_STATUS_LIST_REQUESTS_PER_MINUTE => 60,
1665+
16421666
/**
16431667
* Map of authentication sources and user's email attribute names. This
16441668
* enables you to define a specific attribute name which contains the

hooks/hook_cron.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use SimpleSAML\Module\oidc\ModuleConfig;
2020
use SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException;
2121
use SimpleSAML\Module\oidc\Services\ExpiredEntriesCleaner;
22+
use SimpleSAML\Module\oidc\StatusList\StatusListReconciler;
2223

2324
/**
2425
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
@@ -58,4 +59,26 @@ function oidc_hook_cron(array &$croninfo): void
5859
Logger::warning($message);
5960
$croninfo['summary'][] = $message;
6061
}
62+
63+
// Kept apart from the clean-up above rather than folded into the same try. The two are unrelated,
64+
// and a failure of one says nothing about whether the other should run.
65+
try {
66+
$kernel = new Kernel(ModuleConfig::MODULE_NAME);
67+
$kernel->boot();
68+
/** @var \SimpleSAML\Module\oidc\StatusList\StatusListReconciler $reconciler */
69+
$reconciler = $kernel->getContainer()->get(StatusListReconciler::class);
70+
$invalidated = $reconciler->reconcile();
71+
72+
if ($invalidated > 0) {
73+
$croninfo['summary'][] = sprintf(
74+
'Module `oidc` Status List reconciliation. Invalidated %d published token(s) which no ' .
75+
'longer described their list.',
76+
$invalidated,
77+
);
78+
}
79+
} catch (Throwable $e) {
80+
$message = 'Module `oidc` Status List reconciliation cron script failed: ' . $e->getMessage();
81+
Logger::warning($message);
82+
$croninfo['summary'][] = $message;
83+
}
6184
}

locales/en/LC_MESSAGES/oidc.po

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,3 +1591,22 @@ msgstr ""
15911591
msgid "These pools are inert, since Status Lists are disabled."
15921592
msgstr ""
15931593

1594+
1595+
msgid "Status List Requests Per Minute"
1596+
msgstr ""
1597+
1598+
msgid "No limit"
1599+
msgstr ""
1600+
1601+
msgid ""
1602+
"Applied to the address the request appears to come from, which behind a "
1603+
"reverse proxy is the proxy unless it is trusted. Confirm which address "
1604+
"arrives here, since one shared bucket would refuse every client. Needs a "
1605+
"protocol cache; without one nothing is counted."
1606+
msgstr ""
1607+
1608+
msgid ""
1609+
"The Status List endpoint accepts any number of requests. It is "
1610+
"unauthenticated and its response can reach a couple of hundred "
1611+
"kilobytes."
1612+
msgstr ""

locales/es/LC_MESSAGES/oidc.po

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,3 +1591,22 @@ msgstr ""
15911591
msgid "These pools are inert, since Status Lists are disabled."
15921592
msgstr ""
15931593

1594+
1595+
msgid "Status List Requests Per Minute"
1596+
msgstr ""
1597+
1598+
msgid "No limit"
1599+
msgstr ""
1600+
1601+
msgid ""
1602+
"Applied to the address the request appears to come from, which behind a "
1603+
"reverse proxy is the proxy unless it is trusted. Confirm which address "
1604+
"arrives here, since one shared bucket would refuse every client. Needs a "
1605+
"protocol cache; without one nothing is counted."
1606+
msgstr ""
1607+
1608+
msgid ""
1609+
"The Status List endpoint accepts any number of requests. It is "
1610+
"unauthenticated and its response can reach a couple of hundred "
1611+
"kilobytes."
1612+
msgstr ""

locales/fr/LC_MESSAGES/oidc.po

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,3 +1591,22 @@ msgstr ""
15911591
msgid "These pools are inert, since Status Lists are disabled."
15921592
msgstr ""
15931593

1594+
1595+
msgid "Status List Requests Per Minute"
1596+
msgstr ""
1597+
1598+
msgid "No limit"
1599+
msgstr ""
1600+
1601+
msgid ""
1602+
"Applied to the address the request appears to come from, which behind a "
1603+
"reverse proxy is the proxy unless it is trusted. Confirm which address "
1604+
"arrives here, since one shared bucket would refuse every client. Needs a "
1605+
"protocol cache; without one nothing is counted."
1606+
msgstr ""
1607+
1608+
msgid ""
1609+
"The Status List endpoint accepts any number of requests. It is "
1610+
"unauthenticated and its response can reach a couple of hundred "
1611+
"kilobytes."
1612+
msgstr ""

locales/hr/LC_MESSAGES/oidc.po

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,3 +1639,22 @@ msgstr ""
16391639
msgid "These pools are inert, since Status Lists are disabled."
16401640
msgstr ""
16411641

1642+
1643+
msgid "Status List Requests Per Minute"
1644+
msgstr ""
1645+
1646+
msgid "No limit"
1647+
msgstr ""
1648+
1649+
msgid ""
1650+
"Applied to the address the request appears to come from, which behind a "
1651+
"reverse proxy is the proxy unless it is trusted. Confirm which address "
1652+
"arrives here, since one shared bucket would refuse every client. Needs a "
1653+
"protocol cache; without one nothing is counted."
1654+
msgstr ""
1655+
1656+
msgid ""
1657+
"The Status List endpoint accepts any number of requests. It is "
1658+
"unauthenticated and its response can reach a couple of hundred "
1659+
"kilobytes."
1660+
msgstr ""

locales/it/LC_MESSAGES/oidc.po

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,3 +1591,22 @@ msgstr ""
15911591
msgid "These pools are inert, since Status Lists are disabled."
15921592
msgstr ""
15931593

1594+
1595+
msgid "Status List Requests Per Minute"
1596+
msgstr ""
1597+
1598+
msgid "No limit"
1599+
msgstr ""
1600+
1601+
msgid ""
1602+
"Applied to the address the request appears to come from, which behind a "
1603+
"reverse proxy is the proxy unless it is trusted. Confirm which address "
1604+
"arrives here, since one shared bucket would refuse every client. Needs a "
1605+
"protocol cache; without one nothing is counted."
1606+
msgstr ""
1607+
1608+
msgid ""
1609+
"The Status List endpoint accepts any number of requests. It is "
1610+
"unauthenticated and its response can reach a couple of hundred "
1611+
"kilobytes."
1612+
msgstr ""

locales/nl/LC_MESSAGES/oidc.po

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,3 +1545,22 @@ msgstr ""
15451545
msgid "These pools are inert, since Status Lists are disabled."
15461546
msgstr ""
15471547

1548+
1549+
msgid "Status List Requests Per Minute"
1550+
msgstr ""
1551+
1552+
msgid "No limit"
1553+
msgstr ""
1554+
1555+
msgid ""
1556+
"Applied to the address the request appears to come from, which behind a "
1557+
"reverse proxy is the proxy unless it is trusted. Confirm which address "
1558+
"arrives here, since one shared bucket would refuse every client. Needs a "
1559+
"protocol cache; without one nothing is counted."
1560+
msgstr ""
1561+
1562+
msgid ""
1563+
"The Status List endpoint accepts any number of requests. It is "
1564+
"unauthenticated and its response can reach a couple of hundred "
1565+
"kilobytes."
1566+
msgstr ""

routing/routes/routes.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use SimpleSAML\Module\oidc\Controllers\OAuth2\TokenIntrospectionController;
2323
use SimpleSAML\Module\oidc\Controllers\PushedAuthorizationController;
2424
use SimpleSAML\Module\oidc\Controllers\RegistrationController;
25+
use SimpleSAML\Module\oidc\Controllers\StatusListController;
2526
use SimpleSAML\Module\oidc\Controllers\UserInfoController;
2627
use SimpleSAML\Module\oidc\Controllers\VerifiableCredentials\CredentialIssuerConfigurationController;
2728
use SimpleSAML\Module\oidc\Controllers\VerifiableCredentials\CredentialIssuerCredentialController;
@@ -160,6 +161,12 @@
160161
->controller([CredentialJsonLdContextController::class, 'context'])
161162
->methods([HttpMethodsEnum::GET->value]);
162163

164+
// Not registered under the Verifiable Credential Issuance switch, on purpose: credentials already
165+
// issued resolve their status here, so this has to keep answering after issuance is turned off.
166+
$routes->add(RoutesEnum::StatusList->name, RoutesEnum::StatusList->value)
167+
->controller([StatusListController::class, 'statusList'])
168+
->methods([HttpMethodsEnum::GET->value]);
169+
163170
/*****************************************************************************************************************
164171
* SD-JWT-based Verifiable Credentials (SD-JWT VC)
165172
****************************************************************************************************************/

routing/services/services.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ services:
4545
alias: SimpleSAML\Module\oidc\StatusList\DbStatusIndexAllocator
4646
SimpleSAML\Module\oidc\StatusList\Contracts\StatusUpdaterInterface:
4747
alias: SimpleSAML\Module\oidc\StatusList\DbStatusUpdater
48+
SimpleSAML\Module\oidc\StatusList\Contracts\StatusListTokenProviderInterface:
49+
alias: SimpleSAML\Module\oidc\StatusList\DbStatusListTokenProvider
50+
51+
# Fetched from the (otherwise private) container by the cron hook after booting the module Kernel.
52+
SimpleSAML\Module\oidc\StatusList\StatusListReconciler:
53+
public: true
4854

4955
SimpleSAML\Module\oidc\Factories\:
5056
resource: '../../src/Factories/*'
@@ -123,6 +129,7 @@ services:
123129
SimpleSAML\Module\oidc\Utils\UiLocalesResolver: ~
124130
SimpleSAML\Module\oidc\Utils\ClassInstanceBuilder: ~
125131
SimpleSAML\Module\oidc\Utils\DateIntervalFormatter: ~
132+
SimpleSAML\Module\oidc\Utils\HttpContentNegotiator: ~
126133
SimpleSAML\Module\oidc\Utils\JwksResolver: ~
127134
SimpleSAML\Module\oidc\Utils\AuthenticatedOAuth2ClientResolver: ~
128135
SimpleSAML\Module\oidc\Utils\VciContextResolver: ~

0 commit comments

Comments
 (0)