Skip to content

Commit 6d4245b

Browse files
committed
WIP
1 parent f041094 commit 6d4245b

File tree

10 files changed

+250
-7
lines changed

10 files changed

+250
-7
lines changed

routing/routes/routes.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
->controller([ConfigController::class, 'protocolSettings']);
4141
$routes->add(RoutesEnum::AdminConfigFederation->name, RoutesEnum::AdminConfigFederation->value)
4242
->controller([ConfigController::class, 'federationSettings']);
43+
$routes->add(RoutesEnum::AdminConfigVerifiableCredential->name, RoutesEnum::AdminConfigVerifiableCredential->value)
44+
->controller([ConfigController::class, 'verifiableCredentialSettings']);
4345

4446
// Client management
4547

@@ -112,10 +114,14 @@
112114
->methods([HttpMethodsEnum::GET->value]);
113115

114116
/*****************************************************************************************************************
115-
* OpenID Verifiable Credential Issuance
117+
* OpenID for Verifiable Credential Issuance
116118
****************************************************************************************************************/
117119

118120
$routes->add(RoutesEnum::CredentialIssuerConfiguration->name, RoutesEnum::CredentialIssuerConfiguration->value)
119121
->controller([CredentialIssuerConfigurationController::class, 'configuration'])
120122
->methods([HttpMethodsEnum::GET->value]);
123+
124+
$routes->add(RoutesEnum::CredentialIssuerCredential->name, RoutesEnum::CredentialIssuerCredential->value)
125+
->controller([CredentialIssuerConfigurationController::class, 'credential'])
126+
->methods([HttpMethodsEnum::GET->value]);
121127
};

src/Codebooks/RoutesEnum.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ enum RoutesEnum: string
1212

1313
case AdminConfigProtocol = 'admin/config/protocol';
1414
case AdminConfigFederation = 'admin/config/federation';
15+
case AdminConfigVerifiableCredential = 'admin/config/verifiable-credential';
1516
case AdminMigrations = 'admin/migrations';
1617
case AdminMigrationsRun = 'admin/migrations/run';
1718

@@ -45,7 +46,7 @@ enum RoutesEnum: string
4546
****************************************************************************************************************/
4647

4748
// OAuth 2.0 Authorization Server Metadata https://www.rfc-editor.org/rfc/rfc8414.html
48-
case OAuth2Configuration = '/.well-known/oauth-authorization-server';
49+
case OAuth2Configuration = '.well-known/oauth-authorization-server';
4950

5051
/*****************************************************************************************************************
5152
* OpenID Federation
@@ -56,8 +57,9 @@ enum RoutesEnum: string
5657
case FederationList = 'federation/list';
5758

5859
/*****************************************************************************************************************
59-
* OpenID Verifiable Credential Issuance
60+
* OpenID for Verifiable Credential Issuance
6061
****************************************************************************************************************/
6162

6263
case CredentialIssuerConfiguration = '.well-known/openid-credential-issuer';
64+
case CredentialIssuerCredential = 'credential-issuer/credential';
6365
}

src/Controllers/Admin/ConfigController.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,15 @@ function (string $token): Federation\TrustMark {
104104
RoutesEnum::AdminConfigFederation->value,
105105
);
106106
}
107+
108+
public function verifiableCredentialSettings(): Response
109+
{
110+
return $this->templateFactory->build(
111+
'oidc:config/verifiable-credential.twig',
112+
[
113+
'moduleConfig' => $this->moduleConfig,
114+
],
115+
RoutesEnum::AdminConfigVerifiableCredential->value,
116+
);
117+
}
107118
}

src/Controllers/VerifiableCredentials/CredentialIssuerConfigurationController.php

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use SimpleSAML\Module\oidc\Utils\Routes;
1919
use SimpleSAML\OpenID\Codebooks\ClaimsEnum;
2020
use SimpleSAML\OpenID\Codebooks\CredentialFormatIdentifiersEnum;
21+
use SimpleSAML\OpenID\Codebooks\LanguageTagsEnum;
2122
use Symfony\Component\HttpFoundation\Response;
2223

2324
class CredentialIssuerConfigurationController
@@ -48,7 +49,7 @@ public function configuration(): Response
4849
// authorization_servers
4950

5051
// REQUIRED
51-
// TODO credential_endpoint
52+
ClaimsEnum::CredentialEndpoint->value => $this->routes->urlCredentialIssuerCredential(),
5253

5354
// OPTIONAL
5455
// nonce_endpoint
@@ -81,7 +82,9 @@ public function configuration(): Response
8182

8283
ClaimsEnum::CredentialConfigurationsSupported->value => [
8384
'ResearchAndScholarshipCredentialJwtVcJson' => [
85+
// REQUIRED
8486
ClaimsEnum::Format->value => CredentialFormatIdentifiersEnum::JwtVcJson->value,
87+
// OPTIONAL
8588
ClaimsEnum::Scope->value => 'ResearchAndScholarshipCredentialJwtVcJson',
8689

8790
// OPTIONAL
@@ -117,10 +120,141 @@ public function configuration(): Response
117120
],
118121
],
119122

