[java-idp-plugin-vci] branch dev/READMEDOCS updated: Apply change to rest of sections

Codeberg noreply at shibboleth.net
Fri Oct 2 05:23:17 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch dev/READMEDOCS
in repository java-idp-plugin-vci.

View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-vci/commit/a7de844d3a5a531c353cda6f4bd5bbbfc70c7afb

The following commit(s) were added to refs/heads/dev/READMEDOCS by this push:
     new a7de844  Apply change to rest of sections
a7de844 is described below

commit a7de844d3a5a531c353cda6f4bd5bbbfc70c7afb
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Fri Oct 2 08:23:04 2026 +0300

    Apply change to rest of sections
---
 README.md                                          | 756 ++++++++++-----------
 docs/example/step-1/conf/relying-party.xml         |   4 -
 docs/example/step-2/conf/relying-party.xml         |   4 -
 docs/example/step-3/conf/attribute-filter.xml      |  15 +
 .../example/step-3/conf/openid-vci-credentials.xml |  18 +
 .../{step-2 => step-3}/conf/relying-party.xml      |   6 +-
 docs/example/step-3/etc/jetty-rewrite-rules.xml    |  68 ++
 docs/example/step-3/metadata/oidc-client.json      |  29 +
 .../step-3/metadata/verifiable-credentials.json    | 123 ++++
 .../step-3/static/oauth-authorization-server.json  |  39 ++
 .../credentials/GeantIncubatorDiploma_W3C.json     |  10 +
 docs/example/step-4/conf/attribute-filter.xml      |  15 +
 .../example/step-4/conf/openid-vci-credentials.xml |  18 +
 .../{step-2 => step-4}/conf/relying-party.xml      |   8 +-
 docs/example/step-4/etc/jetty-rewrite-rules.xml    |  77 +++
 docs/example/step-4/metadata/oidc-client.json      |  29 +
 .../step-4/metadata/verifiable-credentials.json    | 130 ++++
 .../step-4/static/oauth-authorization-server.json  |  39 ++
 .../credentials/GeantIncubatorDiploma_W3C.json     |  10 +
 docs/example/step-5/conf/attribute-filter.xml      |  26 +
 .../example/step-5/conf/openid-vci-credentials.xml |  46 ++
 .../{step-2 => step-5}/conf/relying-party.xml      |  26 +-
 docs/example/step-5/etc/jetty-rewrite-rules.xml    |  77 +++
 docs/example/step-5/metadata/oidc-client.json      |  39 ++
 .../step-5/metadata/verifiable-credentials.json    | 197 ++++++
 .../step-5/static/oauth-authorization-server.json  |  49 ++
 .../credentials/GeantIncubatorDiploma_W3C.json     |  10 +
 27 files changed, 1457 insertions(+), 411 deletions(-)

diff --git a/README.md b/README.md
index d61ac64..7f9f051 100644
--- a/README.md
+++ b/README.md
@@ -353,6 +353,8 @@ of the specification, per credential format. Below only the members that need ex
 }
 ```
 
+Full file: [metadata/verifiable-credentials.json](docs/example/step-1/metadata/verifiable-credentials.json)
+
 </details>
 
 The configuration id, `GeantIncubatorDiploma_SDJWT` here, is used everywhere. A wallet uses it
@@ -383,6 +385,8 @@ in it:
 }
 ```
 
+Full file: [webapps/root/credentials/GeantIncubatorDiploma_W3C.json](docs/example/step-1/webapps/root/credentials/GeantIncubatorDiploma_W3C.json)
+
 </details>
 
 You publish it at the url that is in `@context`, see [Metadata endpoints](#metadata-endpoints)
@@ -509,6 +513,8 @@ endpoints go to the anonymous relying party. Both flows below need it:
 ...
 ```
 
+Full file: [conf/relying-party.xml](docs/example/step-1/conf/relying-party.xml)
+
 </details>
 
 You do not need to write your host name into the templates of *static/*. They use `$issuer`,
@@ -528,6 +534,8 @@ One thing you need to add is the credential scopes in `scopes_supported` of
 }
 ```
 
+Full file: [static/oauth-authorization-server.json](docs/example/step-1/static/oauth-authorization-server.json)
+
 The `/.well-known/` locations are not IdP paths, you wire them in Jetty. For this step you need
 these rules in *etc/jetty-rewrite-rules.xml*. The later steps add one rule each and the whole
 file is in [Discovery documents](#discovery-documents).
@@ -573,6 +581,8 @@ file is in [Discovery documents](#discovery-documents).
 </Configure>
 ```
 
+Full file: [etc/jetty-rewrite-rules.xml](docs/example/step-1/etc/jetty-rewrite-rules.xml)
+
 </details>
 
 Wallets running in a browser need also the `Access-Control-Allow-Origin` rule of the whole file in
@@ -609,6 +619,8 @@ different identity. You register both:
 ]
 ```
 
+Full file: [metadata/oidc-client.json](docs/example/step-1/metadata/oidc-client.json)
+
 </details>
 
 The `/wallet` suffix is fixed. A wallet that redeems a pre-authorized
@@ -649,6 +661,8 @@ wallet that redeems the code:
 ...
 ```
 
+Full file: [conf/relying-party.xml](docs/example/step-1/conf/relying-party.xml)
+
 </details>
 
 The offer request is a `POST` of `application/json` to
@@ -761,6 +775,8 @@ in the same *metadata/oidc-client.json* as the clients above:
 ]
 ```
 
+Full file: [metadata/oidc-client.json](docs/example/step-1/metadata/oidc-client.json)
+
 </details>
 
 Note the `scope` value. Every configuration id you want to be requestable by scope needs to be
@@ -802,6 +818,8 @@ authorization request:
 ...
 ```
 
+Full file: [conf/relying-party.xml](docs/example/step-1/conf/relying-party.xml)
+
 </details>
 
 The *value* of the attribute is the claims as an array of `{"path": [...], "value": ...}`, the
@@ -865,6 +883,8 @@ And you release it to the wallet in *conf/attribute-filter.xml*. This flow reads
 </AttributeFilterPolicy>
 ```
 
+Full file: [conf/attribute-filter.xml](docs/example/step-1/conf/attribute-filter.xml)
+
 </details>
 
 The token endpoint of the code flow keeps only the credentials the wallet was authorized for: a
@@ -1306,65 +1326,133 @@ What is new:
 - the credential header `kid` is the plain name of the key, as in the keyset of the OP
 - the Status List url of the credential ends with `~url`
 
-The credential in *metadata/verifiable-credentials.json* is like the one of Step 2, with id
-`GeantIncubatorDiploma_URL` and:
+The changes per file, each with a link to the whole file after this step:
 
-```json
-{
-  "credential_configurations_supported": {
-    ...
-    "GeantIncubatorDiploma_URL": {
-      "format": "dc+sd-jwt",
-      "vct": "GeantIncubatorDiploma_URL",
-      "scope": "GeantIncubatorDiploma_URL",
-      ...
-      "_issuance_configuration": {
-        "issuer": "url"
-      },
-      "credential_metadata": { "...": "..." }
-    }
-  }
-}
+<details>
+<summary>metadata/verifiable-credentials.json</summary>
+
+```diff
+ ...
+         ]
+       }
++    },
++    "GeantIncubatorDiploma_URL": {
++      "format": "dc+sd-jwt",
++      "vct": "GeantIncubatorDiploma_URL",
++      "scope": "GeantIncubatorDiploma_URL",
++      "cryptographic_binding_methods_supported": ["did:jwk"],
++      "proof_types_supported": {
++        "jwt": {
++          "proof_signing_alg_values_supported": ["ES256"]
++        }
++      },
++      "_issuance_configuration": {
++        "issuer": "url"
++      },
++      "credential_metadata": {
++        "display": [
++          { "name": "Incubator Diploma, url", "locale": "en" }
++        ],
++        "claims": [
++          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
++          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
++          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
++          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
++          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
++          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
++        ]
++      }
+     }
+   }
 ```
 
+Full file: [metadata/verifiable-credentials.json](docs/example/step-3/metadata/verifiable-credentials.json)
+
+</details>
+
 `url` stands for the value of `idp.oidc.issuer`. You may also write the url itself.
 
-Add **OAuth.JWTVCIssuer** to the anonymous relying party:
+<details>
+<summary>conf/relying-party.xml</summary>
 
-```xml
-<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>
+```diff
+ ...
+                 <!-- A verifier resolves the did:web identifier from this -->
+                 <ref bean="DID.Document" />
++                <!-- A verifier finds the key of a url issuer through this -->
++                <ref bean="OAuth.JWTVCIssuer" />
+             </list>
+         </property>
 ```
 
-and wire it in *etc/jetty-rewrite-rules.xml*:
+Full file: [conf/relying-party.xml](docs/example/step-3/conf/relying-party.xml)
 
