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:

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:

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:

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:

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:

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:

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:

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:

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

@ -30,3 +30,4 @@ 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