[java-idp-plugin-vci] branch main updated: Improve readability of examples
Codeberg
noreply at shibboleth.net
Thu Sep 24 18:08:29 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-idp-plugin-vci.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-vci/commit/4257210d3da264e21409dfb9d735beeff279a593
The following commit(s) were added to refs/heads/main by this push:
new 4257210 Improve readability of examples
4257210 is described below
commit 4257210d3da264e21409dfb9d735beeff279a593
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Thu Sep 24 21:08:11 2026 +0300
Improve readability of examples
---
README.md | 161 +++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 111 insertions(+), 50 deletions(-)
diff --git a/README.md b/README.md
index ca0f72c..3d12a8a 100644
--- a/README.md
+++ b/README.md
@@ -217,7 +217,7 @@ but it is not guaranteed that they work for you as such.
1. A did:jwk credential with both flows and the Status List. Signed with the key of the OP.
2. A second credential, did:web.
3. A third credential, the issuer is the plain url.
-4. The third credential is made an OpenID Federation credential. Own signing key is taken into use.
+4. The third credential is made an OpenID Federation credential.
5. A fourth credential, for a HAIP wallet. Signing key gets a certificate chain. The wallet is
the OpenID Foundation conformance suite.
6. Rolling the signing key to the next one.
@@ -484,11 +484,15 @@ OP. One thing you need to add is the credential scopes in `scopes_supported` of
*static/oauth-authorization-server.json*, a wallet of the code flow asks a credential by scope:
```json
+{
+ ...
"scopes_supported":[
"openid",
"GeantIncubatorDiploma_SDJWT",
"GeantIncubatorDiploma_W3C"
],
+ ...
+}
```
The `/.well-known/` locations are not IdP paths, you wire them in Jetty. For this step you need
@@ -499,6 +503,8 @@ file is in [Discovery documents](#discovery-documents).
<summary>Example snippet of etc/jetty-rewrite-rules.xml</summary>
```xml
+<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
+ ...
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
@@ -531,6 +537,7 @@ file is in [Discovery documents](#discovery-documents).
</New>
</Arg>
</Call>
+</Configure>
```
</details>
@@ -698,6 +705,8 @@ in the same *metadata/oidc-client.json* as the clients above:
<summary>Example snippet of metadata/oidc-client.json</summary>
```json
+[
+ ...
{
"client_id": "id.animo.paradym",
"client_name": "Paradym Wallet",
@@ -714,6 +723,7 @@ in the same *metadata/oidc-client.json* as the clients above:
"urn:ietf:params:oauth:grant-type:pre-authorized_code"
]
}
+]
```
</details>
@@ -1026,6 +1036,11 @@ The credential goes next to the two of Step 1 in *metadata/verifiable-credential
<summary>Example snippet of metadata/verifiable-credentials.json</summary>
```json
+{
+ "credential_configurations_supported": {
+ "GeantIncubatorDiploma_SDJWT": { "...": "..." },
+ "GeantIncubatorDiploma_W3C": { "...": "..." },
+ ...
"GeantIncubatorDiploma_DIDWEB": {
"format": "dc+sd-jwt",
"vct": "GeantIncubatorDiploma_DIDWEB",
@@ -1053,6 +1068,8 @@ The credential goes next to the two of Step 1 in *metadata/verifiable-credential
]
}
}
+ }
+}
```
</details>
@@ -1064,13 +1081,22 @@ and state it per credential.
Add **DID.Document** to the anonymous relying party in *conf/relying-party.xml*:
```xml
- <!-- A verifier resolves the did:web identifier from this -->
- <ref bean="DID.Document" />
+<bean id="shibboleth.UnverifiedRelyingParty" parent="RelyingParty">
+ <property name="profileConfigurations">
+ <list>
+ ...
+ <!-- A verifier resolves the did:web identifier from this -->
+ <ref bean="DID.Document" />
+ </list>
+ </property>
+</bean>
```
and wire it in *etc/jetty-rewrite-rules.xml*:
```xml
+<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
+ ...
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
@@ -1079,6 +1105,7 @@ and wire it in *etc/jetty-rewrite-rules.xml*:
</New>
</Arg>
</Call>
+</Configure>
```
The document has no file behind it. It is formed from the keys that sign credentials and Status
@@ -1162,9 +1189,21 @@ The credential in *metadata/verifiable-credentials.json* is like the one of Step
`GeantIncubatorDiploma_URL` and:
```json
+{
+ "credential_configurations_supported": {
+ ...
+ "GeantIncubatorDiploma_URL": {
+ "format": "dc+sd-jwt",
+ "vct": "GeantIncubatorDiploma_URL",
+ "scope": "GeantIncubatorDiploma_URL",
+ ...
"_issuance_configuration": {
"issuer": "url"
},
+ "credential_metadata": { "...": "..." }
+ }
+ }
+}
```
`url` is a keyword for the issuer of the OP. You may also write the url itself.
@@ -1172,13 +1211,22 @@ The credential in *metadata/verifiable-credentials.json* is like the one of Step
Add **OAuth.JWTVCIssuer** to the anonymous relying party:
```xml
- <!-- A verifier finds the key of a url issuer through this -->
- <ref bean="OAuth.JWTVCIssuer" />
+<bean id="shibboleth.UnverifiedRelyingParty" parent="RelyingParty">
+ <property name="profileConfigurations">
+ <list>
+ ...
+ <!-- A verifier finds the key of a url issuer through this -->
+ <ref bean="OAuth.JWTVCIssuer" />
+ </list>
+ </property>
+</bean>
```
and wire it in *etc/jetty-rewrite-rules.xml*:
```xml
+<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
+ ...
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
@@ -1187,6 +1235,7 @@ and wire it in *etc/jetty-rewrite-rules.xml*:
</New>
</Arg>
</Call>
+</Configure>
```
*static/jwt-vc-issuer.json* as it comes with the plugin is fine. Its `jwks_uri` is the keyset of
@@ -1205,42 +1254,29 @@ authority hints and so on, is configured in the plugins of [Dependencies](#depen
What is new:
-- an own signing key replaces the keys of the OP in credential signing
- the Entity Configuration at `/.well-known/openid-federation` has `openid_credential_issuer`
metadata and the credential signing keys
- the url credential carries `"fed": "https://issuer.example.org"`, the other credentials not
-#### Own signing key
+#### Signing key
-The federation part reads the signing keys of the credentials from
-**openidvci.SigningCredentials**, so that list has to be defined now. Generate an EC key the
-same way as the keys of the OP:
+The Entity Configuration publishes the keys credentials are signed with, and it reads them from
+**openidvci.SigningCredentials**. The keys of the OP are not visible to it, so the list has to
+be defined even if the signing key stays the same. The IdP does not start with the federation
+import and without the list.
-```bash
-bin/jwtgen.sh -t EC -c P-256 -u sig -i signingvci | tail -n +2 > credentials/openid-vci-signing-es.jwk
-```
-
-Uncomment the key and the list in *conf/openid-vci-credentials.xml*. Keep the EC key of the OP
-in the list after the new one. It is defined here again from the same file, as the bean of the
-OP is not visible where this file is imported:
+In *conf/openid-vci-credentials.xml* the EC key of the OP is defined again from the same file and
+put in the list. Nothing changes in signing:
```xml
-<bean id="openidvci.DefaultESSigningCredential" parent="shibboleth.JWKCredential"
- p:resource="%{openidvci.signing.es.key}" />
-
-<bean id="openidvci.PreviousESSigningCredential" parent="shibboleth.JWKCredential"
+<bean id="openidvci.OPESSigningCredential" parent="shibboleth.JWKCredential"
p:resource="%{idp.signing.oidc.es.key}" />
<util:list id="openidvci.SigningCredentials">
- <ref bean="openidvci.DefaultESSigningCredential" />
- <ref bean="openidvci.PreviousESSigningCredential" />
+ <ref bean="openidvci.OPESSigningCredential" />
</util:list>
```
-The first key that fits the algorithm signs, the others are there only to be published. This
-is a key rollover from the key of the OP to the own key. [Step 6](#step-6-rolling-the-signing-key)
-tells why the old key stays.
-
Import the file into *conf/global.xml*. Normally it would go to *conf/credentials.xml*, but the
Entity Configuration is published from the root context and it does not see beans of
*conf/credentials.xml*:
@@ -1249,22 +1285,6 @@ Entity Configuration is published from the root context and it does not see bean
<import resource="openid-vci-credentials.xml"/>
```
-The url credential names its key through the keyset of the OP, and the new key is not in that
-keyset. Publish it in *conf/oidc-credentials.xml*. The list replaces what is published, so
-the keys of the OP are listed too. If that file has an `alias` named
-`shibboleth.oidc.SigningCredentialsToPublish`, remove it:
-
-```xml
-<util:list id="shibboleth.oidc.SigningCredentialsToPublish">
- <ref bean="shibboleth.oidc.DefaultRSSigningCredential" />
- <ref bean="shibboleth.oidc.DefaultESSigningCredential" />
- <ref bean="openidvci.DefaultESSigningCredential" />
-</util:list>
-```
-
-Publish the key before you start signing with it. A verifier that fetched the keyset earlier
-may have the old one in cache.
-
#### Federation
The Entity Identifier and `credential_issuer` of the Credential Issuer metadata have to be the
@@ -1291,13 +1311,38 @@ Once the import is there every credential states the Entity Identifier, unless i
`"oidfed": false`. We want only the url credential in the federation, so the three others get:
```json
+{
+ "credential_configurations_supported": {
+ "GeantIncubatorDiploma_SDJWT": {
+ ...
"_issuance_configuration": {
"oidfed": false
- },
+ }
+ },
+ "GeantIncubatorDiploma_W3C": {
+ ...
+ "_issuance_configuration": {
+ "oidfed": false
+ }
+ },
+ "GeantIncubatorDiploma_DIDWEB": {
+ ...
+ "_issuance_configuration": {
+ "issuer": "did:web",
+ "oidfed": false
+ }
+ },
+ "GeantIncubatorDiploma_URL": {
+ ...
+ "_issuance_configuration": {
+ "issuer": "url"
+ }
+ }
+ }
+}
```
-`GeantIncubatorDiploma_DIDWEB` has `"issuer": "did:web"` there already, the two members go
-side by side. The url credential then carries:
+The url credential then carries:
```json
{
@@ -1360,8 +1405,7 @@ put **first** in the list. The key needs a name, `p:keyNames`, for the did:web d
<util:list id="openidvci.SigningCredentials">
<ref bean="openidvci.X509ESSigningCredential" />
- <ref bean="openidvci.DefaultESSigningCredential" />
- <ref bean="openidvci.PreviousESSigningCredential" />
+ <ref bean="openidvci.OPESSigningCredential" />
</util:list>
<util:list id="openidvci.issuerMetadata.SigningCredentials">
@@ -1372,7 +1416,7 @@ put **first** in the list. The key needs a name, `p:keyNames`, for the did:web d
The chain is emitted whenever the issuer of the signed thing is an https url, there is no
switch for it. That means the url credential of Steps 3 and 4 now carries `x5c` too, and no
`kid`. A verifier of it moves from `/.well-known/jwt-vc-issuer` to the chain. The did:jwk and
-did:web credentials do not carry a chain, their identifier resolves the key. This is again a key
+did:web credentials do not carry a chain, their identifier resolves the key. This is a key
rollover, see [Step 6](#step-6-rolling-the-signing-key).
#### The credential
@@ -1384,6 +1428,11 @@ attestation required:
<summary>Example snippet of metadata/verifiable-credentials.json</summary>
```json
+{
+ "credential_configurations_supported": {
+ "GeantIncubatorDiploma_SDJWT": { "...": "..." },
+ "GeantIncubatorDiploma_W3C": { "...": "..." },
+ ...
"GeantIncubatorDiploma_HAIP": {
"format": "dc+sd-jwt",
"vct": "GeantIncubatorDiploma_HAIP",
@@ -1416,6 +1465,8 @@ attestation required:
]
}
}
+ }
+}
```
</details>
@@ -1476,6 +1527,8 @@ being the alias of your test plan:
<summary>Example snippet of metadata/oidc-client.json</summary>
```json
+[
+ ...
{
"client_id": "conformance_client_1",
"client_name": "OpenID Conformance Suite",
@@ -1496,6 +1549,7 @@ being the alias of your test plan:
"response_types": ["code"],
"grant_types": ["authorization_code", "urn:ietf:params:oauth:grant-type:pre-authorized_code"]
}
+]
```
</details>
@@ -1507,6 +1561,8 @@ response and both token and PAR endpoints take the Wallet Attestation:
<summary>Example snippet of conf/relying-party.xml</summary>
```xml
+<util:list id="shibboleth.RelyingPartyOverrides">
+ ...
<bean parent="RelyingPartyByName"
c:relyingPartyIds="#{{'conformance_client_1','conformance_client_2'}}">
<property name="profileConfigurations">
@@ -1523,6 +1579,7 @@ response and both token and PAR endpoints take the Wallet Attestation:
</list>
</property>
</bean>
+</util:list>
```
</details>
@@ -1537,6 +1594,8 @@ Advertise the rest in *static/oauth-authorization-server.json*. `GeantIncubatorD
`scopes_supported` as before and these are added:
```json
+{
+ ...
"token_endpoint_auth_methods_supported":[
"none",
"client_secret_basic",
@@ -1547,6 +1606,8 @@ Advertise the rest in *static/oauth-authorization-server.json*. `GeantIncubatorD
"client_attestation_signing_alg_values_supported":[ "ES256" ],
"client_attestation_pop_signing_alg_values_supported":[ "ES256" ],
"authorization_response_iss_parameter_supported":true,
+ ...
+}
```
#### Suite configuration
@@ -1577,7 +1638,7 @@ above.
### Step 6: Rolling the signing key
-Steps 4 and 5 changed the signing key. What a key change means depends on the issuer
+Step 5 changed the signing key. What a key change means depends on the issuer
identifier of the credential. The configuration is the same for all:
1. The new key goes **first** in **openidvci.SigningCredentials**. The first key that fits the
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list