120-
// As per appendix A.1.1.2. https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-vc-signed-as-a-jwt-not-usin
123+
// OPTIONAL A.1.1.2. https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-vc-signed-as-a-jwt-not-usin
121124
ClaimsEnum::Claims->value => [
125+
/**
126+
* https://refeds.org/category/research-and-scholarship
127+
*
128+
* The R&S attribute bundle consists (abstractly) of the following required data elements:
129+
*
130+
* shared user identifier
131+
* person name
132+
* email address
133+
*
134+
* and one optional data element:
135+
*
136+
* affiliation
137+
*
138+
* where shared user identifier is a persistent, non-reassigned, non-targeted identifier
139+
* defined to be either of the following:
140+
*
141+
* eduPersonPrincipalName (if non-reassigned)
142+
* eduPersonPrincipalName + eduPersonTargetedID
143+
*
144+
* and where person name is defined to be either (or both) of the following:
145+
*
146+
* displayName
147+
* givenName + sn
148+
*
149+
* and where email address is defined to be the mail attribute,
150+
*
151+
* and where affiliation is defined to be the eduPersonScopedAffiliation attribute.
152+
*
153+
* All of the above attributes are defined or referenced in the [eduPerson] specification. The
154+
* specific naming and format of these attributes is guided by the protocol in use. For SAML
155+
* 2.0 the [SAMLAttr] profile MUST be used. This specification may be extended to reference
156+
* other protocol-specific formulations as circumstances warrant.
157+
*/
158+
[
159+
// REQUIRED
160+
ClaimsEnum::Path->value => [
161+
ClaimsEnum::Credential_Subject->value,
162+
'eduPersonPrincipalName',
163+
],
164+
// OPTIONAL
165+
ClaimsEnum::Mandatory->value => true,
166+
// OPTIONAL
167+
ClaimsEnum::Display->value => [
168+
[
169+
// OPTIONAL
170+
ClaimsEnum::Name->value => 'Principal Name',
171+
// OPTIONAL
172+
ClaimsEnum::Locale->value => LanguageTagsEnum::EnUs->value,
173+
],
174+
],
175+
],
176+
[
177+
ClaimsEnum::Path->value => [
178+
ClaimsEnum::Credential_Subject->value,
179+
'eduPersonTargetedID',
180+
],
181+
ClaimsEnum::Mandatory->value => false,
182+
ClaimsEnum::Display->value => [
183+
[
184+
ClaimsEnum::Name->value => 'Targeted ID',
185+
ClaimsEnum::Locale->value => LanguageTagsEnum::EnUs->value,
186+
],
187+
],
188+
],
189+
[
190+
ClaimsEnum::Path->value => [
191+
ClaimsEnum::Credential_Subject->value,
192+
'displayName',
193+
],
194+
ClaimsEnum::Mandatory->value => false,
195+
ClaimsEnum::Display->value => [
196+
[
197+
ClaimsEnum::Name->value => 'Display Name',
198+
ClaimsEnum::Locale->value => LanguageTagsEnum::EnUs->value,
199+
],
200+
],
201+
],
122202
[
203+
ClaimsEnum::Path->value => [
204+
ClaimsEnum::Credential_Subject->value,
205+
'givenName',
206+
],
207+
ClaimsEnum::Mandatory->value => false,
208+
ClaimsEnum::Display->value => [
209+
[
210+
ClaimsEnum::Name->value => 'Given Name',
211+
ClaimsEnum::Locale->value => LanguageTagsEnum::EnUs->value,
212+
],
213+
],
214+
],
215+
[
216+
ClaimsEnum::Path->value => [
217+
ClaimsEnum::Credential_Subject->value,
218+
'sn',
219+
],
220+
ClaimsEnum::Display->value => [
221+
[
222+
ClaimsEnum::Name->value => 'Last Name',
223+
ClaimsEnum::Locale->value => LanguageTagsEnum::EnUs->value,
224+
],
225+
],
226+
],
227+
[
228+
ClaimsEnum::Path->value => [
229+
ClaimsEnum::Credential_Subject->value,
230+
'mail',
231+
],
232+
ClaimsEnum::Display->value => [
233+
[
234+
ClaimsEnum::Name->value => 'Email Address',
235+
ClaimsEnum::Locale->value => LanguageTagsEnum::EnUs->value,
236+
],
237+
],
238+
],
239+
[
240+
ClaimsEnum::Path->value => [
241+
ClaimsEnum::Credential_Subject->value,
242+
'eduPersonScopedAffiliation',
243+
],
244+
ClaimsEnum::Display->value => [
245+
[
246+
ClaimsEnum::Name->value => 'Scoped Affiliation',
247+
ClaimsEnum::Locale->value => LanguageTagsEnum::EnUs->value,
248+
],
249+
],
250+
],
251+
],
123252