-```xml
-<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
-  ...
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/.well-known/jwt-vc-issuer</Set>
-        <Set name="replacement">/idp/profile/oauth/jwt-vc-issuer</Set>
-      </New>
-    </Arg>
-  </Call>
-</Configure>
+</details>
+
+<details>
+<summary>etc/jetty-rewrite-rules.xml</summary>
+
+```diff
+ ...
+     </Arg>
+   </Call>
++  <!-- JWT VC issuer metadata -->
++  <Call name="addRule">
++    <Arg>
++      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
++        <Set name="pattern">/.well-known/jwt-vc-issuer</Set>
++        <Set name="replacement">/idp/profile/oauth/jwt-vc-issuer</Set>
++      </New>
++    </Arg>
++  </Call>
+   <!-- Wallets running in a browser need this -->
+   <Call name="addRule">
+```
+
+Full file: [etc/jetty-rewrite-rules.xml](docs/example/step-3/etc/jetty-rewrite-rules.xml)
+
+</details>
+
+<details>
+<summary>metadata/oidc-client.json</summary>
+
+```diff
+ ...
+     "client_name": "Paradym Wallet",
+     "redirect_uris": ["https://paradym.id/invitation/redirect"],
+-    "scope": "openid GeantIncubatorDiploma_SDJWT GeantIncubatorDiploma_W3C GeantIncubatorDiploma_DIDWEB",
++    "scope": "openid GeantIncubatorDiploma_SDJWT GeantIncubatorDiploma_W3C GeantIncubatorDiploma_DIDWEB GeantIncubatorDiploma_URL",
+     "audience": [
+       "credentials",
 ```
 
+Full file: [metadata/oidc-client.json](docs/example/step-3/metadata/oidc-client.json)
+
+</details>
+
+<details>
+<summary>static/oauth-authorization-server.json</summary>
+
+```diff
+ ...
+       "GeantIncubatorDiploma_SDJWT",
+       "GeantIncubatorDiploma_W3C",
+-      "GeantIncubatorDiploma_DIDWEB"
++      "GeantIncubatorDiploma_DIDWEB",
++      "GeantIncubatorDiploma_URL"
+    ],
+    "authorization_details_types_supported":[
+```
+
+Full file: [static/oauth-authorization-server.json](docs/example/step-3/static/oauth-authorization-server.json)
+
+</details>
+
 *static/jwt-vc-issuer.json* as it comes with the plugin is fine. Its `jwks_uri` is the keyset of
 the OP, served by `OIDC.Keyset` that is already in the anonymous relying party. The keyset has
 the keys of the OP, which sign the credentials until Step 5.
 
-Scope, scopes supported, attribute encoder and offer as in Step 2, with
-`GeantIncubatorDiploma_URL`.
+Attribute encoder and offer as in Step 2, with `GeantIncubatorDiploma_URL`.
 
 ### Step 4: Make the url credential an OpenID Federation credential
 
@@ -1400,45 +1488,88 @@ Import the federation file into *conf/global.xml*, after the import of Step 2:
 <import resource="openid-vci-oidfed.xml"/>
 ```
 
-Add `OIDFED.Configuration` of the federation plugin to the anonymous relying party and wire
-`/.well-known/openid-federation` to `/idp/profile/oidfed/entity-configuration` in Jetty, the same
-way as the rules above.
-
 Once the import is there every credential states the Entity Identifier, unless it says
-`"oidfed": false`. We want only the url credential in the federation, so the three others get:
+`"oidfed": false`. We want only the url credential in the federation, so the three others get
+`"oidfed": false`:
 
-```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"
-      }
-    }
-  }
-}
+<details>
+<summary>metadata/verifiable-credentials.json</summary>
+
+```diff
+ ...
+       "vct": "GeantIncubatorDiploma_SDJWT",
+       "scope": "GeantIncubatorDiploma_SDJWT",
++      "_issuance_configuration": {
++        "oidfed": false
++      },
+       "cryptographic_binding_methods_supported": ["did:jwk"],
+       "proof_types_supported": {
+ ...
+       "format": "vc+sd-jwt",
+       "scope": "GeantIncubatorDiploma_W3C",
++      "_issuance_configuration": {
++        "oidfed": false
++      },
+       "cryptographic_binding_methods_supported": ["did:jwk"],
+       "proof_types_supported": {
+ ...
+       },
+       "_issuance_configuration": {
+-        "issuer": "did:web"
++        "issuer": "did:web",
++        "oidfed": false
+       },
+       "credential_metadata": {
+```
+
+Full file: [metadata/verifiable-credentials.json](docs/example/step-4/metadata/verifiable-credentials.json)
+
+</details>
+
+`OIDFED.Configuration` of the federation plugin goes to the anonymous relying party, and
+`/.well-known/openid-federation` is wired in Jetty:
+
+<details>
+<summary>conf/relying-party.xml</summary>
+
+```diff
+ ...
+                 <!-- A verifier finds the key of a url issuer through this -->
+                 <ref bean="OAuth.JWTVCIssuer" />
++                <!-- Of the federation plugin. Serves the Entity Configuration -->
++                <ref bean="OIDFED.Configuration" />
+             </list>
+         </property>
 ```
 
+Full file: [conf/relying-party.xml](docs/example/step-4/conf/relying-party.xml)
+
+</details>
+
+<details>
+<summary>etc/jetty-rewrite-rules.xml</summary>
+
+```diff
+ ...
+     </Arg>
+   </Call>
++  <!-- Entity Configuration, of the federation plugin -->
++  <Call name="addRule">
++    <Arg>
++      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
++        <Set name="pattern">/.well-known/openid-federation</Set>
++        <Set name="replacement">/idp/profile/oidfed/entity-configuration</Set>
++      </New>
++    </Arg>
++  </Call>
+   <!-- Wallets running in a browser need this -->
+   <Call name="addRule">
+```
+
+Full file: [etc/jetty-rewrite-rules.xml](docs/example/step-4/etc/jetty-rewrite-rules.xml)
+
+</details>
+
 The url credential then carries:
 
 ```json
@@ -1496,39 +1627,51 @@ In *conf/openid-vci-credentials.xml* the signing key is put **first** in the lis
 credential of Step 2 is still issued, so the new keys need a name, `p:keyNames`, for the did:web
 document:
 
-```xml
-<bean id="openidvci.X509ESSigningCredential" parent="shibboleth.BasicX509CredentialFactoryBean"
-    p:privateKey="%{idp.home}/credentials/vci-signing.key" p:keyNames="signingvci-x509">
-    <property name="certificates">
-        <list>
-            <value>%{idp.home}/credentials/vci-signing.crt</value>
-        </list>
-    </property>
-</bean>
-
-<bean id="openidvci.X509StatusListSigningCredential" parent="shibboleth.BasicX509CredentialFactoryBean"
-    p:privateKey="%{idp.home}/credentials/vci-status-list.key" p:keyNames="statuslist-x509">
-    <property name="certificates">
-        <list>
-            <value>%{idp.home}/credentials/vci-status-list.crt</value>
-        </list>
-    </property>
-</bean>
-
-<util:list id="openidvci.SigningCredentials">
-    <ref bean="openidvci.X509ESSigningCredential" />
-    <ref bean="openidvci.OPESSigningCredential" />
-</util:list>
+<details>
+<summary>conf/openid-vci-credentials.xml</summary>
 
-<util:list id="openidvci.status-list.SigningCredentials">
-    <ref bean="openidvci.X509StatusListSigningCredential" />
-    <ref bean="openidvci.OPESSigningCredential" />
-</util:list>
+```diff
+ ...
+         p:resource="%{idp.signing.oidc.es.key}" />
+ 
++    <bean id="openidvci.X509ESSigningCredential" parent="shibboleth.BasicX509CredentialFactoryBean"
++        p:privateKey="%{idp.home}/credentials/vci-signing.key" p:keyNames="signingvci-x509">
++        <property name="certificates">
++            <list>
++                <value>%{idp.home}/credentials/vci-signing.crt</value>
++            </list>
++        </property>
++    </bean>
++
++    <bean id="openidvci.X509StatusListSigningCredential" parent="shibboleth.BasicX509CredentialFactoryBean"
++        p:privateKey="%{idp.home}/credentials/vci-status-list.key" p:keyNames="statuslist-x509">
++        <property name="certificates">
++            <list>
++                <value>%{idp.home}/credentials/vci-status-list.crt</value>
++            </list>
++        </property>
++    </bean>
++
+     <util:list id="openidvci.SigningCredentials">
++        <ref bean="openidvci.X509ESSigningCredential" />
+         <ref bean="openidvci.OPESSigningCredential" />
+     </util:list>
+ 
++    <util:list id="openidvci.status-list.SigningCredentials">
++        <ref bean="openidvci.X509StatusListSigningCredential" />
++        <ref bean="openidvci.OPESSigningCredential" />
++    </util:list>
++
++    <util:list id="openidvci.issuerMetadata.SigningCredentials">
++        <ref bean="openidvci.X509ESSigningCredential" />
++    </util:list>
++
+ </beans>
+```
+
+Full file: [conf/openid-vci-credentials.xml](docs/example/step-5/conf/openid-vci-credentials.xml)
 
-<util:list id="openidvci.issuerMetadata.SigningCredentials">
-    <ref bean="openidvci.X509ESSigningCredential" />
-</util:list>
-```
+</details>
 
 The credentials of Steps 1 to 4 were signed with the key of the OP, so it stays in both lists,
 after the new keys, see [Step 6](#step-6-rolling-the-signing-key). In the Status List list it signs
@@ -1590,6 +1733,8 @@ attestation required:
 }
 ```
 
+Full file: [metadata/verifiable-credentials.json](docs/example/step-5/metadata/verifiable-credentials.json)
+
 </details>
 
 For the values of `key_attestations_required`, see
@@ -1652,6 +1797,8 @@ Issuer identifier is not used.
 }
 ```
 
+Full file: [metadata/verifiable-credentials.json](docs/example/step-5/metadata/verifiable-credentials.json)
+
 </details>
 
 What is different from an SD-JWT VC configuration:
@@ -1709,6 +1856,31 @@ The paths differ from the SD-JWT VC credentials, so the content is an attribute
 Add `GeantIncubatorDiplomaMdoc` to `idp.oidc.encodedAttributes` in *conf/oidc.properties* and
 release it to the HAIP wallet in *conf/attribute-filter.xml*.
 
+<details>
+<summary>conf/attribute-filter.xml</summary>
+
+```diff
+ ...
+     </AttributeFilterPolicy>
+ 
++    <AttributeFilterPolicy id="GeantIncubatorDiplomaToHAIPWallets">
++        <PolicyRequirementRule xsi:type="Requester"
++            value="haip-wallet" />
++        <AttributeRule attributeID="GeantIncubatorDiploma">
++            <PermitValueRule xsi:type="ANY" />
++        </AttributeRule>
++        <AttributeRule attributeID="GeantIncubatorDiplomaMdoc">
++            <PermitValueRule xsi:type="ANY" />
++        </AttributeRule>
++    </AttributeFilterPolicy>
++
+ </AttributeFilterPolicyGroup>
+```
+
+Full file: [conf/attribute-filter.xml](docs/example/step-5/conf/attribute-filter.xml)
+
+</details>
+
 The Status List needs nothing more for the mdoc, it is also served as CWT, see
 [OAuth.StatusList](#oauth-statuslist).
 
@@ -1761,24 +1933,28 @@ idp.oauth2.authn.flows = OpenIDVCIClient
 The client id is the `sub` of the Wallet Attestation of the wallet. In *metadata/oidc-client.json*:
 
 <details>
-<summary>Example snippet of metadata/oidc-client.json</summary>
+<summary>metadata/oidc-client.json</summary>
 
-```json
-[
-  ...
-  {
-    "client_id": "haip-wallet",
-    "client_name": "HAIP Wallet",
-    "redirect_uris": ["https://wallet.example.org/callback"],
-    "scope": "openid GeantIncubatorDiploma_HAIP GeantIncubatorDiploma_MDOC",
-    "audience": "credentials",
-    "token_endpoint_auth_method": "attest_jwt_client_auth",
-    "response_types": ["code"],
-    "grant_types": ["authorization_code"]
-  }
-]
+```diff
+ ...
+       "urn:ietf:params:oauth:grant-type:pre-authorized_code"
+     ]
++  },
++  {
++    "client_id": "haip-wallet",
++    "client_name": "HAIP Wallet",
++    "redirect_uris": ["https://wallet.example.org/callback"],
++    "scope": "openid GeantIncubatorDiploma_HAIP GeantIncubatorDiploma_MDOC",
++    "audience": "credentials",
++    "token_endpoint_auth_method": "attest_jwt_client_auth",
++    "response_types": ["code"],
++    "grant_types": ["authorization_code"]
+   }
+ ]
 ```
 
+Full file: [metadata/oidc-client.json](docs/example/step-5/metadata/oidc-client.json)
+
 </details>
 
 In *conf/relying-party.xml* PKCE and PAR are required, `iss` is returned in the authorization
@@ -1787,30 +1963,35 @@ response, the authorization code lives one minute, see
 and both token and PAR endpoints take the Wallet Attestation:
 
 <details>
-<summary>Example snippet of conf/relying-party.xml</summary>
+<summary>conf/relying-party.xml</summary>
 
-```xml
-<util:list id="shibboleth.RelyingPartyOverrides">
-    ...
-        <bean parent="RelyingPartyByName"
-              c:relyingPartyIds="#{{'haip-wallet'}}">
-          <property name="profileConfigurations">
-              <list>
-                  <bean parent="OIDC.SSO"
-                        p:authorizationCodeClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
-                        p:forcePKCE="true" p:requirePushedAuthorizationRequest="true"
-                        p:includeIssuerInResponse="true" p:authorizeCodeLifetime="PT1M" />
-                  <bean parent="OpenID.VCI.Token"
-                        p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
-                        p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}" />
-                  <bean parent="OpenID.VCI.Credentials" />
-                  <bean parent="OAUTH2.PAR" p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}"
-                        p:requestUriClaimsSetManipulationStrategy-ref="openidvci.PushedAuthorizationDPoPJktManipulationStrategy" />
-              </list>
-          </property>
-        </bean>
-</util:list>
-```
+```diff
+ ...
+         </bean>
+ 
++        <bean parent="RelyingPartyByName"
++              c:relyingPartyIds="#{{'haip-wallet'}}">
++          <property name="profileConfigurations">
++              <list>
++                  <bean parent="OIDC.SSO"
++                        p:authorizationCodeClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
++                        p:forcePKCE="true" p:requirePushedAuthorizationRequest="true"
++                        p:includeIssuerInResponse="true" p:authorizeCodeLifetime="PT1M" />
++                  <bean parent="OpenID.VCI.Token"
++                        p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
++                        p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}" />
++                  <bean parent="OpenID.VCI.Credentials" />
++                  <bean parent="OAUTH2.PAR" p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}"
++                        p:requestUriClaimsSetManipulationStrategy-ref="openidvci.PushedAuthorizationDPoPJktManipulationStrategy" />
++              </list>
++          </property>
++        </bean>
++
+     </util:list>
+ 
+```
+
+Full file: [conf/relying-party.xml](docs/example/step-5/conf/relying-party.xml)
 
 </details>
 
@@ -1819,65 +2000,43 @@ DPoP settings are left to their defaults, so a DPoP nonce is required.
 `openidvci.PushedAuthorizationDPoPJktManipulationStrategy` on **OAUTH2.PAR** is recommended with
 DPoP, see [RFC 9449 10.1](https://www.rfc-editor.org/rfc/rfc9449#section-10.1).
 
-The whole *static/oauth-authorization-server.json* after this step. `token_endpoint_auth_methods_supported`
-lists the methods your `tokenEndpointAuthMethods` allow on the token and PAR endpoints, here `none`
-for Paradym and `attest_jwt_client_auth` for the HAIP wallet:
+`token_endpoint_auth_methods_supported` of *static/oauth-authorization-server.json* lists the
+methods your `tokenEndpointAuthMethods` allow on the token and PAR endpoints, here `none` for
+Paradym and `attest_jwt_client_auth` for the HAIP wallet:
 
 <details>
-<summary>Example contents of static/oauth-authorization-server.json</summary>
+<summary>static/oauth-authorization-server.json</summary>
 
-```json
-{
-   "issuer":"$issuer",
-   "authorization_endpoint":"$baseUrl/idp/profile/oidc/authorize",
-   "pushed_authorization_request_endpoint":"$baseUrl/idp/profile/oauth2/pushed-authorization",
-   "require_pushed_authorization_requests":true,
-   "token_endpoint":"$baseUrl/idp/profile/openid/vci/token",
-   "jwks_uri":"$baseUrl/idp/profile/oidc/keyset",
-   "token_endpoint_auth_methods_supported":[
-      "none",
-      "attest_jwt_client_auth"
-   ],
-   "client_attestation_signing_alg_values_supported":[
-      "ES256"
-   ],
-   "client_attestation_pop_signing_alg_values_supported":[
-      "ES256"
-   ],
-   "authorization_response_iss_parameter_supported":true,
-   "response_types_supported":[
-      "code"
-   ],
-   "grant_types_supported":[
-      "authorization_code",
-      "urn:ietf:params:oauth:grant-type:pre-authorized_code"
-   ],
-   "code_challenge_methods_supported":[
-      "S256"
-   ],
-   "dpop_signing_alg_values_supported":[
-      "ES256",
-      "ES384",
-      "ES512",
-      "PS256",
-      "PS384",
-      "PS512"
-   ],
-   "scopes_supported":[
-      "openid",
-      "GeantIncubatorDiploma_SDJWT",
-      "GeantIncubatorDiploma_W3C",
-      "GeantIncubatorDiploma_DIDWEB",
-      "GeantIncubatorDiploma_URL",
-      "GeantIncubatorDiploma_HAIP",
-      "GeantIncubatorDiploma_MDOC"
-   ],
-   "authorization_details_types_supported":[
-      "openid_credential"
-   ]
-}
+```diff
+ ...
+    "jwks_uri":"$baseUrl/idp/profile/oidc/keyset",
+    "token_endpoint_auth_methods_supported":[
+-      "none"
++      "none",
++      "attest_jwt_client_auth"
+    ],
++   "client_attestation_signing_alg_values_supported":[
++      "ES256"
++   ],
++   "client_attestation_pop_signing_alg_values_supported":[
++      "ES256"
++   ],
++   "authorization_response_iss_parameter_supported":true,
+    "response_types_supported":[
+       "code"
+ ...
+       "GeantIncubatorDiploma_W3C",
+       "GeantIncubatorDiploma_DIDWEB",
+-      "GeantIncubatorDiploma_URL"
++      "GeantIncubatorDiploma_URL",
++      "GeantIncubatorDiploma_HAIP",
++      "GeantIncubatorDiploma_MDOC"
+    ],
+    "authorization_details_types_supported":[
 ```
 
