[java-idp-plugin-vci] 01/01: Exampe files shown in README
Codeberg
noreply at shibboleth.net
Fri Oct 2 05:14:15 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/4dc4c18a0f6ca35ac9941942845e2a2e6f1101e7
commit 4dc4c18a0f6ca35ac9941942845e2a2e6f1101e7
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Fri Oct 2 08:13:55 2026 +0300
Exampe files shown in README
---
README.md | 217 +++++++++++++--------
docs/example/step-1/conf/attribute-filter.xml | 15 ++
docs/example/step-1/conf/relying-party.xml | 92 +++++++++
docs/example/step-1/etc/jetty-rewrite-rules.xml | 50 +++++
docs/example/step-1/metadata/oidc-client.json | 29 +++
.../step-1/metadata/verifiable-credentials.json | 69 +++++++
.../step-1/static/oauth-authorization-server.json | 37 ++++
.../credentials/GeantIncubatorDiploma_W3C.json | 10 +
docs/example/step-2/conf/attribute-filter.xml | 15 ++
.../example/step-2/conf/openid-vci-credentials.xml | 18 ++
docs/example/step-2/conf/relying-party.xml | 94 +++++++++
docs/example/step-2/etc/jetty-rewrite-rules.xml | 59 ++++++
docs/example/step-2/metadata/oidc-client.json | 29 +++
.../step-2/metadata/verifiable-credentials.json | 96 +++++++++
.../step-2/static/oauth-authorization-server.json | 38 ++++
.../credentials/GeantIncubatorDiploma_W3C.json | 10 +
16 files changed, 800 insertions(+), 78 deletions(-)
diff --git a/README.md b/README.md
index 18c5d8e..d61ac64 100644
--- a/README.md
+++ b/README.md
@@ -1071,47 +1071,47 @@ What is new:
- the Status List url of the credential ends with `~did-web`
- the plugin gets a signing key list of its own, with the EC key of the OP only
-The credential goes next to the two of Step 1 in *metadata/verifiable-credentials.json*:
+The changes per file, each with a link to the whole file after this step:
<details>
-<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",
- "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" }] }
- ]
- }
- }
- }
-}
-```
+<summary>metadata/verifiable-credentials.json</summary>
+
+```diff
+ ...
+ ]
+ }
++ },
++ "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" }] }
++ ]
++ }
+ }
+ }
+```
+
+Full file: [metadata/verifiable-credentials.json](docs/example/step-2/metadata/verifiable-credentials.json)
</details>
@@ -1119,50 +1119,117 @@ Setting `openidvci.issuer = did:web` in *conf/openid-vci.properties* would do th
credential that states no `issuer` of its own. Here we keep the deployment default as did:jwk
and state it per credential.
-Add **DID.Document** to the anonymous relying party in *conf/relying-party.xml*:
+<details>
+<summary>conf/relying-party.xml</summary>
-```xml
-<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>
+```diff
+ ...
+ <!-- Of the OP plugin. Needed for the audience values of the wallet -->
+ <ref bean="OAUTH2.TokenAudience" />
++ <!-- A verifier resolves the did:web identifier from this -->
++ <ref bean="DID.Document" />
+ </list>
+ </property>
```
-and wire it in *etc/jetty-rewrite-rules.xml*:
+Full file: [conf/relying-party.xml](docs/example/step-2/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/did.json</Set>
- <Set name="replacement">/idp/profile/did/document</Set>
- </New>
- </Arg>
- </Call>
-</Configure>
+</details>
+
+<details>
+<summary>etc/jetty-rewrite-rules.xml</summary>
+
+```diff
+ ...
+ </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>
+ <!-- Wallets running in a browser need this -->
+ <Call name="addRule">
+```
+
+Full file: [etc/jetty-rewrite-rules.xml](docs/example/step-2/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",
++ "scope": "openid GeantIncubatorDiploma_SDJWT GeantIncubatorDiploma_W3C GeantIncubatorDiploma_DIDWEB",
+ "audience": [
+ "credentials",
```
-The document has no file behind it. It is formed from the keys of
+Full file: [metadata/oidc-client.json](docs/example/step-2/metadata/oidc-client.json)
+
+</details>
+
+<details>
+<summary>static/oauth-authorization-server.json</summary>
+
+```diff
+ ...
+ "openid",
+ "GeantIncubatorDiploma_SDJWT",
+- "GeantIncubatorDiploma_W3C"
++ "GeantIncubatorDiploma_W3C",
++ "GeantIncubatorDiploma_DIDWEB"
+ ],
+ "authorization_details_types_supported":[
+```
+
+Full file: [static/oauth-authorization-server.json](docs/example/step-2/static/oauth-authorization-server.json)
+
+</details>
+
+The did:web document has no file behind it. It is formed from the keys of
**openidvci.SigningCredentials**. Without that list it would have all the signing keys of the OP,
also the RSA key. 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:
+<details>
+<summary>conf/openid-vci-credentials.xml</summary>
+
```xml
-<bean id="openidvci.OPESSigningCredential" parent="shibboleth.JWKCredential"
- p:resource="%{idp.signing.oidc.es.key}" />
+<?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>
-<util:list id="openidvci.SigningCredentials">
- <ref bean="openidvci.OPESSigningCredential" />
-</util:list>
+</beans>
```
+Full file: [conf/openid-vci-credentials.xml](docs/example/step-2/conf/openid-vci-credentials.xml)
+
+</details>
+
+A key needs a name to be listed, the `kid` of a JWK key. The EC key of the OP has one.
+
Import the file into *conf/global.xml*. The Entity Configuration of
[Step 4](#step-4-make-the-url-credential-an-openid-federation-credential) does not see beans of
*conf/credentials.xml*:
@@ -1171,6 +1238,9 @@ Import the file into *conf/global.xml*. The Entity Configuration of
<import resource="openid-vci-credentials.xml"/>
```
+Add `<AttributeEncoder xsi:type="oidc:OIDCString" name="GeantIncubatorDiploma_DIDWEB" />` to the
+attribute definition of Step 1. The claims are the same, so the script does not change.
+
<details>
<summary>Example of the document at /.well-known/did.json</summary>
@@ -1203,15 +1273,6 @@ Import the file into *conf/global.xml*. The Entity Configuration of
</details>
-A key needs a name to be listed, the `kid` of a JWK key. The EC key of the OP has one.
-
-To make the credential requestable, the same small additions for both flows:
-
-- `GeantIncubatorDiploma_DIDWEB` to `scope` of `id.animo.paradym` in *metadata/oidc-client.json*
-- the same to `scopes_supported` of *static/oauth-authorization-server.json*
-- `<AttributeEncoder xsi:type="oidc:OIDCString" name="GeantIncubatorDiploma_DIDWEB" />` to the
- attribute definition of Step 1. The claims are the same, so the script does not change.
-
And the offer of the pre-authorized code flow has the new id:
```bash
diff --git a/docs/example/step-1/conf/attribute-filter.xml b/docs/example/step-1/conf/attribute-filter.xml
new file mode 100644
index 0000000..b10fb12
--- /dev/null
+++ b/docs/example/step-1/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-1/conf/relying-party.xml b/docs/example/step-1/conf/relying-party.xml
new file mode 100644
index 0000000..87e6a74
--- /dev/null
+++ b/docs/example/step-1/conf/relying-party.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ 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/context http://www.springframework.org/schema/context/spring-context.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="shibboleth.UnverifiedRelyingParty" parent="RelyingParty">
+ <property name="profileConfigurations">
+ <list>
+ <!-- The wallet reads the Credential Issuer metadata -->
+ <ref bean="OpenID.VCI.IssuerMetadata" />
+ <!-- The wallet finds the token endpoint through this one -->
+ <ref bean="OAuth.AuthorizationServer" />
+ <!-- The wallet asks for the nonce its key proof has to carry -->
+ <ref bean="OpenID.VCI.Nonce" />
+ <!-- A verifier reads the Status List -->
+ <ref bean="OAuth.StatusList" />
+ <!-- Of the OP plugin. Publishes the keys of the OP as a keyset -->
+ <ref bean="OIDC.Keyset" />
+ <!-- Of the OP plugin. Serves /.well-known/openid-configuration -->
+ <ref bean="OIDC.Configuration" />
+ <!-- Of the OP plugin. Needed for the audience values of the wallet -->
+ <ref bean="OAUTH2.TokenAudience" />
+ </list>
+ </property>
+ </bean>
+
+ <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>
+
+ <util:list id="shibboleth.RelyingPartyOverrides">
+
+ <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>
+
+ <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>
+
+ <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>
+
+ </util:list>
+
+</beans>
diff --git a/docs/example/step-1/etc/jetty-rewrite-rules.xml b/docs/example/step-1/etc/jetty-rewrite-rules.xml
new file mode 100644
index 0000000..d7017ac
--- /dev/null
+++ b/docs/example/step-1/etc/jetty-rewrite-rules.xml
@@ -0,0 +1,50 @@
+<?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>
+ <!-- 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-1/metadata/oidc-client.json b/docs/example/step-1/metadata/oidc-client.json
new file mode 100644
index 0000000..a95e4a5
--- /dev/null
+++ b/docs/example/step-1/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",
+ "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-1/metadata/verifiable-credentials.json b/docs/example/step-1/metadata/verifiable-credentials.json
new file mode 100644
index 0000000..f1df0c1
--- /dev/null
+++ b/docs/example/step-1/metadata/verifiable-credentials.json
@@ -0,0 +1,69 @@
+{
+ "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" }] }
+ ]
+ }
+ }
+ }
+}
diff --git a/docs/example/step-1/static/oauth-authorization-server.json b/docs/example/step-1/static/oauth-authorization-server.json
new file mode 100644
index 0000000..fd7ac81
--- /dev/null
+++ b/docs/example/step-1/static/oauth-authorization-server.json
@@ -0,0 +1,37 @@
+{
+ "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"
+ ],
+ "authorization_details_types_supported":[
+ "openid_credential"
+ ]
+}
diff --git a/docs/example/step-1/webapps/root/credentials/GeantIncubatorDiploma_W3C.json b/docs/example/step-1/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
new file mode 100644
index 0000000..3f2fb9a
--- /dev/null
+++ b/docs/example/step-1/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-2/conf/attribute-filter.xml b/docs/example/step-2/conf/attribute-filter.xml
new file mode 100644
index 0000000..b10fb12
--- /dev/null
+++ b/docs/example/step-2/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-2/conf/openid-vci-credentials.xml b/docs/example/step-2/conf/openid-vci-credentials.xml
new file mode 100644
index 0000000..09dbf29
--- /dev/null
+++ b/docs/example/step-2/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-2/conf/relying-party.xml
new file mode 100644
index 0000000..c042fdb
--- /dev/null
+++ b/docs/example/step-2/conf/relying-party.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ 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/context http://www.springframework.org/schema/context/spring-context.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="shibboleth.UnverifiedRelyingParty" parent="RelyingParty">
+ <property name="profileConfigurations">
+ <list>
+ <!-- The wallet reads the Credential Issuer metadata -->
+ <ref bean="OpenID.VCI.IssuerMetadata" />
+ <!-- The wallet finds the token endpoint through this one -->
+ <ref bean="OAuth.AuthorizationServer" />
+ <!-- The wallet asks for the nonce its key proof has to carry -->
+ <ref bean="OpenID.VCI.Nonce" />
+ <!-- A verifier reads the Status List -->
+ <ref bean="OAuth.StatusList" />
+ <!-- Of the OP plugin. Publishes the keys of the OP as a keyset -->
+ <ref bean="OIDC.Keyset" />
+ <!-- Of the OP plugin. Serves /.well-known/openid-configuration -->
+ <ref bean="OIDC.Configuration" />
+ <!-- Of the OP plugin. Needed for the audience values of the wallet -->
+ <ref bean="OAUTH2.TokenAudience" />
+ <!-- A verifier resolves the did:web identifier from this -->
+ <ref bean="DID.Document" />
+ </list>
+ </property>
+ </bean>
+
+ <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>
+
+ <util:list id="shibboleth.RelyingPartyOverrides">
+
+ <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>
+
+ <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>
+
+ <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>
+
+ </util:list>
+
+</beans>
diff --git a/docs/example/step-2/etc/jetty-rewrite-rules.xml b/docs/example/step-2/etc/jetty-rewrite-rules.xml
new file mode 100644
index 0000000..ef1ffe6
--- /dev/null
+++ b/docs/example/step-2/etc/jetty-rewrite-rules.xml
@@ -0,0 +1,59 @@
+<?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>
+ <!-- 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-2/metadata/oidc-client.json b/docs/example/step-2/metadata/oidc-client.json
new file mode 100644
index 0000000..0d835e3
--- /dev/null
+++ b/docs/example/step-2/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",
+ "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-2/metadata/verifiable-credentials.json b/docs/example/step-2/metadata/verifiable-credentials.json
new file mode 100644
index 0000000..ab0a926
--- /dev/null
+++ b/docs/example/step-2/metadata/verifiable-credentials.json
@@ -0,0 +1,96 @@
+{
+ "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" }] }
+ ]
+ }
+ }
+ }
+}
diff --git a/docs/example/step-2/static/oauth-authorization-server.json b/docs/example/step-2/static/oauth-authorization-server.json
new file mode 100644
index 0000000..25684d1
--- /dev/null
+++ b/docs/example/step-2/static/oauth-authorization-server.json
@@ -0,0 +1,38 @@
+{
+ "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"
+ ],
+ "authorization_details_types_supported":[
+ "openid_credential"
+ ]
+}
diff --git a/docs/example/step-2/webapps/root/credentials/GeantIncubatorDiploma_W3C.json b/docs/example/step-2/webapps/root/credentials/GeantIncubatorDiploma_W3C.json
new file mode 100644
index 0000000..3f2fb9a
--- /dev/null
+++ b/docs/example/step-2/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