253+
// REQUIRED
254+
ClaimsEnum::CredentialDefinition->value => [
255+
ClaimsEnum::Type->value => [
256+
'VerifiableCredential', // TODO mivanci CredentialTypesEnum
257+
'ResearchAndScholarshipCredentialJwtVcJson',
124258
],
125259
],
126260
],
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Module\oidc\Controllers\VerifiableCredentials;
6+
7+
use SimpleSAML\Module\oidc\ModuleConfig;
8+
use SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException;
9+
use SimpleSAML\Module\oidc\Utils\Routes;
10+
use Symfony\Component\HttpFoundation\Response;
11+
12+
class CredentialIssuerCredentialController
13+
{
14+
/**
15+
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
16+
*/
17+
public function __construct(
18+
protected readonly ModuleConfig $moduleConfig,
19+
protected readonly Routes $routes,
20+
) {
21+
if (!$this->moduleConfig->getVerifiableCredentialEnabled()) {
22+
throw OidcServerException::forbidden('Verifiable Credential capabilities not enabled');
23+
}
24+
}
25+
26+
public function credential(): Response
27+
{
28+
return $this->routes->newJsonResponse(
29+
[
30+
'credential' => 'credential',
31+
],
32+
);
33+
}
34+
}

src/Factories/TemplateFactory.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ protected function includeDefaultMenuItems(): void
141141
Translate::noop('Test Trust Mark Validation'),
142142
),
143143
);
144+
145+
$this->oidcMenu->addItem(
146+
$this->oidcMenu->buildItem(
147+
$this->moduleConfig->getModuleUrl(RoutesEnum::AdminConfigVerifiableCredential->value),
148+
Translate::noop('Verifiable Credential Settings'),
149+
),
150+
);
144151
}
145152

146153
public function setShowMenu(bool $showMenu): TemplateFactory

src/ModuleConfig.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ public function isFederationParticipationLimitedByTrustMarksFor(string $trustAnc
777777

778778

779779
/*****************************************************************************************************************
780-
* OpenID Verifiable Credential related config.
780+
* OpenID Verifiable Credential Issuance related config.
781781
****************************************************************************************************************/
782782

783783
public function getVerifiableCredentialEnabled(): bool

src/Services/AuthContextService.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,16 @@ public function requirePermission(string $neededPermission): void
8080
/**
8181
* @throws \Exception
8282
*/
83-
private function authenticate(): Simple
83+
public function authenticate(): Simple
8484
{
8585
$simple = $this->authSimpleFactory->getDefaultAuthSource();
8686
$simple->requireAuth();
8787
return $simple;
8888
}
89+
90+
public function logout(): void
91+
{
92+
$simple = $this->authSimpleFactory->getDefaultAuthSource();
93+
$simple->logout();
94+
}
8995
}

src/Utils/Routes.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ public function urlAdminTestTrustMarkValidation(array $parameters = []): string
146146
return $this->getModuleUrl(RoutesEnum::AdminTestTrustMarkValidation->value, $parameters);
147147
}
148148

149+
/*****************************************************************************************************************
150+
* OAuth 2.0 Authorization Server
151+
****************************************************************************************************************/
152+
153+
public function urlOAuth2Configuration(array $parameters = []): string
154+
{
155+
return $this->getModuleUrl(RoutesEnum::OAuth2Configuration->value, $parameters);
156+
}
157+
149158
/*****************************************************************************************************************
150159
* OpenID Connect URLs.
151160
****************************************************************************************************************/
@@ -198,4 +207,18 @@ public function urlFederationList(array $parameters = []): string
198207
{
199208
return $this->getModuleUrl(RoutesEnum::FederationList->value, $parameters);
200209
}
210+
211+
/*****************************************************************************************************************
212+
* OpenID for Verifiable Credential Issuance URLs.
213+
****************************************************************************************************************/
214+
215+
public function urlCredentialIssuerConfiguration(array $parameters = []): string
216+
{
217+
return $this->getModuleUrl(RoutesEnum::CredentialIssuerConfiguration->value, $parameters);
218+
}
219+
220+
public function urlCredentialIssuerCredential(array $parameters = []): string
221+
{
222+
return $this->getModuleUrl(RoutesEnum::CredentialIssuerCredential->value, $parameters);
223+
}
201224
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{% set subPageTitle = 'Verifiable Credential Settings'|trans %}
2+
3+
{% extends "@oidc/base.twig" %}
4+
5+
{% block oidcContent %}
6+
<p>
7+
{{ 'Verifiable Credential Enabled'|trans }}:
8+
{{ moduleConfig.getVerifiableCredentialEnabled ? 'Yes'|trans : 'No'|trans }}
9+
</p>
10+
11+
<h4>{{ 'Entity'|trans }}</h4>
12+
<p>
13+
{{ 'Configuration URL'|trans }}:
14+
<a href="{{ routes.urlCredentialIssuerConfiguration }}" target="_blank">{{ routes.urlCredentialIssuerConfiguration }}</a>
15+
</p>
16+
<p>
17+
{{ 'Issuer'|trans }}: {{ moduleConfig.getIssuer }}
18+
</p>
19+
20+
{% endblock oidcContent -%}

0 commit comments

Comments
 (0)