Create SPI and Provider for Verifiable Credentials Signing #25937 (#26263)

* implement oid4vci service interfaces

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* add oid4vc to the disabled features test

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* fix test and add doc

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* add the new preview feature

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* add class-level doc

remove wildcard imports

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* add license headers

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* fix year

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* fix teste

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* two additional test fixes

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* make the feature experimental

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* remove clock

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* remove usage of var

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

* fix tests

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>

---------

Signed-off-by: Stefan Wiedemann <wistefan@googlemail.com>
This commit is contained in:
Stefan Wiedemann 2024-01-25 07:36:28 +01:00 committed by GitHub
parent cbfdae5e75
commit efa6ddc41e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1052 additions and 87 deletions

View file

@ -111,6 +111,8 @@ public class Profile {
HOSTNAME_V1("Hostname Options V1", Type.DEFAULT), HOSTNAME_V1("Hostname Options V1", Type.DEFAULT),
//HOSTNAME_V2("Hostname Options V2", Type.DEFAULT, 2), //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), DECLARATIVE_UI("declarative ui spi", Type.EXPERIMENTAL),
; ;

View file

@ -86,7 +86,8 @@ public class ProfileTest {
Profile.Feature.UPDATE_EMAIL, Profile.Feature.UPDATE_EMAIL,
Profile.Feature.LINKEDIN_OAUTH, Profile.Feature.LINKEDIN_OAUTH,
Profile.Feature.OFFLINE_SESSION_PRELOADING, 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) // KERBEROS can be disabled (i.e. FIPS mode disables SunJGSS provider)

View file

@ -67,19 +67,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
HTTP(S): HTTP(S):

View file

@ -64,20 +64,19 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api[:v1], --features <feature> 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], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1],
admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1],
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[:
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: scripts[:v1], step-up-authentication[:v1], token-exchange[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn transient-users[:v1], update-email[:v1], web-authn[:v1].
[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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, step-up-authentication, token-exchange, transient-users, update-email,
web-authn. web-authn.

View file

@ -62,19 +62,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Config: Config:
@ -156,4 +156,4 @@ Export:
--users-per-file <number> --users-per-file <number>
Set the number of users per file. It is used only if 'users' is set to 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 'different_files'. Increasing this number leads to exponentially increasing
export times. Default: 50. export times. Default: 50.

View file

@ -62,19 +62,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Config: Config:
@ -156,4 +156,4 @@ Export:
--users-per-file <number> --users-per-file <number>
Set the number of users per file. It is used only if 'users' is set to 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 'different_files'. Increasing this number leads to exponentially increasing
export times. Default: 50. export times. Default: 50.

View file

@ -62,19 +62,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Config: Config:
@ -150,4 +150,4 @@ Import:
--file <file> Set the path to a file that will be read. --file <file> Set the path to a file that will be read.
--override <true|false> --override <true|false>
Set if existing data should be overwritten. If set to false, data will be Set if existing data should be overwritten. If set to false, data will be
ignored. Default: true. ignored. Default: true.

View file

@ -62,19 +62,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Config: Config:
@ -150,4 +150,4 @@ Import:
--file <file> Set the path to a file that will be read. --file <file> Set the path to a file that will be read.
--override <true|false> --override <true|false>
Set if existing data should be overwritten. If set to false, data will be Set if existing data should be overwritten. If set to false, data will be
ignored. Default: true. ignored. Default: true.

View file

@ -92,19 +92,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Hostname: Hostname:
@ -293,4 +293,4 @@ Security:
Do NOT start the server using this command when deploying to production. 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 Use 'kc.sh start-dev --help-all' to list all available options, including build
options. options.

View file

@ -102,7 +102,7 @@ Feature:
authorization, ciba, client-policies, client-secret-rotation, client-types, authorization, ciba, client-policies, client-secret-rotation, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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, step-up-authentication, token-exchange, transient-users, update-email,
web-authn. web-authn.

View file

@ -92,19 +92,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Hostname: Hostname:
@ -293,4 +293,4 @@ Security:
Do NOT start the server using this command when deploying to production. 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 Use 'kc.sh start-dev --help-all' to list all available options, including build
options. options.

View file

@ -102,7 +102,7 @@ Feature:
authorization, ciba, client-policies, client-secret-rotation, client-types, authorization, ciba, client-policies, client-secret-rotation, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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, step-up-authentication, token-exchange, transient-users, update-email,
web-authn. web-authn.

View file

@ -93,19 +93,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Hostname: Hostname:
@ -298,4 +298,4 @@ By default, this command tries to update the server configuration by running a
$ kc.sh start '--optimized' $ kc.sh start '--optimized'
By doing that, the server should start faster based on any previous By doing that, the server should start faster based on any previous
configuration you have set when manually running the 'build' command. configuration you have set when manually running the 'build' command.

View file

@ -103,7 +103,7 @@ Feature:
authorization, ciba, client-policies, client-secret-rotation, client-types, authorization, ciba, client-policies, client-secret-rotation, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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, step-up-authentication, token-exchange, transient-users, update-email,
web-authn. web-authn.

View file

@ -93,19 +93,19 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1],
device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1],
hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1], hostname[:v1], impersonation[:v1], js-adapter[:v1], kerberos[:v1],
linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[: linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1],
v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[: oid4vc-vci[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1],
v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1],
[:v1]. update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, account3, admin-api, admin-fine-grained-authz, admin2, 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, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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,
step-up-authentication, token-exchange, transient-users, update-email, scripts, step-up-authentication, token-exchange, transient-users,
web-authn. update-email, web-authn.
Hostname: Hostname:
@ -298,4 +298,4 @@ By default, this command tries to update the server configuration by running a
$ kc.sh start '--optimized' $ kc.sh start '--optimized'
By doing that, the server should start faster based on any previous By doing that, the server should start faster based on any previous
configuration you have set when manually running the 'build' command. configuration you have set when manually running the 'build' command.

