From efa6ddc41ea58b6f7a78265ae614ea852b64fe43 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Thu, 25 Jan 2024 07:36:28 +0100 Subject: [PATCH] Create SPI and Provider for Verifiable Credentials Signing #25937 (#26263) * implement oid4vci service interfaces Signed-off-by: Stefan Wiedemann * add oid4vc to the disabled features test Signed-off-by: Stefan Wiedemann * fix test and add doc Signed-off-by: Stefan Wiedemann * add the new preview feature Signed-off-by: Stefan Wiedemann * add class-level doc remove wildcard imports Signed-off-by: Stefan Wiedemann * add license headers Signed-off-by: Stefan Wiedemann * fix year Signed-off-by: Stefan Wiedemann * fix teste Signed-off-by: Stefan Wiedemann * two additional test fixes Signed-off-by: Stefan Wiedemann * make the feature experimental Signed-off-by: Stefan Wiedemann * remove clock Signed-off-by: Stefan Wiedemann * remove usage of var Signed-off-by: Stefan Wiedemann * fix tests Signed-off-by: Stefan Wiedemann --------- Signed-off-by: Stefan Wiedemann --- .../java/org/keycloak/common/Profile.java | 2 + .../java/org/keycloak/common/ProfileTest.java | 3 +- ...ndDistTest.testBuildHelp.unix.approved.txt | 14 +- ...istTest.testBuildHelp.windows.approved.txt | 17 ++- ...dDistTest.testExportHelp.unix.approved.txt | 16 +-- ...stTest.testExportHelpAll.unix.approved.txt | 16 +-- ...dDistTest.testImportHelp.unix.approved.txt | 16 +-- ...stTest.testImportHelpAll.unix.approved.txt | 16 +-- ...istTest.testStartDevHelp.unix.approved.txt | 16 +-- ...Test.testStartDevHelp.windows.approved.txt | 2 +- ...Test.testStartDevHelpAll.unix.approved.txt | 16 +-- ...t.testStartDevHelpAll.windows.approved.txt | 2 +- ...ndDistTest.testStartHelp.unix.approved.txt | 16 +-- ...istTest.testStartHelp.windows.approved.txt | 2 +- ...istTest.testStartHelpAll.unix.approved.txt | 16 +-- ...Test.testStartHelpAll.windows.approved.txt | 4 +- .../oid4vc/issuance/VCIssuerException.java | 34 +++++ .../issuance/signing/JwtSigningService.java | 42 ++++++ .../JwtSigningServiceProviderFactory.java | 74 +++++++++++ .../issuance/signing/LDSigningService.java | 46 +++++++ .../LDSigningServiceProviderFactory.java | 74 +++++++++++ .../issuance/signing/SdJwtSigningService.java | 42 ++++++ .../SdJwtSigningServiceProviderFactory.java | 78 +++++++++++ .../issuance/signing/SigningProperties.java | 58 +++++++++ .../issuance/signing/SigningService.java | 51 ++++++++ .../signing/SigningServiceException.java | 34 +++++ .../VCSigningServiceProviderFactory.java | 90 +++++++++++++ .../issuance/signing/VCSigningServiceSpi.java | 51 ++++++++ .../VerifiableCredentialsSigningService.java | 37 ++++++ .../oid4vc/model/CredentialSubject.java | 49 +++++++ .../protocol/oid4vc/model/Format.java | 81 ++++++++++++ .../oid4vc/model/VerifiableCredential.java | 121 ++++++++++++++++++ .../services/org.keycloak.provider.Spi | 3 +- 33 files changed, 1052 insertions(+), 87 deletions(-) create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/VCIssuerException.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningService.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningServiceProviderFactory.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningService.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningServiceProviderFactory.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningService.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningServiceProviderFactory.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningProperties.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningService.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningServiceException.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceProviderFactory.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceSpi.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VerifiableCredentialsSigningService.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/model/CredentialSubject.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/model/Format.java create mode 100644 services/src/main/java/org/keycloak/protocol/oid4vc/model/VerifiableCredential.java diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java index 3212e3e9bd..9c4f147efe 100755 --- a/common/src/main/java/org/keycloak/common/Profile.java +++ b/common/src/main/java/org/keycloak/common/Profile.java @@ -111,6 +111,8 @@ public class Profile { HOSTNAME_V1("Hostname Options V1", Type.DEFAULT), //HOSTNAME_V2("Hostname Options V2", Type.DEFAULT, 2), + OID4VC_VCI("Support for the OID4VCI protocol as part of OID4VC.", Type.EXPERIMENTAL), + DECLARATIVE_UI("declarative ui spi", Type.EXPERIMENTAL), ; diff --git a/common/src/test/java/org/keycloak/common/ProfileTest.java b/common/src/test/java/org/keycloak/common/ProfileTest.java index 78ce8b93cb..d8af3e4450 100644 --- a/common/src/test/java/org/keycloak/common/ProfileTest.java +++ b/common/src/test/java/org/keycloak/common/ProfileTest.java @@ -86,7 +86,8 @@ public class ProfileTest { Profile.Feature.UPDATE_EMAIL, Profile.Feature.LINKEDIN_OAUTH, Profile.Feature.OFFLINE_SESSION_PRELOADING, - Profile.Feature.CLIENT_TYPES + Profile.Feature.CLIENT_TYPES, + Profile.Feature.OID4VC_VCI )); // KERBEROS can be disabled (i.e. FIPS mode disables SunJGSS provider) diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt index 65f13839e5..fc758f626a 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt @@ -67,19 +67,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. HTTP(S): diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt index 896e6f62c1..eb6dd0a245 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt @@ -64,20 +64,19 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], - device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], - hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], + scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], + transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, client-types, + authorization, ciba, client-policies, client-secret-rotation, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, scripts, step-up-authentication, token-exchange, transient-users, update-email, web-authn. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt index aa71080ac0..5853c84320 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt @@ -62,19 +62,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Config: @@ -156,4 +156,4 @@ Export: --users-per-file Set the number of users per file. It is used only if 'users' is set to 'different_files'. Increasing this number leads to exponentially increasing - export times. Default: 50. \ No newline at end of file + export times. Default: 50. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt index aa71080ac0..5853c84320 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt @@ -62,19 +62,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Config: @@ -156,4 +156,4 @@ Export: --users-per-file Set the number of users per file. It is used only if 'users' is set to 'different_files'. Increasing this number leads to exponentially increasing - export times. Default: 50. \ No newline at end of file + export times. Default: 50. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt index 3fc607e3d6..ecf12a0201 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt @@ -62,19 +62,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Config: @@ -150,4 +150,4 @@ Import: --file Set the path to a file that will be read. --override Set if existing data should be overwritten. If set to false, data will be - ignored. Default: true. \ No newline at end of file + ignored. Default: true. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt index 3fc607e3d6..ecf12a0201 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt @@ -62,19 +62,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Config: @@ -150,4 +150,4 @@ Import: --file Set the path to a file that will be read. --override Set if existing data should be overwritten. If set to false, data will be - ignored. Default: true. \ No newline at end of file + ignored. Default: true. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt index a6d0042392..b1eb47018b 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt @@ -92,19 +92,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Hostname: @@ -293,4 +293,4 @@ Security: Do NOT start the server using this command when deploying to production. Use 'kc.sh start-dev --help-all' to list all available options, including build -options. \ No newline at end of file +options. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt index cda67ffd7c..d1712141d0 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt @@ -102,7 +102,7 @@ Feature: authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, scripts, step-up-authentication, token-exchange, transient-users, update-email, web-authn. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt index a6d0042392..b1eb47018b 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt @@ -92,19 +92,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Hostname: @@ -293,4 +293,4 @@ Security: Do NOT start the server using this command when deploying to production. Use 'kc.sh start-dev --help-all' to list all available options, including build -options. \ No newline at end of file +options. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt index cda67ffd7c..d1712141d0 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt @@ -102,7 +102,7 @@ Feature: authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, scripts, step-up-authentication, token-exchange, transient-users, update-email, web-authn. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt index f674126326..1f941fd9e5 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt @@ -93,19 +93,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Hostname: @@ -298,4 +298,4 @@ By default, this command tries to update the server configuration by running a $ kc.sh start '--optimized' By doing that, the server should start faster based on any previous -configuration you have set when manually running the 'build' command. \ No newline at end of file +configuration you have set when manually running the 'build' command. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt index fa6768c8ae..7ed5a6c716 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt @@ -103,7 +103,7 @@ Feature: authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, scripts, step-up-authentication, token-exchange, transient-users, update-email, web-authn. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt index f674126326..1f941fd9e5 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt @@ -93,19 +93,19 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], - linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: - v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: - v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn - [:v1]. + linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], + oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], + step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], + update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, - step-up-authentication, token-exchange, transient-users, update-email, - web-authn. + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, + scripts, step-up-authentication, token-exchange, transient-users, + update-email, web-authn. Hostname: @@ -298,4 +298,4 @@ By default, this command tries to update the server configuration by running a $ kc.sh start '--optimized' By doing that, the server should start faster based on any previous -configuration you have set when manually running the 'build' command. \ No newline at end of file +configuration you have set when manually running the 'build' command. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt index e88980a713..605aa7ca25 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt @@ -93,7 +93,7 @@ Feature: client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], - offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], + offline-session-preloading[:v1], oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled @@ -102,7 +102,7 @@ Feature: authorization, ciba, client-policies, client-secret-rotation, client-types, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, - offline-session-preloading, par, preview, recovery-codes, scripts, + offline-session-preloading, oid4vc-vci, par, preview, recovery-codes, scripts, step-up-authentication, token-exchange, transient-users, update-email, web-authn. diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/VCIssuerException.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/VCIssuerException.java new file mode 100644 index 0000000000..d8f137660d --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/VCIssuerException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance; + +/** + * Exception to be thrown in case credentials issuance fails. + * + * @author Stefan Wiedemann + */ +public class VCIssuerException extends RuntimeException { + + public VCIssuerException(String message) { + super(message); + } + + public VCIssuerException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningService.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningService.java new file mode 100644 index 0000000000..072b0f9bc3 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningService.java @@ -0,0 +1,42 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.models.KeycloakSession; +import org.keycloak.protocol.oid4vc.model.VerifiableCredential; + +/** + * {@link VerifiableCredentialsSigningService} implementing the JWT_VC format. It returns a string, containing the + * Signed JWT-Credential + * {@see https://identity.foundation/jwt-vc-presentation-profile/} + * + * @author Stefan Wiedemann + */ +public class JwtSigningService extends SigningService { + + public JwtSigningService(KeycloakSession keycloakSession, String keyId, String algorithmType) { + super(keycloakSession, keyId, algorithmType); + } + + @Override + public String signCredential(VerifiableCredential verifiableCredential) { + + throw new UnsupportedOperationException("JWT-VC Credentials Signing is not yet supported."); + } + +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningServiceProviderFactory.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningServiceProviderFactory.java new file mode 100644 index 0000000000..085813523f --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/JwtSigningServiceProviderFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.component.ComponentModel; +import org.keycloak.component.ComponentValidationException; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.protocol.oid4vc.model.Format; +import org.keycloak.provider.ConfigurationValidationHelper; +import org.keycloak.provider.ProviderConfigProperty; + +import java.util.List; + +/** + * Provider Factory to create {@link JwtSigningService}s + * @author Stefan Wiedemann + */ +public class JwtSigningServiceProviderFactory implements VCSigningServiceProviderFactory { + + public static final Format SUPPORTED_FORMAT = Format.JWT_VC; + private static final String HELP_TEXT = "Issues JWT-VCs following the specification of https://identity.foundation/jwt-vc-presentation-profile/."; + + @Override + public VerifiableCredentialsSigningService create(KeycloakSession session, ComponentModel model) { + String keyId = model.get(SigningProperties.KEY_ID.getKey()); + String algorithmType = model.get(SigningProperties.ALGORITHM_TYPE.getKey()); + + return new JwtSigningService(session, keyId, algorithmType); + } + + @Override + public String getHelpText() { + return HELP_TEXT; + } + + @Override + public List getConfigProperties() { + return VCSigningServiceProviderFactory.configurationBuilder() + .property(SigningProperties.ALGORITHM_TYPE.asConfigProperty()) + .build(); + } + + @Override + public String getId() { + return SUPPORTED_FORMAT.toString(); + } + + @Override + public void validateSpecificConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model) throws ComponentValidationException { + ConfigurationValidationHelper.check(model) + .checkRequired(SigningProperties.ALGORITHM_TYPE.asConfigProperty()); + } + + @Override + public Format supportedFormat() { + return SUPPORTED_FORMAT; + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningService.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningService.java new file mode 100644 index 0000000000..71bc77bfb7 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningService.java @@ -0,0 +1,46 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + + +import org.keycloak.models.KeycloakSession; +import org.keycloak.protocol.oid4vc.model.VerifiableCredential; + +/** + * {@link VerifiableCredentialsSigningService} implementing the LDP_VC format. It returns a Verifiable Credential, + * containing the created LDProof. + *