+Full file: [static/oauth-authorization-server.json](docs/example/step-5/static/oauth-authorization-server.json)
+
 </details>
 
 ### Step 6: Rolling the signing key
@@ -1922,8 +2081,7 @@ them in that list too.
 | `GeantIncubatorDiploma_HAIP` | `https://issuer.example.org` | `x5c` | no | HAIP wallet |
 | `GeantIncubatorDiploma_MDOC` | none | `x5chain` | no | HAIP wallet |
 
-The whole *conf/relying-party.xml* is in [Relying party configuration](#relying-party-configuration)
-and the whole *etc/jetty-rewrite-rules.xml* in [Discovery documents](#discovery-documents).
+The files at the end of the story are in [docs/example/step-5](docs/example/step-5).
 
 ## Requesting a credential by configuration or by identifier
 
@@ -2554,196 +2712,12 @@ Add the credential configuration ids to `scopes_supported`. For Wallet Attestati
 
 </details>
 
-<details>
-<summary>Example contents of etc/jetty-rewrite-rules.xml</summary>
-
-```xml
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
-<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
-  <!-- Credential Issuer metadata comes from this plugin -->
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/.well-known/openid-credential-issuer</Set>
-        <Set name="replacement">/idp/profile/openid/vci/issuer-metadata</Set>
-      </New>
-    </Arg>
-  </Call>
-  <!-- OP metadata comes from the OP plugin -->
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/.well-known/openid-configuration</Set>
-        <Set name="replacement">/idp/profile/oidc/configuration</Set>
-      </New>
-    </Arg>
-  </Call>
-  <!-- These two come from this plugin as well -->
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/.well-known/jwt-vc-issuer</Set>
-        <Set name="replacement">/idp/profile/oauth/jwt-vc-issuer</Set>
-      </New>
-    </Arg>
-  </Call>
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/.well-known/oauth-authorization-server</Set>
-        <Set name="replacement">/idp/profile/oauth/authorization-server</Set>
-      </New>
-    </Arg>
-  </Call>
-  <!-- Needed only for did:web credentials -->
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/.well-known/did.json</Set>
-        <Set name="replacement">/idp/profile/did/document</Set>
-      </New>
-    </Arg>
-  </Call>
-  <!-- Needed only when the federation plugin publishes an Entity Configuration -->
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/.well-known/openid-federation</Set>
-        <Set name="replacement">/idp/profile/oidfed/entity-configuration</Set>
-      </New>
-    </Arg>
-  </Call>
-  <!-- The JSON-LD context of the vc+sd-jwt credential is a static file of Jetty -->
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
-        <Set name="pattern">/credentials/GeantIncubatorDiploma_W3C</Set>
-        <Set name="replacement">/credentials/GeantIncubatorDiploma_W3C.json</Set>
-      </New>
-    </Arg>
-  </Call>
-  <!-- Wallets running in a browser need this -->
-  <Call name="addRule">
-    <Arg>
-      <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
-        <Set name="pattern">/*</Set>
-        <Set name="headerName">Access-Control-Allow-Origin</Set>
-        <Set name="headerValue">*</Set>
-      </New>
-    </Arg>
-  </Call>
-</Configure>
-```
-
-</details>
+The whole *etc/jetty-rewrite-rules.xml* at the end of the story: [etc/jetty-rewrite-rules.xml](docs/example/step-5/etc/jetty-rewrite-rules.xml).
 
 ### Relying party configuration
 
 **File(s):** *conf/relying-party.xml*
 **Format:** Native Spring
 
-The file as it is at the end of [First installation, by example](#first-installation-by-example).
-
-<details>
-<summary>Example contents of conf/relying-party.xml</summary>
-
-```xml
-...
-    <bean id="shibboleth.UnverifiedRelyingParty" parent="RelyingParty">
-        <property name="profileConfigurations">
-            <list>
-                <ref bean="OIDC.Keyset" />
-                <ref bean="OIDC.Configuration" />
-                <ref bean="OAUTH2.TokenAudience" />
-                <!-- Anyone may read the Credential Issuer metadata -->
-                <ref bean="OpenID.VCI.IssuerMetadata" />
-                <!-- Anyone may read the keys that signed a credential -->
-                <ref bean="OAuth.JWTVCIssuer" />
-                <!-- Anyone may read the did:web document, needed for did:web credentials -->
-                <ref bean="DID.Document" />
-                <!-- Anyone may read the authorization server metadata -->
-                <ref bean="OAuth.AuthorizationServer" />
-                <!-- Anyone may ask for a nonce -->
-                <ref bean="OpenID.VCI.Nonce" />
-                <!-- Anyone may read a Status List -->
-                <ref bean="OAuth.StatusList" />
-                <!-- Anyone may read the Entity Configuration, of the federation plugin -->
-                <ref bean="OIDFED.Configuration" />
-            </list>
-        </property>
-    </bean>
-
-    <!-- This plugin does not need anything of shibboleth.DefaultRelyingParty -->
-
-    <util:list id="shibboleth.RelyingPartyOverrides">
-
-        <!-- The caller that creates Credential Offers and revokes what was issued -->
-        <bean parent="RelyingPartyByName" c:relyingPartyIds="offer-caller">
-          <property name="profileConfigurations">
-              <list>
-                  <bean parent="OpenID.VCI.CredentialOffer"
-                        p:tokenEndpointAuthMethods="#{{'client_secret_basic'}}" />
-                  <bean parent="OAuth.StatusList.Revoke"
-                        p:tokenEndpointAuthMethods="#{{'client_secret_basic'}}" />
-                  <bean parent="OAuth.StatusList.Assignments"
-                        p:tokenEndpointAuthMethods="#{{'client_secret_basic'}}" />
-              </list>
-          </property>
-        </bean>
-
-        <!-- Wallets that redeem a pre-authorized code created by offer-caller -->
-        <bean parent="RelyingPartyByName" c:relyingPartyIds="offer-caller/wallet">
-          <property name="profileConfigurations">
-              <list>
-                  <bean parent="OpenID.VCI.Token"
-                        p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
-                        p:tokenEndpointAuthMethods="#{{'none'}}" />
-                  <bean parent="OpenID.VCI.Credentials" />
-              </list>
-          </property>
-        </bean>
-
-        <!-- A registered wallet running the authorization code flow -->
-        <bean parent="RelyingPartyByName"
-              c:relyingPartyIds="#{{'id.animo.paradym'}}">
-          <property name="profileConfigurations">
-              <list>
-                  <bean parent="OIDC.SSO"
-                        p:authorizationCodeClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
-                        p:forcePKCE="true"
-                        p:requirePushedAuthorizationRequest="true" />
-                  <bean parent="OpenID.VCI.Token"
-                        p:tokenEndpointAuthMethods="#{{'none'}}"
-                        p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy" />
-                  <bean parent="OpenID.VCI.Credentials" />
-                  <bean parent="OAUTH2.PAR" p:tokenEndpointAuthMethods="#{{'none'}}"
-                        p:requestUriClaimsSetManipulationStrategy-ref="openidvci.PushedAuthorizationDPoPJktManipulationStrategy" />
-              </list>
-          </property>
-        </bean>
-
-        <!-- HAIP wallets, authenticating with a Wallet Attestation -->
-        <bean parent="RelyingPartyByName"
-              c:relyingPartyIds="#{{'haip-wallet'}}">
-          <property name="profileConfigurations">
-              <list>
-                  <bean parent="OIDC.SSO"
-                        p:authorizationCodeClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
-                        p:forcePKCE="true" p:requirePushedAuthorizationRequest="true"
-                        p:includeIssuerInResponse="true" p:authorizeCodeLifetime="PT1M" />
-                  <bean parent="OpenID.VCI.Token"
-                        p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
-                        p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}" />
-                  <bean parent="OpenID.VCI.Credentials" />
-                  <bean parent="OAUTH2.PAR" p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}"
-                        p:requestUriClaimsSetManipulationStrategy-ref="openidvci.PushedAuthorizationDPoPJktManipulationStrategy" />
-              </list>
-          </property>
-        </bean>
-
-    </util:list>
-...
-```
-
-</details>
+The file as it is at the end of [First installation, by example](#first-installation-by-example):
+[conf/relying-party.xml](docs/example/step-5/conf/relying-party.xml).
diff --git a/docs/example/step-1/conf/relying-party.xml b/docs/example/step-1/conf/relying-party.xml
index 87e6a74..017cf48 100644
--- a/docs/example/step-1/conf/relying-party.xml
+++ b/docs/example/step-1/conf/relying-party.xml
@@ -35,10 +35,6 @@
     <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
         <property name="profileConfigurations">
             <list>
-                <ref bean="SAML2.SSO" />
-                <ref bean="SAML2.ECP" />
-                <ref bean="SAML2.Logout" />
-                <ref bean="SAML2.ArtifactResolution" />
             </list>
         </property>
     </bean>
diff --git a/docs/example/step-2/conf/relying-party.xml b/docs/example/step-2/conf/relying-party.xml
index c042fdb..df0e9ac 100644
--- a/docs/example/step-2/conf/relying-party.xml
+++ b/docs/example/step-2/conf/relying-party.xml
@@ -37,10 +37,6 @@
     <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
         <property name="profileConfigurations">
             <list>
-                <ref bean="SAML2.SSO" />
-                <ref bean="SAML2.ECP" />
-                <ref bean="SAML2.Logout" />
-                <ref bean="SAML2.ArtifactResolution" />
             </list>
         </property>
     </bean>
diff --git a/docs/example/step-3/conf/attribute-filter.xml b/docs/example/step-3/conf/attribute-filter.xml
new file mode 100644
index 0000000..b10fb12
--- /dev/null
+++ b/docs/example/step-3/conf/attribute-filter.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
+        xmlns="urn:mace:shibboleth:2.0:afp"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd">
+
+    <AttributeFilterPolicy id="GeantIncubatorDiplomaToWallets">
+        <PolicyRequirementRule xsi:type="Requester"
+            value="id.animo.paradym" />
+        <AttributeRule attributeID="GeantIncubatorDiploma">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+    </AttributeFilterPolicy>
+
+</AttributeFilterPolicyGroup>
diff --git a/docs/example/step-3/conf/openid-vci-credentials.xml b/docs/example/step-3/conf/openid-vci-credentials.xml
new file mode 100644
index 0000000..09dbf29
--- /dev/null
+++ b/docs/example/step-3/conf/openid-vci-credentials.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean id="openidvci.OPESSigningCredential" parent="shibboleth.JWKCredential"
+        p:resource="%{idp.signing.oidc.es.key}" />
+
+    <util:list id="openidvci.SigningCredentials">
+        <ref bean="openidvci.OPESSigningCredential" />
+    </util:list>
+
+</beans>
diff --git a/docs/example/step-2/conf/relying-party.xml b/docs/example/step-3/conf/relying-party.xml
similarity index 96%
copy from docs/example/step-2/conf/relying-party.xml
copy to docs/example/step-3/conf/relying-party.xml
index c042fdb..6bf8645 100644
--- a/docs/example/step-2/conf/relying-party.xml
+++ b/docs/example/step-3/conf/relying-party.xml
@@ -30,6 +30,8 @@
                 <ref bean="OAUTH2.TokenAudience" />
                 <!-- A verifier resolves the did:web identifier from this -->
                 <ref bean="DID.Document" />
+                <!-- A verifier finds the key of a url issuer through this -->
+                <ref bean="OAuth.JWTVCIssuer" />
             </list>
         </property>
     </bean>
@@ -37,10 +39,6 @@
     <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
         <property name="profileConfigurations">
             <list>
-                <ref bean="SAML2.SSO" />
-                <ref bean="SAML2.ECP" />
-                <ref bean="SAML2.Logout" />
-                <ref bean="SAML2.ArtifactResolution" />
             </list>
         </property>
     </bean>
diff --git a/docs/example/step-3/etc/jetty-rewrite-rules.xml b/docs/example/step-3/etc/jetty-rewrite-rules.xml
new file mode 100644
index 0000000..b5b91fa
--- /dev/null
+++ b/docs/example/step-3/etc/jetty-rewrite-rules.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
+<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
+  <!-- Credential Issuer metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-credential-issuer</Set>
+        <Set name="replacement">/idp/profile/openid/vci/issuer-metadata</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Authorization server metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/oauth-authorization-server</Set>
+        <Set name="replacement">/idp/profile/oauth/authorization-server</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- OP metadata, of the OP plugin -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-configuration</Set>
+        <Set name="replacement">/idp/profile/oidc/configuration</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- The JSON-LD context of the vc+sd-jwt credential is a static file of Jetty -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/credentials/GeantIncubatorDiploma_W3C</Set>
+        <Set name="replacement">/credentials/GeantIncubatorDiploma_W3C.json</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- The did:web document -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/did.json</Set>
+        <Set name="replacement">/idp/profile/did/document</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- JWT VC issuer metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/jwt-vc-issuer</Set>
+        <Set name="replacement">/idp/profile/oauth/jwt-vc-issuer</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Wallets running in a browser need this -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
+        <Set name="pattern">/*</Set>
+        <Set name="headerName">Access-Control-Allow-Origin</Set>
+        <Set name="headerValue">*</Set>
+      </New>
+    </Arg>
+  </Call>
+</Configure>
diff --git a/docs/example/step-3/metadata/oidc-client.json b/docs/example/step-3/metadata/oidc-client.json
new file mode 100644
index 0000000..57f62c0
--- /dev/null
+++ b/docs/example/step-3/metadata/oidc-client.json
@@ -0,0 +1,29 @@
+[
+  {
+    "client_id": "offer-caller",
+    "client_name": "Credential offer caller",
+    "client_secret": "CHANGE-ME"
+  },
+  {
+    "client_id": "offer-caller/wallet",
+    "client_name": "Wallets redeeming a pre-authorized code minted by offer-caller",
+    "token_endpoint_auth_method": "none",
+    "grant_types": ["urn:ietf:params:oauth:grant-type:pre-authorized_code"]
+  },
+  {
+    "client_id": "id.animo.paradym",
+    "client_name": "Paradym Wallet",
+    "redirect_uris": ["https://paradym.id/invitation/redirect"],
+    "scope": "openid GeantIncubatorDiploma_SDJWT GeantIncubatorDiploma_W3C GeantIncubatorDiploma_DIDWEB GeantIncubatorDiploma_URL",
+    "audience": [
+      "credentials",
+      "urn:shibboleth.oidc.op.resource:https://issuer.example.org"
+    ],
+    "token_endpoint_auth_method": "none",
+    "response_types": ["code"],
+    "grant_types": [
+      "authorization_code",
+      "urn:ietf:params:oauth:grant-type:pre-authorized_code"
+    ]
+  }
+]
diff --git a/docs/example/step-3/metadata/verifiable-credentials.json b/docs/example/step-3/metadata/verifiable-credentials.json
new file mode 100644
index 0000000..d76ae38
--- /dev/null
+++ b/docs/example/step-3/metadata/verifiable-credentials.json
@@ -0,0 +1,123 @@
+{
+  "credential_configurations_supported": {
+    "GeantIncubatorDiploma_SDJWT": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_SDJWT",
+      "scope": "GeantIncubatorDiploma_SDJWT",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "credential_metadata": {
+        "display": [
+          {
+            "name": "Incubator Diploma",
+            "locale": "en",
+            "description": "Diploma issued by the Trust and Identity Incubator"
+          }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",      "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",        "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",  "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",  "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",  "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_W3C": {
+      "format": "vc+sd-jwt",
+      "scope": "GeantIncubatorDiploma_W3C",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "credential_definition": {
+        "@context": [
+          "https://www.w3.org/ns/credentials/v2",
+          "https://issuer.example.org/credentials/GeantIncubatorDiploma_W3C"
+        ],
+        "type": [
+          "VerifiableCredential",
+          "GeantIncubatorDiploma_W3C"
+        ]
+      },
+      "credential_metadata": {
+        "display": [
+          {
+            "name": "Incubator Diploma, W3C",
+            "locale": "en",
+            "description": "Diploma issued by the Trust and Identity Incubator"
+          }
+        ],
+        "claims": [
+          { "path": ["credentialSubject","diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["credentialSubject","mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["credentialSubject","eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["credentialSubject","givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["credentialSubject","familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["credentialSubject","affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_DIDWEB": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_DIDWEB",
+      "scope": "GeantIncubatorDiploma_DIDWEB",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "did:web"
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, did:web", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_URL": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_URL",
+      "scope": "GeantIncubatorDiploma_URL",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "url"
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, url", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    }
+  }
+}
diff --git a/docs/example/step-3/static/oauth-authorization-server.json b/docs/example/step-3/static/oauth-authorization-server.json
new file mode 100644
index 0000000..6f5ae89
--- /dev/null
+++ b/docs/example/step-3/static/oauth-authorization-server.json
@@ -0,0 +1,39 @@
+{
+   "issuer":"$issuer",
+   "authorization_endpoint":"$baseUrl/idp/profile/oidc/authorize",
+   "pushed_authorization_request_endpoint":"$baseUrl/idp/profile/oauth2/pushed-authorization",
+   "require_pushed_authorization_requests":true,
+   "token_endpoint":"$baseUrl/idp/profile/openid/vci/token",
+   "jwks_uri":"$baseUrl/idp/profile/oidc/keyset",
+   "token_endpoint_auth_methods_supported":[
+      "none"
+   ],
+   "response_types_supported":[
+      "code"
+   ],
+   "grant_types_supported":[
+      "authorization_code",
+      "urn:ietf:params:oauth:grant-type:pre-authorized_code"
+   ],
+   "code_challenge_methods_supported":[
+      "S256"
+   ],
+   "dpop_signing_alg_values_supported":[
+      "ES256",
+      "ES384",
+      "ES512",
+      "PS256",
+      "PS384",
+      "PS512"
+   ],
+   "scopes_supported":[
+      "openid",
+      "GeantIncubatorDiploma_SDJWT",
+      "GeantIncubatorDiploma_W3C",
+      "GeantIncubatorDiploma_DIDWEB",
+      "GeantIncubatorDiploma_URL"
+   ],
+   "authorization_details_types_supported":[
+      "openid_credential"
+   ]
+}
diff --git a/docs/example/step-3/webapps/root/credentials/GeantIncubatorDiploma_W3C.json b/docs/example/step-3/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
new file mode 100644
index 0000000..3f2fb9a
--- /dev/null
+++ b/docs/example/step-3/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
@@ -0,0 +1,10 @@
+{
+  "@context": {
+    "diploma": "https://vocabulary.example.org/terms#diploma",
+    "mail": "https://vocabulary.example.org/terms#mail",
+    "eppn": "https://vocabulary.example.org/terms#eppn",
+    "givenName": "https://vocabulary.example.org/terms#givenName",
+    "familyName": "https://vocabulary.example.org/terms#familyName",
+    "affiliation": "https://vocabulary.example.org/terms#affiliation"
+  }
+}
diff --git a/docs/example/step-4/conf/attribute-filter.xml b/docs/example/step-4/conf/attribute-filter.xml
new file mode 100644
index 0000000..b10fb12
--- /dev/null
+++ b/docs/example/step-4/conf/attribute-filter.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
+        xmlns="urn:mace:shibboleth:2.0:afp"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd">
+
+    <AttributeFilterPolicy id="GeantIncubatorDiplomaToWallets">
+        <PolicyRequirementRule xsi:type="Requester"
+            value="id.animo.paradym" />
+        <AttributeRule attributeID="GeantIncubatorDiploma">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+    </AttributeFilterPolicy>
+
+</AttributeFilterPolicyGroup>
diff --git a/docs/example/step-4/conf/openid-vci-credentials.xml b/docs/example/step-4/conf/openid-vci-credentials.xml
new file mode 100644
index 0000000..09dbf29
--- /dev/null
+++ b/docs/example/step-4/conf/openid-vci-credentials.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean id="openidvci.OPESSigningCredential" parent="shibboleth.JWKCredential"
+        p:resource="%{idp.signing.oidc.es.key}" />
+
+    <util:list id="openidvci.SigningCredentials">
+        <ref bean="openidvci.OPESSigningCredential" />
+    </util:list>
+
+</beans>
diff --git a/docs/example/step-2/conf/relying-party.xml b/docs/example/step-4/conf/relying-party.xml
similarity index 94%
copy from docs/example/step-2/conf/relying-party.xml
copy to docs/example/step-4/conf/relying-party.xml
index c042fdb..667d8b1 100644
--- a/docs/example/step-2/conf/relying-party.xml
+++ b/docs/example/step-4/conf/relying-party.xml
@@ -30,6 +30,10 @@
                 <ref bean="OAUTH2.TokenAudience" />
                 <!-- A verifier resolves the did:web identifier from this -->
                 <ref bean="DID.Document" />
+                <!-- A verifier finds the key of a url issuer through this -->
+                <ref bean="OAuth.JWTVCIssuer" />
+                <!-- Of the federation plugin. Serves the Entity Configuration -->
+                <ref bean="OIDFED.Configuration" />
             </list>
         </property>
     </bean>
@@ -37,10 +41,6 @@
     <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
         <property name="profileConfigurations">
             <list>
-                <ref bean="SAML2.SSO" />
-                <ref bean="SAML2.ECP" />
-                <ref bean="SAML2.Logout" />
-                <ref bean="SAML2.ArtifactResolution" />
             </list>
         </property>
     </bean>
diff --git a/docs/example/step-4/etc/jetty-rewrite-rules.xml b/docs/example/step-4/etc/jetty-rewrite-rules.xml
new file mode 100644
index 0000000..9b8ed66
--- /dev/null
+++ b/docs/example/step-4/etc/jetty-rewrite-rules.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
+<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
+  <!-- Credential Issuer metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-credential-issuer</Set>
+        <Set name="replacement">/idp/profile/openid/vci/issuer-metadata</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Authorization server metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/oauth-authorization-server</Set>
+        <Set name="replacement">/idp/profile/oauth/authorization-server</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- OP metadata, of the OP plugin -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-configuration</Set>
+        <Set name="replacement">/idp/profile/oidc/configuration</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- The JSON-LD context of the vc+sd-jwt credential is a static file of Jetty -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/credentials/GeantIncubatorDiploma_W3C</Set>
+        <Set name="replacement">/credentials/GeantIncubatorDiploma_W3C.json</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- The did:web document -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/did.json</Set>
+        <Set name="replacement">/idp/profile/did/document</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- JWT VC issuer metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/jwt-vc-issuer</Set>
+        <Set name="replacement">/idp/profile/oauth/jwt-vc-issuer</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Entity Configuration, of the federation plugin -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-federation</Set>
+        <Set name="replacement">/idp/profile/oidfed/entity-configuration</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Wallets running in a browser need this -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
+        <Set name="pattern">/*</Set>
+        <Set name="headerName">Access-Control-Allow-Origin</Set>
+        <Set name="headerValue">*</Set>
+      </New>
+    </Arg>
+  </Call>
+</Configure>
diff --git a/docs/example/step-4/metadata/oidc-client.json b/docs/example/step-4/metadata/oidc-client.json
new file mode 100644
index 0000000..57f62c0
--- /dev/null
+++ b/docs/example/step-4/metadata/oidc-client.json
@@ -0,0 +1,29 @@
+[
+  {
+    "client_id": "offer-caller",
+    "client_name": "Credential offer caller",
+    "client_secret": "CHANGE-ME"
+  },
+  {
+    "client_id": "offer-caller/wallet",
+    "client_name": "Wallets redeeming a pre-authorized code minted by offer-caller",
+    "token_endpoint_auth_method": "none",
+    "grant_types": ["urn:ietf:params:oauth:grant-type:pre-authorized_code"]
+  },
+  {
+    "client_id": "id.animo.paradym",
+    "client_name": "Paradym Wallet",
+    "redirect_uris": ["https://paradym.id/invitation/redirect"],
+    "scope": "openid GeantIncubatorDiploma_SDJWT GeantIncubatorDiploma_W3C GeantIncubatorDiploma_DIDWEB GeantIncubatorDiploma_URL",
+    "audience": [
+      "credentials",
+      "urn:shibboleth.oidc.op.resource:https://issuer.example.org"
+    ],
+    "token_endpoint_auth_method": "none",
+    "response_types": ["code"],
+    "grant_types": [
+      "authorization_code",
+      "urn:ietf:params:oauth:grant-type:pre-authorized_code"
+    ]
+  }
+]
diff --git a/docs/example/step-4/metadata/verifiable-credentials.json b/docs/example/step-4/metadata/verifiable-credentials.json
new file mode 100644
index 0000000..b13d335
--- /dev/null
+++ b/docs/example/step-4/metadata/verifiable-credentials.json
@@ -0,0 +1,130 @@
+{
+  "credential_configurations_supported": {
+    "GeantIncubatorDiploma_SDJWT": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_SDJWT",
+      "scope": "GeantIncubatorDiploma_SDJWT",
+      "_issuance_configuration": {
+        "oidfed": false
+      },
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "credential_metadata": {
+        "display": [
+          {
+            "name": "Incubator Diploma",
+            "locale": "en",
+            "description": "Diploma issued by the Trust and Identity Incubator"
+          }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",      "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",        "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",  "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",  "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",  "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_W3C": {
+      "format": "vc+sd-jwt",
+      "scope": "GeantIncubatorDiploma_W3C",
+      "_issuance_configuration": {
+        "oidfed": false
+      },
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "credential_definition": {
+        "@context": [
+          "https://www.w3.org/ns/credentials/v2",
+          "https://issuer.example.org/credentials/GeantIncubatorDiploma_W3C"
+        ],
+        "type": [
+          "VerifiableCredential",
+          "GeantIncubatorDiploma_W3C"
+        ]
+      },
+      "credential_metadata": {
+        "display": [
+          {
+            "name": "Incubator Diploma, W3C",
+            "locale": "en",
+            "description": "Diploma issued by the Trust and Identity Incubator"
+          }
+        ],
+        "claims": [
+          { "path": ["credentialSubject","diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["credentialSubject","mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["credentialSubject","eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["credentialSubject","givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["credentialSubject","familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["credentialSubject","affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_DIDWEB": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_DIDWEB",
+      "scope": "GeantIncubatorDiploma_DIDWEB",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "did:web",
+        "oidfed": false
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, did:web", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_URL": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_URL",
+      "scope": "GeantIncubatorDiploma_URL",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "url"
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, url", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    }
+  }
+}
diff --git a/docs/example/step-4/static/oauth-authorization-server.json b/docs/example/step-4/static/oauth-authorization-server.json
new file mode 100644
index 0000000..6f5ae89
--- /dev/null
+++ b/docs/example/step-4/static/oauth-authorization-server.json
@@ -0,0 +1,39 @@
+{
+   "issuer":"$issuer",
+   "authorization_endpoint":"$baseUrl/idp/profile/oidc/authorize",
+   "pushed_authorization_request_endpoint":"$baseUrl/idp/profile/oauth2/pushed-authorization",
+   "require_pushed_authorization_requests":true,
+   "token_endpoint":"$baseUrl/idp/profile/openid/vci/token",
+   "jwks_uri":"$baseUrl/idp/profile/oidc/keyset",
+   "token_endpoint_auth_methods_supported":[
+      "none"
+   ],
+   "response_types_supported":[
+      "code"
+   ],
+   "grant_types_supported":[
+      "authorization_code",
+      "urn:ietf:params:oauth:grant-type:pre-authorized_code"
+   ],
+   "code_challenge_methods_supported":[
+      "S256"
+   ],
+   "dpop_signing_alg_values_supported":[
+      "ES256",
+      "ES384",
+      "ES512",
+      "PS256",
+      "PS384",
+      "PS512"
+   ],
+   "scopes_supported":[
+      "openid",
+      "GeantIncubatorDiploma_SDJWT",
+      "GeantIncubatorDiploma_W3C",
+      "GeantIncubatorDiploma_DIDWEB",
+      "GeantIncubatorDiploma_URL"
+   ],
+   "authorization_details_types_supported":[
+      "openid_credential"
+   ]
+}
diff --git a/docs/example/step-4/webapps/root/credentials/GeantIncubatorDiploma_W3C.json b/docs/example/step-4/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
new file mode 100644
index 0000000..3f2fb9a
--- /dev/null
+++ b/docs/example/step-4/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
@@ -0,0 +1,10 @@
+{
+  "@context": {
+    "diploma": "https://vocabulary.example.org/terms#diploma",
+    "mail": "https://vocabulary.example.org/terms#mail",
+    "eppn": "https://vocabulary.example.org/terms#eppn",
+    "givenName": "https://vocabulary.example.org/terms#givenName",
+    "familyName": "https://vocabulary.example.org/terms#familyName",
+    "affiliation": "https://vocabulary.example.org/terms#affiliation"
+  }
+}
diff --git a/docs/example/step-5/conf/attribute-filter.xml b/docs/example/step-5/conf/attribute-filter.xml
new file mode 100644
index 0000000..b767242
--- /dev/null
+++ b/docs/example/step-5/conf/attribute-filter.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
+        xmlns="urn:mace:shibboleth:2.0:afp"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd">
+
+    <AttributeFilterPolicy id="GeantIncubatorDiplomaToWallets">
+        <PolicyRequirementRule xsi:type="Requester"
+            value="id.animo.paradym" />
+        <AttributeRule attributeID="GeantIncubatorDiploma">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+    </AttributeFilterPolicy>
+
+    <AttributeFilterPolicy id="GeantIncubatorDiplomaToHAIPWallets">
+        <PolicyRequirementRule xsi:type="Requester"
+            value="haip-wallet" />
+        <AttributeRule attributeID="GeantIncubatorDiploma">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+        <AttributeRule attributeID="GeantIncubatorDiplomaMdoc">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+    </AttributeFilterPolicy>
+
+</AttributeFilterPolicyGroup>
diff --git a/docs/example/step-5/conf/openid-vci-credentials.xml b/docs/example/step-5/conf/openid-vci-credentials.xml
new file mode 100644
index 0000000..66f03b8
--- /dev/null
+++ b/docs/example/step-5/conf/openid-vci-credentials.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean id="openidvci.OPESSigningCredential" parent="shibboleth.JWKCredential"
+        p:resource="%{idp.signing.oidc.es.key}" />
+
+    <bean id="openidvci.X509ESSigningCredential" parent="shibboleth.BasicX509CredentialFactoryBean"
+        p:privateKey="%{idp.home}/credentials/vci-signing.key" p:keyNames="signingvci-x509">
+        <property name="certificates">
+            <list>
+                <value>%{idp.home}/credentials/vci-signing.crt</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="openidvci.X509StatusListSigningCredential" parent="shibboleth.BasicX509CredentialFactoryBean"
+        p:privateKey="%{idp.home}/credentials/vci-status-list.key" p:keyNames="statuslist-x509">
+        <property name="certificates">
+            <list>
+                <value>%{idp.home}/credentials/vci-status-list.crt</value>
+            </list>
+        </property>
+    </bean>
+
+    <util:list id="openidvci.SigningCredentials">
+        <ref bean="openidvci.X509ESSigningCredential" />
+        <ref bean="openidvci.OPESSigningCredential" />
+    </util:list>
+
+    <util:list id="openidvci.status-list.SigningCredentials">
+        <ref bean="openidvci.X509StatusListSigningCredential" />
+        <ref bean="openidvci.OPESSigningCredential" />
+    </util:list>
+
+    <util:list id="openidvci.issuerMetadata.SigningCredentials">
+        <ref bean="openidvci.X509ESSigningCredential" />
+    </util:list>
+
+</beans>
diff --git a/docs/example/step-2/conf/relying-party.xml b/docs/example/step-5/conf/relying-party.xml
similarity index 76%
copy from docs/example/step-2/conf/relying-party.xml
copy to docs/example/step-5/conf/relying-party.xml
index c042fdb..9391e3f 100644
--- a/docs/example/step-2/conf/relying-party.xml
+++ b/docs/example/step-5/conf/relying-party.xml
@@ -30,6 +30,10 @@
                 <ref bean="OAUTH2.TokenAudience" />
                 <!-- A verifier resolves the did:web identifier from this -->
                 <ref bean="DID.Document" />
+                <!-- A verifier finds the key of a url issuer through this -->
+                <ref bean="OAuth.JWTVCIssuer" />
+                <!-- Of the federation plugin. Serves the Entity Configuration -->
+                <ref bean="OIDFED.Configuration" />
             </list>
         </property>
     </bean>
@@ -37,10 +41,6 @@
     <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
         <property name="profileConfigurations">
             <list>
-                <ref bean="SAML2.SSO" />
-                <ref bean="SAML2.ECP" />
-                <ref bean="SAML2.Logout" />
-                <ref bean="SAML2.ArtifactResolution" />
             </list>
         </property>
     </bean>
@@ -89,6 +89,24 @@
           </property>
         </bean>
 
+        <bean parent="RelyingPartyByName"
+              c:relyingPartyIds="#{{'haip-wallet'}}">
+          <property name="profileConfigurations">
+              <list>
+                  <bean parent="OIDC.SSO"
+                        p:authorizationCodeClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
+                        p:forcePKCE="true" p:requirePushedAuthorizationRequest="true"
+                        p:includeIssuerInResponse="true" p:authorizeCodeLifetime="PT1M" />
+                  <bean parent="OpenID.VCI.Token"
+                        p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
+                        p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}" />
+                  <bean parent="OpenID.VCI.Credentials" />
+                  <bean parent="OAUTH2.PAR" p:tokenEndpointAuthMethods="#{{'attest_jwt_client_auth'}}"
+                        p:requestUriClaimsSetManipulationStrategy-ref="openidvci.PushedAuthorizationDPoPJktManipulationStrategy" />
+              </list>
+          </property>
+        </bean>
+
     </util:list>
 
 </beans>
diff --git a/docs/example/step-5/etc/jetty-rewrite-rules.xml b/docs/example/step-5/etc/jetty-rewrite-rules.xml
new file mode 100644
index 0000000..9b8ed66
--- /dev/null
+++ b/docs/example/step-5/etc/jetty-rewrite-rules.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
+<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
+  <!-- Credential Issuer metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-credential-issuer</Set>
+        <Set name="replacement">/idp/profile/openid/vci/issuer-metadata</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Authorization server metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/oauth-authorization-server</Set>
+        <Set name="replacement">/idp/profile/oauth/authorization-server</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- OP metadata, of the OP plugin -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-configuration</Set>
+        <Set name="replacement">/idp/profile/oidc/configuration</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- The JSON-LD context of the vc+sd-jwt credential is a static file of Jetty -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/credentials/GeantIncubatorDiploma_W3C</Set>
+        <Set name="replacement">/credentials/GeantIncubatorDiploma_W3C.json</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- The did:web document -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/did.json</Set>
+        <Set name="replacement">/idp/profile/did/document</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- JWT VC issuer metadata -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/jwt-vc-issuer</Set>
+        <Set name="replacement">/idp/profile/oauth/jwt-vc-issuer</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Entity Configuration, of the federation plugin -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+        <Set name="pattern">/.well-known/openid-federation</Set>
+        <Set name="replacement">/idp/profile/oidfed/entity-configuration</Set>
+      </New>
+    </Arg>
+  </Call>
+  <!-- Wallets running in a browser need this -->
+  <Call name="addRule">
+    <Arg>
+      <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
+        <Set name="pattern">/*</Set>
+        <Set name="headerName">Access-Control-Allow-Origin</Set>
+        <Set name="headerValue">*</Set>
+      </New>
+    </Arg>
+  </Call>
+</Configure>
diff --git a/docs/example/step-5/metadata/oidc-client.json b/docs/example/step-5/metadata/oidc-client.json
new file mode 100644
index 0000000..76a3a9c
--- /dev/null
+++ b/docs/example/step-5/metadata/oidc-client.json
@@ -0,0 +1,39 @@
+[
+  {
+    "client_id": "offer-caller",
+    "client_name": "Credential offer caller",
+    "client_secret": "CHANGE-ME"
+  },
+  {
+    "client_id": "offer-caller/wallet",
+    "client_name": "Wallets redeeming a pre-authorized code minted by offer-caller",
+    "token_endpoint_auth_method": "none",
+    "grant_types": ["urn:ietf:params:oauth:grant-type:pre-authorized_code"]
+  },
+  {
+    "client_id": "id.animo.paradym",
+    "client_name": "Paradym Wallet",
+    "redirect_uris": ["https://paradym.id/invitation/redirect"],
+    "scope": "openid GeantIncubatorDiploma_SDJWT GeantIncubatorDiploma_W3C GeantIncubatorDiploma_DIDWEB GeantIncubatorDiploma_URL",
+    "audience": [
+      "credentials",
+      "urn:shibboleth.oidc.op.resource:https://issuer.example.org"
+    ],
+    "token_endpoint_auth_method": "none",
+    "response_types": ["code"],
+    "grant_types": [
+      "authorization_code",
+      "urn:ietf:params:oauth:grant-type:pre-authorized_code"
+    ]
+  },
+  {
+    "client_id": "haip-wallet",
+    "client_name": "HAIP Wallet",
+    "redirect_uris": ["https://wallet.example.org/callback"],
+    "scope": "openid GeantIncubatorDiploma_HAIP GeantIncubatorDiploma_MDOC",
+    "audience": "credentials",
+    "token_endpoint_auth_method": "attest_jwt_client_auth",
+    "response_types": ["code"],
+    "grant_types": ["authorization_code"]
+  }
+]
diff --git a/docs/example/step-5/metadata/verifiable-credentials.json b/docs/example/step-5/metadata/verifiable-credentials.json
new file mode 100644
index 0000000..8fcfaf1
--- /dev/null
+++ b/docs/example/step-5/metadata/verifiable-credentials.json
@@ -0,0 +1,197 @@
+{
+  "credential_configurations_supported": {
+    "GeantIncubatorDiploma_SDJWT": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_SDJWT",
+      "scope": "GeantIncubatorDiploma_SDJWT",
+      "_issuance_configuration": {
+        "oidfed": false
+      },
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "credential_metadata": {
+        "display": [
+          {
+            "name": "Incubator Diploma",
+            "locale": "en",
+            "description": "Diploma issued by the Trust and Identity Incubator"
+          }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",      "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",        "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",  "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",  "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",  "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_W3C": {
+      "format": "vc+sd-jwt",
+      "scope": "GeantIncubatorDiploma_W3C",
+      "_issuance_configuration": {
+        "oidfed": false
+      },
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "credential_definition": {
+        "@context": [
+          "https://www.w3.org/ns/credentials/v2",
+          "https://issuer.example.org/credentials/GeantIncubatorDiploma_W3C"
+        ],
+        "type": [
+          "VerifiableCredential",
+          "GeantIncubatorDiploma_W3C"
+        ]
+      },
+      "credential_metadata": {
+        "display": [
+          {
+            "name": "Incubator Diploma, W3C",
+            "locale": "en",
+            "description": "Diploma issued by the Trust and Identity Incubator"
+          }
+        ],
+        "claims": [
+          { "path": ["credentialSubject","diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["credentialSubject","mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["credentialSubject","eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["credentialSubject","givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["credentialSubject","familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["credentialSubject","affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_DIDWEB": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_DIDWEB",
+      "scope": "GeantIncubatorDiploma_DIDWEB",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "did:web",
+        "oidfed": false
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, did:web", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_URL": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_URL",
+      "scope": "GeantIncubatorDiploma_URL",
+      "cryptographic_binding_methods_supported": ["did:jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"]
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "url"
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, url", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_HAIP": {
+      "format": "dc+sd-jwt",
+      "vct": "GeantIncubatorDiploma_HAIP",
+      "scope": "GeantIncubatorDiploma_HAIP",
+      "cryptographic_binding_methods_supported": ["jwk"],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"],
+          "key_attestations_required": {
+            "key_storage": ["iso_18045_moderate"],
+            "user_authentication": ["iso_18045_moderate"]
+          }
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "url",
+        "oidfed": false
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, HAIP", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["diploma"],     "display": [{ "name": "Diploma",        "locale": "en" }] },
+          { "path": ["mail"],        "display": [{ "name": "Email",          "locale": "en" }] },
+          { "path": ["eppn"],        "display": [{ "name": "Principal name", "locale": "en" }] },
+          { "path": ["givenName"],   "display": [{ "name": "Given names",    "locale": "en" }] },
+          { "path": ["familyName"],  "display": [{ "name": "Family name",    "locale": "en" }] },
+          { "path": ["affiliation"], "display": [{ "name": "Affiliation",    "locale": "en" }] }
+        ]
+      }
+    },
+    "GeantIncubatorDiploma_MDOC": {
+      "format": "mso_mdoc",
+      "doctype": "org.geant.incubator.diploma.1",
+      "scope": "GeantIncubatorDiploma_MDOC",
+      "cryptographic_binding_methods_supported": ["cose_key"],
+      "credential_signing_alg_values_supported": [-7],
+      "proof_types_supported": {
+        "jwt": {
+          "proof_signing_alg_values_supported": ["ES256"],
+          "key_attestations_required": {
+            "key_storage": ["iso_18045_moderate"],
+            "user_authentication": ["iso_18045_moderate"]
+          }
+        }
+      },
+      "_issuance_configuration": {
+        "issuer": "url",
+        "lifetime": "P45D",
+        "claim_types": [
+          { "path": ["org.geant.incubator.1", "issue_date"], "type": "full-date" }
+        ]
+      },
+      "credential_metadata": {
+        "display": [
+          { "name": "Incubator Diploma, mdoc", "locale": "en" }
+        ],
+        "claims": [
+          { "path": ["org.geant.incubator.1", "diploma"],     "display": [{ "name": "Diploma",     "locale": "en" }] },
+          { "path": ["org.geant.incubator.1", "issue_date"],  "display": [{ "name": "Issued",      "locale": "en" }] },
+          { "path": ["org.geant.incubator.1", "mail"],        "display": [{ "name": "Email",       "locale": "en" }] },
+          { "path": ["org.geant.incubator.1", "given_name"],  "display": [{ "name": "Given names", "locale": "en" }] },
+          { "path": ["org.geant.incubator.1", "family_name"], "display": [{ "name": "Family name", "locale": "en" }] }
+        ]
+      }
+    }
+  }
+}
diff --git a/docs/example/step-5/static/oauth-authorization-server.json b/docs/example/step-5/static/oauth-authorization-server.json
new file mode 100644
index 0000000..1aa03ac
--- /dev/null
+++ b/docs/example/step-5/static/oauth-authorization-server.json
@@ -0,0 +1,49 @@
+{
+   "issuer":"$issuer",
+   "authorization_endpoint":"$baseUrl/idp/profile/oidc/authorize",
+   "pushed_authorization_request_endpoint":"$baseUrl/idp/profile/oauth2/pushed-authorization",
+   "require_pushed_authorization_requests":true,
+   "token_endpoint":"$baseUrl/idp/profile/openid/vci/token",
+   "jwks_uri":"$baseUrl/idp/profile/oidc/keyset",
+   "token_endpoint_auth_methods_supported":[
+      "none",
+      "attest_jwt_client_auth"
+   ],
+   "client_attestation_signing_alg_values_supported":[
+      "ES256"
+   ],
+   "client_attestation_pop_signing_alg_values_supported":[
+      "ES256"
+   ],
+   "authorization_response_iss_parameter_supported":true,
+   "response_types_supported":[
+      "code"
+   ],
+   "grant_types_supported":[
+      "authorization_code",
+      "urn:ietf:params:oauth:grant-type:pre-authorized_code"
+   ],
+   "code_challenge_methods_supported":[
+      "S256"
+   ],
+   "dpop_signing_alg_values_supported":[
+      "ES256",
+      "ES384",
+      "ES512",
+      "PS256",
+      "PS384",
+      "PS512"
+   ],
+   "scopes_supported":[
+      "openid",
+      "GeantIncubatorDiploma_SDJWT",
+      "GeantIncubatorDiploma_W3C",
+      "GeantIncubatorDiploma_DIDWEB",
+      "GeantIncubatorDiploma_URL",
+      "GeantIncubatorDiploma_HAIP",
+      "GeantIncubatorDiploma_MDOC"
+   ],
+   "authorization_details_types_supported":[
+      "openid_credential"
+   ]
+}
diff --git a/docs/example/step-5/webapps/root/credentials/GeantIncubatorDiploma_W3C.json b/docs/example/step-5/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
new file mode 100644
index 0000000..3f2fb9a
--- /dev/null
+++ b/docs/example/step-5/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
@@ -0,0 +1,10 @@
+{
+  "@context": {
+    "diploma": "https://vocabulary.example.org/terms#diploma",
+    "mail": "https://vocabulary.example.org/terms#mail",
+    "eppn": "https://vocabulary.example.org/terms#eppn",
+    "givenName": "https://vocabulary.example.org/terms#givenName",
+    "familyName": "https://vocabulary.example.org/terms#familyName",
+    "affiliation": "https://vocabulary.example.org/terms#affiliation"
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list