View file

@ -93,7 +93,7 @@ Feature:
client-secret-rotation[:v1], client-types[:v1], declarative-ui[:v1], device-flow[: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 docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation
[:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], [: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], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1],
transient-users[:v1], update-email[:v1], web-authn[:v1]. transient-users[:v1], update-email[:v1], web-authn[:v1].
--features-disabled <feature> --features-disabled <feature>
@ -102,7 +102,7 @@ Feature:
authorization, ciba, client-policies, client-secret-rotation, client-types, authorization, ciba, client-policies, client-secret-rotation, client-types,
declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips,
impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, 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, step-up-authentication, token-exchange, transient-users, update-email,
web-authn. web-authn.

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public class VCIssuerException extends RuntimeException {
public VCIssuerException(String message) {
super(message);
}
public VCIssuerException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public class JwtSigningService extends SigningService<String> {
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.");
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
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<ProviderConfigProperty> 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;
}
}

View file

@ -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.
* <p>
* {@see https://www.w3.org/TR/vc-data-model/}
*
* @author <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public class LDSigningService extends SigningService<VerifiableCredential> {
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.");
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
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<ProviderConfigProperty> 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;
}
}

View file

@ -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
* <p>
* {@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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public class SdJwtSigningService extends SigningService<String> {
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.");
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
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<ProviderConfigProperty> 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;
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
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;
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public abstract class SigningService<T> implements VerifiableCredentialsSigningService<T> {
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
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public class SigningServiceException extends RuntimeException {
public SigningServiceException(String message) {
super(message);
}
public SigningServiceException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public interface VCSigningServiceProviderFactory extends ComponentFactory<VerifiableCredentialsSigningService, VerifiableCredentialsSigningService>, 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();
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
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<? extends Provider> getProviderClass() {
return VerifiableCredentialsSigningService.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return VCSigningServiceProviderFactory.class;
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public interface VerifiableCredentialsSigningService<T> 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);
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CredentialSubject {
@JsonIgnore
private Map<String, Object> claims = new HashMap<>();
@JsonAnyGetter
public Map<String, Object> getClaims() {
return claims;
}
@JsonAnySetter
public void setClaims(String name, Object claim) {
claims.put(name, claim);
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
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
* <a href="https://download.oracle.com/otndocs/jcp/jaxrs-2_0-fr-eval-spec/index.html">See JAX RS 2.0 Specification, section 3.2, p. 12</a>
*/
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 + "'");
}
}

View file

@ -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 <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class VerifiableCredential {
@JsonProperty("@context")
private List<String> context;
private List<String> type = new ArrayList<>();
private URI issuer;
private Date issuanceDate;
private URI id;
private Date expirationDate;
private CredentialSubject credentialSubject = new CredentialSubject();
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<>();
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperties(String name, Object property) {
additionalProperties.put(name, property);
}
public List<String> getContext() {
return context;
}
public void setContext(List<String> context) {
this.context = context;
}
public List<String> getType() {
return type;
}
public void setType(List<String> 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;
}
}

View file

@ -29,4 +29,5 @@ org.keycloak.protocol.oidc.grants.ciba.channel.AuthenticationChannelSpi
org.keycloak.protocol.oidc.grants.ciba.resolvers.CIBALoginUserResolverSpi org.keycloak.protocol.oidc.grants.ciba.resolvers.CIBALoginUserResolverSpi
org.keycloak.protocol.oidc.rar.AuthorizationRequestParserSpi org.keycloak.protocol.oidc.rar.AuthorizationRequestParserSpi
org.keycloak.services.resources.admin.ext.AdminRealmResourceSpi org.keycloak.services.resources.admin.ext.AdminRealmResourceSpi
org.keycloak.theme.freemarker.FreeMarkerSPI org.keycloak.theme.freemarker.FreeMarkerSPI
org.keycloak.protocol.oid4vc.issuance.signing.VCSigningServiceSpi