+ * {@see https://www.w3.org/TR/vc-data-model/} + * + * @author Stefan Wiedemann + */ +public class LDSigningService extends SigningService { + + + public LDSigningService(KeycloakSession keycloakSession, String keyId, String ldpType) { + super(keycloakSession, keyId, ldpType); + + } + + @Override + public VerifiableCredential signCredential(VerifiableCredential verifiableCredential) { + + throw new UnsupportedOperationException("LD-Credentials Signing is not yet supported."); + } + +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningServiceProviderFactory.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningServiceProviderFactory.java new file mode 100644 index 0000000000..6ebb156b17 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/LDSigningServiceProviderFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.component.ComponentModel; +import org.keycloak.component.ComponentValidationException; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.protocol.oid4vc.model.Format; +import org.keycloak.provider.ConfigurationValidationHelper; +import org.keycloak.provider.ProviderConfigProperty; + +import java.util.List; + +/** + * Provider Factory to create {@link LDSigningService}s + * + * @author Stefan Wiedemann + */ +public class LDSigningServiceProviderFactory implements VCSigningServiceProviderFactory { + public static final Format SUPPORTED_FORMAT = Format.LDP_VC; + private static final String HELP_TEXT = "Issues Verifiable Credentials in the W3C Data Model, using Linked-Data Proofs. See https://www.w3.org/TR/vc-data-model/"; + + @Override + public VerifiableCredentialsSigningService create(KeycloakSession session, ComponentModel model) { + String keyId = model.get(SigningProperties.KEY_ID.getKey()); + String proofType = model.get(SigningProperties.PROOF_TYPE.getKey()); + return new LDSigningService(session, keyId, proofType); + } + + @Override + public String getHelpText() { + return HELP_TEXT; + } + + @Override + public List getConfigProperties() { + return VCSigningServiceProviderFactory.configurationBuilder() + .property(SigningProperties.PROOF_TYPE.asConfigProperty()) + .build(); + } + + @Override + public String getId() { + return SUPPORTED_FORMAT.toString(); + } + + @Override + public void validateSpecificConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model) throws ComponentValidationException { + ConfigurationValidationHelper.check(model) + .checkRequired(SigningProperties.PROOF_TYPE.asConfigProperty()); + } + + @Override + public Format supportedFormat() { + return SUPPORTED_FORMAT; + } + +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningService.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningService.java new file mode 100644 index 0000000000..f06c0329b9 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningService.java @@ -0,0 +1,42 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.models.KeycloakSession; +import org.keycloak.protocol.oid4vc.model.VerifiableCredential; + +/** + * {@link VerifiableCredentialsSigningService} implementing the SD_JWT_VC format. It returns a String, containing + * the signed SD-JWT + *

+ * {@see https://drafts.oauth.net/oauth-sd-jwt-vc/draft-ietf-oauth-sd-jwt-vc.html} + * {@see https://www.ietf.org/archive/id/draft-fett-oauth-selective-disclosure-jwt-02.html} + * + * @author Stefan Wiedemann + */ +public class SdJwtSigningService extends SigningService { + + public SdJwtSigningService(KeycloakSession keycloakSession, String keyId, String algorithmType) { + super(keycloakSession, keyId, algorithmType); + } + + @Override + public String signCredential(VerifiableCredential verifiableCredential) { + throw new UnsupportedOperationException("SD-JWT Signing is not yet supported."); + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningServiceProviderFactory.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningServiceProviderFactory.java new file mode 100644 index 0000000000..e8b9874c19 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SdJwtSigningServiceProviderFactory.java @@ -0,0 +1,78 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.common.util.Time; +import org.keycloak.component.ComponentModel; +import org.keycloak.component.ComponentValidationException; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.protocol.oid4vc.model.Format; +import org.keycloak.provider.ConfigurationValidationHelper; +import org.keycloak.provider.ProviderConfigProperty; + +import java.util.List; + +/** + * Provider Factory to create {@link SdJwtSigningService}s + * + * @author Stefan Wiedemann + */ +public class SdJwtSigningServiceProviderFactory implements VCSigningServiceProviderFactory { + + public static final Format SUPPORTED_FORMAT = Format.SD_JWT_VC; + private static final String HELP_TEXT = "Issues SD-JWT-VCs following the specification of https://drafts.oauth.net/oauth-sd-jwt-vc/draft-ietf-oauth-sd-jwt-vc.html."; + + @Override + public VerifiableCredentialsSigningService create(KeycloakSession session, ComponentModel model) { + String keyId = model.get(SigningProperties.KEY_ID.getKey()); + String algorithmType = model.get(SigningProperties.ALGORITHM_TYPE.getKey()); + + return new SdJwtSigningService(session, keyId, algorithmType); + } + + @Override + public String getHelpText() { + return HELP_TEXT; + } + + @Override + public List getConfigProperties() { + return VCSigningServiceProviderFactory.configurationBuilder() + .property(SigningProperties.ALGORITHM_TYPE.asConfigProperty()) + .property(SigningProperties.DECOYS.asConfigProperty()) + .build(); + } + + @Override + public String getId() { + return SUPPORTED_FORMAT.toString(); + } + + @Override + public void validateSpecificConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model) throws ComponentValidationException { + ConfigurationValidationHelper.check(model) + .checkRequired(SigningProperties.ALGORITHM_TYPE.asConfigProperty()) + .checkInt(SigningProperties.DECOYS.asConfigProperty(), true); + } + + @Override + public Format supportedFormat() { + return SUPPORTED_FORMAT; + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningProperties.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningProperties.java new file mode 100644 index 0000000000..418e861164 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningProperties.java @@ -0,0 +1,58 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.crypto.Algorithm; +import org.keycloak.provider.ProviderConfigProperty; + +/** + * Properties for configuring the {@link VerifiableCredentialsSigningService}'s + * + * @author Stefan Wiedemann + */ +public enum SigningProperties { + + ISSUER_DID("issuerDid", "Did of the issuer.", "Provide the DID of the issuer. Needs to match the provided key material.", ProviderConfigProperty.STRING_TYPE, null), + KEY_ID("keyId", "Id of the signing key.", "The id of the key to be used for signing credentials. The key needs to be provided as a realm key.", ProviderConfigProperty.STRING_TYPE, null), + PROOF_TYPE("proofType", "Type of the LD-Proof.", "The type of LD-Proofs to be created. Needs to fit the provided signing key.", ProviderConfigProperty.STRING_TYPE, null), + ALGORITHM_TYPE("algorithmType", "Type of the signing algorithm.", "The type of the algorithm to be used for signing. Needs to fit the provided signing key.", ProviderConfigProperty.STRING_TYPE, Algorithm.RS256), + DECOYS("decoys", "Number of decoys to be added.", "The number of decoys to be added to the SD-JWT.", ProviderConfigProperty.STRING_TYPE, 0); + + private final String key; + private final String label; + private final String helpText; + private final String type; + private final Object defaultValue; + + SigningProperties(String key, String label, String helpText, String type, Object defaultValue) { + this.key = key; + this.label = label; + this.helpText = helpText; + this.type = type; + this.defaultValue = defaultValue; + } + + + public ProviderConfigProperty asConfigProperty() { + return new ProviderConfigProperty(key, label, helpText, type, defaultValue); + } + + public String getKey() { + return key; + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningService.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningService.java new file mode 100644 index 0000000000..7a1b5da3c1 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningService.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.crypto.KeyUse; +import org.keycloak.crypto.KeyWrapper; +import org.keycloak.models.KeycloakSession; + +/** + * Abstract base class to provide the Signing Services common functionality + * + * @author Stefan Wiedemann + */ +public abstract class SigningService implements VerifiableCredentialsSigningService { + + protected final KeycloakSession keycloakSession; + protected final String keyId; + + // values of the type field are defined by the implementing service. Could f.e. the security suite for ldp_vc or the algorithm to be used for jwt_vc + protected final String type; + + protected SigningService(KeycloakSession keycloakSession, String keyId, String type) { + this.keycloakSession = keycloakSession; + this.keyId = keyId; + this.type = type; + } + + protected KeyWrapper getKey(String kid, String algorithm) { + return keycloakSession.keys().getKey(keycloakSession.getContext().getRealm(), kid, KeyUse.SIG, algorithm); + } + + @Override + public void close() { + // no-op + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningServiceException.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningServiceException.java new file mode 100644 index 0000000000..765698b7e6 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/SigningServiceException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +/** + * Exception to be thrown if credentials signing does fail + * + * @author Stefan Wiedemann + */ +public class SigningServiceException extends RuntimeException { + + public SigningServiceException(String message) { + super(message); + } + + public SigningServiceException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceProviderFactory.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceProviderFactory.java new file mode 100644 index 0000000000..6c26413961 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceProviderFactory.java @@ -0,0 +1,90 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.Config; +import org.keycloak.common.Profile; +import org.keycloak.component.ComponentFactory; +import org.keycloak.component.ComponentModel; +import org.keycloak.component.ComponentValidationException; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.RealmModel; +import org.keycloak.protocol.oid4vc.model.Format; +import org.keycloak.provider.ConfigurationValidationHelper; +import org.keycloak.provider.EnvironmentDependentProviderFactory; +import org.keycloak.provider.ProviderConfigurationBuilder; + +import java.time.Clock; + +/** + * Provider Factory to create {@link VerifiableCredentialsSigningService}s + * + * @author Stefan Wiedemann + */ +public interface VCSigningServiceProviderFactory extends ComponentFactory, EnvironmentDependentProviderFactory { + public static ProviderConfigurationBuilder configurationBuilder() { + return ProviderConfigurationBuilder.create() + .property(SigningProperties.KEY_ID.asConfigProperty()); + } + + @Override + default void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model) throws ComponentValidationException { + ConfigurationValidationHelper.check(model) + .checkRequired(SigningProperties.KEY_ID.asConfigProperty()); + validateSpecificConfiguration(session, realm, model); + } + + + @Override + default void close() { + // no-op + } + + @Override + default void init(Config.Scope config) { + // no-op + } + + @Override + default void postInit(KeycloakSessionFactory factory) { + // no-op + } + + @Override + default boolean isSupported(Config.Scope config) { + return Profile.isFeatureEnabled(Profile.Feature.OID4VC_VCI); + } + + @Override + default boolean isSupported() { + return Profile.isFeatureEnabled(Profile.Feature.OID4VC_VCI); + } + + /** + * Should validate potential implementation specific configuration of the factory. + */ + void validateSpecificConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model) throws ComponentValidationException; + + /** + * Should return the credentials format supported by the signing service. + * + * @return the format + */ + Format supportedFormat(); +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceSpi.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceSpi.java new file mode 100644 index 0000000000..3e9b87b38e --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VCSigningServiceSpi.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.provider.Provider; +import org.keycloak.provider.ProviderFactory; +import org.keycloak.provider.Spi; + +/** + * Spi implementation fo the creation of {@link VerifiableCredentialsSigningService} + * + * @author Stefan Wiedemann + */ +public class VCSigningServiceSpi implements Spi { + private static final String NAME = "vcSigningService"; + + @Override + public boolean isInternal() { + return true; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public Class getProviderClass() { + return VerifiableCredentialsSigningService.class; + } + + @Override + public Class getProviderFactoryClass() { + return VCSigningServiceProviderFactory.class; + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VerifiableCredentialsSigningService.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VerifiableCredentialsSigningService.java new file mode 100644 index 0000000000..d142dc3f83 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/VerifiableCredentialsSigningService.java @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.issuance.signing; + +import org.keycloak.protocol.oid4vc.model.VerifiableCredential; +import org.keycloak.provider.Provider; + +/** + * Interface to be used for signing verifiable credentials. + * + * @author Stefan Wiedemann + */ +public interface VerifiableCredentialsSigningService extends Provider { + /** + * Takes a verifiable credential and signs it according to the implementation. + * Depending on the type of the SigningService, it will return a signed representation of the credential + * + * @param verifiableCredential the credential to sign + * @return a signed representation + */ + T signCredential(VerifiableCredential verifiableCredential); +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/model/CredentialSubject.java b/services/src/main/java/org/keycloak/protocol/oid4vc/model/CredentialSubject.java new file mode 100644 index 0000000000..a6049bf586 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/model/CredentialSubject.java @@ -0,0 +1,49 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.model; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.HashMap; +import java.util.Map; + +/** + * Pojo to represent a CredentialSubject for internal handling + * + * @author Stefan Wiedemann + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CredentialSubject { + + + @JsonIgnore + private Map claims = new HashMap<>(); + + @JsonAnyGetter + public Map getClaims() { + return claims; + } + + @JsonAnySetter + public void setClaims(String name, Object claim) { + claims.put(name, claim); + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/model/Format.java b/services/src/main/java/org/keycloak/protocol/oid4vc/model/Format.java new file mode 100644 index 0000000000..c133607950 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/model/Format.java @@ -0,0 +1,81 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Enum of supported credential formats + * + * @author Stefan Wiedemann + */ +public enum Format { + + /** + * LD-Credentials {@see https://www.w3.org/TR/vc-data-model/} + */ + LDP_VC("ldp_vc"), + + /** + * JWT-Credentials {@see https://identity.foundation/jwt-vc-presentation-profile/} + */ + JWT_VC("jwt_vc"), + + /** + * SD-JWT-Credentials {@see https://drafts.oauth.net/oauth-sd-jwt-vc/draft-ietf-oauth-sd-jwt-vc.html} + */ + SD_JWT_VC("sd-jwt_vc"); + + private String value; + + Format(String value) { + this.value = value; + } + + /** + * Convert a String into String, as specified in the + * See JAX RS 2.0 Specification, section 3.2, p. 12 + */ + public static Format fromString(String s) { + for (Format b : Format.values()) { + // using Objects.toString() to be safe if value type non-object type + // because types like 'int' etc. will be auto-boxed + if (java.util.Objects.toString(b.value).equals(s)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected string value '" + s + "'"); + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static Format fromValue(String value) { + for (Format b : Format.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } +} \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/model/VerifiableCredential.java b/services/src/main/java/org/keycloak/protocol/oid4vc/model/VerifiableCredential.java new file mode 100644 index 0000000000..aac078ecc1 --- /dev/null +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/model/VerifiableCredential.java @@ -0,0 +1,121 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.protocol.oid4vc.model; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Pojo to represent a VerifiableCredential for internal handling + * + * @author Stefan Wiedemann + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class VerifiableCredential { + + @JsonProperty("@context") + private List context; + private List type = new ArrayList<>(); + private URI issuer; + private Date issuanceDate; + private URI id; + private Date expirationDate; + private CredentialSubject credentialSubject = new CredentialSubject(); + @JsonIgnore + private Map additionalProperties = new HashMap<>(); + + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperties(String name, Object property) { + additionalProperties.put(name, property); + } + + public List getContext() { + return context; + } + + public void setContext(List context) { + this.context = context; + } + + public List getType() { + return type; + } + + public void setType(List type) { + this.type = type; + } + + public void addType(String type) { + this.type.add(type); + } + + public URI getIssuer() { + return issuer; + } + + public void setIssuer(URI issuer) { + this.issuer = issuer; + } + + public Date getIssuanceDate() { + return issuanceDate; + } + + public void setIssuanceDate(Date issuanceDate) { + this.issuanceDate = issuanceDate; + } + + public Date getExpirationDate() { + return expirationDate; + } + + public void setExpirationDate(Date expirationDate) { + this.expirationDate = expirationDate; + } + + public CredentialSubject getCredentialSubject() { + return credentialSubject; + } + + public void setCredentialSubject(CredentialSubject credentialSubject) { + this.credentialSubject = credentialSubject; + } + + public URI getId() { + return id; + } + + public void setId(URI id) { + this.id = id; + } +} \ No newline at end of file diff --git a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi index 6238b9bc2a..86b966e487 100755 --- a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -29,4 +29,5 @@ org.keycloak.protocol.oidc.grants.ciba.channel.AuthenticationChannelSpi org.keycloak.protocol.oidc.grants.ciba.resolvers.CIBALoginUserResolverSpi org.keycloak.protocol.oidc.rar.AuthorizationRequestParserSpi org.keycloak.services.resources.admin.ext.AdminRealmResourceSpi -org.keycloak.theme.freemarker.FreeMarkerSPI \ No newline at end of file +org.keycloak.theme.freemarker.FreeMarkerSPI +org.keycloak.protocol.oid4vc.issuance.signing.VCSigningServiceSpi \ No newline at end of file