Exchange Enum type of Format for String (#30875)

closes #30873

Signed-off-by: Pascal Knüppel <pascal.knueppel@governikus.de>
This commit is contained in:
Pascal Knüppel 2024-07-11 18:18:14 +02:00 committed by GitHub
parent 4970a9b729
commit 96234d42cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 40 additions and 75 deletions

View file

@ -99,7 +99,7 @@ public class OID4VCLoginProtocolFactory implements LoginProtocolFactory, OID4VCE
return builtins;
}
private void addServiceFromComponent(Map<Format, VerifiableCredentialsSigningService> signingServices, KeycloakSession keycloakSession, ComponentModel componentModel) {
private void addServiceFromComponent(Map<String, VerifiableCredentialsSigningService> signingServices, KeycloakSession keycloakSession, ComponentModel componentModel) {
ProviderFactory<VerifiableCredentialsSigningService> factory = keycloakSession
.getKeycloakSessionFactory()
.getProviderFactory(VerifiableCredentialsSigningService.class, componentModel.getProviderId());
@ -114,7 +114,7 @@ public class OID4VCLoginProtocolFactory implements LoginProtocolFactory, OID4VCE
@Override
public Object createProtocolEndpoint(KeycloakSession keycloakSession, EventBuilder event) {
Map<Format, VerifiableCredentialsSigningService> signingServices = new EnumMap<>(Format.class);
Map<String, VerifiableCredentialsSigningService> signingServices = new HashMap<>();
RealmModel realm = keycloakSession.getContext().getRealm();
realm.getComponentsStream(realm.getId(), VerifiableCredentialsSigningService.class.getName())
.forEach(cm -> addServiceFromComponent(signingServices, keycloakSession, cm));
@ -170,4 +170,4 @@ public class OID4VCLoginProtocolFactory implements LoginProtocolFactory, OID4VCE
return PROTOCOL_ID;
}
}
}

View file

@ -90,6 +90,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import static org.keycloak.protocol.oid4vc.model.Format.JWT_VC;
import static org.keycloak.protocol.oid4vc.model.Format.LDP_VC;
import static org.keycloak.protocol.oid4vc.model.Format.SD_JWT_VC;
/**
* Provides the (REST-)endpoints required for the OID4VCI protocol.
* <p>
@ -115,13 +119,13 @@ public class OID4VCIssuerEndpoint {
// lifespan of the preAuthorizedCodes in seconds
private final int preAuthorizedCodeLifeSpan;
private final Map<Format, VerifiableCredentialsSigningService> signingServices;
private final Map<String, VerifiableCredentialsSigningService> signingServices;
private final boolean isIgnoreScopeCheck;
public OID4VCIssuerEndpoint(KeycloakSession session,
String issuerDid,
Map<Format, VerifiableCredentialsSigningService> signingServices,
Map<String, VerifiableCredentialsSigningService> signingServices,
AppAuthManager.BearerTokenAuthenticator authenticator,
ObjectMapper objectMapper, TimeProvider timeProvider, int preAuthorizedCodeLifeSpan) {
this.session = session;
@ -136,7 +140,7 @@ public class OID4VCIssuerEndpoint {
public OID4VCIssuerEndpoint(KeycloakSession session,
String issuerDid,
Map<Format, VerifiableCredentialsSigningService> signingServices,
Map<String, VerifiableCredentialsSigningService> signingServices,
AppAuthManager.BearerTokenAuthenticator authenticator,
ObjectMapper objectMapper, TimeProvider timeProvider, int preAuthorizedCodeLifeSpan,
boolean isIgnoreScopeCheck) {
@ -168,7 +172,7 @@ public class OID4VCIssuerEndpoint {
throw new BadRequestException(getErrorResponse(ErrorType.INVALID_CREDENTIAL_REQUEST));
}
SupportedCredentialConfiguration supportedCredentialConfiguration = credentialsMap.get(vcId);
Format format = supportedCredentialConfiguration.getFormat();
String format = supportedCredentialConfiguration.getFormat();
// check that the user is allowed to get such credential
if (getClientsOfType(supportedCredentialConfiguration.getScope(), format).isEmpty()) {
@ -303,7 +307,7 @@ public class OID4VCIssuerEndpoint {
checkScope(credentialRequestVO);
}
Format requestedFormat = credentialRequestVO.getFormat();
String requestedFormat = credentialRequestVO.getFormat();
String requestedCredential = credentialRequestVO.getCredentialIdentifier();
SupportedCredentialConfiguration supportedCredentialConfiguration = Optional
@ -372,7 +376,7 @@ public class OID4VCIssuerEndpoint {
* @param format format of the credential to be created
* @return the signed credential
*/
private Object getCredential(UserSessionModel userSessionModel, String vcType, Format format) {
private Object getCredential(UserSessionModel userSessionModel, String vcType, String format) {
List<OID4VCClient> clients = getClientsOfType(vcType, format);
@ -424,7 +428,7 @@ public class OID4VCIssuerEndpoint {
}
// Return all {@link OID4VCClient}s that support the given type and format
private List<OID4VCClient> getClientsOfType(String vcType, Format format) {
private List<OID4VCClient> getClientsOfType(String vcType, String format) {
LOGGER.debugf("Retrieve all clients of type %s, supporting format %s", vcType, format.toString());
if (Optional.ofNullable(vcType).filter(type -> !type.isEmpty()).isEmpty()) {

View file

@ -74,7 +74,7 @@ public class OID4VCIssuerWellKnownProvider implements WellKnownProvider {
public static Map<String, SupportedCredentialConfiguration> getSupportedCredentials(KeycloakSession keycloakSession) {
RealmModel realm = keycloakSession.getContext().getRealm();
List<Format> supportedFormats = realm.getComponentsStream(realm.getId(), VerifiableCredentialsSigningService.class.getName())
List<String> supportedFormats = realm.getComponentsStream(realm.getId(), VerifiableCredentialsSigningService.class.getName())
.map(cm ->
keycloakSession
.getKeycloakSessionFactory()
@ -115,4 +115,4 @@ public class OID4VCIssuerWellKnownProvider implements WellKnownProvider {
public static String getCredentialsEndpoint(KeycloakContext context) {
return getIssuer(context) + "/protocol/" + OID4VCLoginProtocolFactory.PROTOCOL_ID + "/" + OID4VCIssuerEndpoint.CREDENTIAL_PATH;
}
}
}

View file

@ -38,7 +38,7 @@ import java.util.Optional;
*/
public class JwtSigningServiceProviderFactory implements VCSigningServiceProviderFactory {
public static final Format SUPPORTED_FORMAT = Format.JWT_VC;
public static final String 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
@ -83,7 +83,7 @@ public class JwtSigningServiceProviderFactory implements VCSigningServiceProvide
}
@Override
public Format supportedFormat() {
public String supportedFormat() {
return SUPPORTED_FORMAT;
}
}
}

View file

@ -36,7 +36,7 @@ import java.util.Optional;
* @author <a href="https://github.com/wistefan">Stefan Wiedemann</a>
*/
public class LDSigningServiceProviderFactory implements VCSigningServiceProviderFactory {
public static final Format SUPPORTED_FORMAT = Format.LDP_VC;
public static final String 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/";
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@ -77,8 +77,8 @@ public class LDSigningServiceProviderFactory implements VCSigningServiceProvider
}
@Override
public Format supportedFormat() {
public String supportedFormat() {
return SUPPORTED_FORMAT;
}
}
}

View file

@ -39,7 +39,7 @@ import java.util.Optional;
*/
public class SdJwtSigningServiceProviderFactory implements VCSigningServiceProviderFactory {
public static final Format SUPPORTED_FORMAT = Format.SD_JWT_VC;
public static final String 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
@ -97,7 +97,7 @@ public class SdJwtSigningServiceProviderFactory implements VCSigningServiceProvi
}
@Override
public Format supportedFormat() {
public String supportedFormat() {
return SUPPORTED_FORMAT;
}
}
}

View file

@ -85,5 +85,5 @@ public interface VCSigningServiceProviderFactory extends ComponentFactory<Verifi
*
* @return the format
*/
Format supportedFormat();
}
String supportedFormat();
}

View file

@ -29,18 +29,18 @@ import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CredentialRequest {
private Format format;
private String format;
@JsonProperty("credential_identifier")
private String credentialIdentifier;
private Proof proof;
public Format getFormat() {
public String getFormat() {
return format;
}
public CredentialRequest setFormat(Format format) {
public CredentialRequest setFormat(String format) {
this.format = format;
return this;
}
@ -62,4 +62,4 @@ public class CredentialRequest {
this.proof = proof;
return this;
}
}
}

View file

@ -17,65 +17,26 @@
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 {
public class Format {
/**
* LD-Credentials {@see https://www.w3.org/TR/vc-data-model/}
*/
LDP_VC("ldp_vc"),
public static final String LDP_VC = "ldp_vc";
/**
* JWT-Credentials {@see https://identity.foundation/jwt-vc-presentation-profile/}
*/
JWT_VC("jwt_vc"),
public static final String 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("vc+sd-jwt");
public static final String SD_JWT_VC = "vc+sd-jwt";
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

@ -59,7 +59,7 @@ public class SupportedCredentialConfiguration {
private String id;
@JsonProperty(FORMAT_KEY)
private Format format;
private String format;
@JsonProperty(SCOPE_KEY)
private String scope;
@ -85,11 +85,11 @@ public class SupportedCredentialConfiguration {
@JsonProperty(CLAIMS_KEY)
private Claims claims;
public Format getFormat() {
public String getFormat() {
return format;
}
public SupportedCredentialConfiguration setFormat(Format format) {
public SupportedCredentialConfiguration setFormat(String format) {
this.format = format;
return this;
}
@ -205,7 +205,7 @@ public class SupportedCredentialConfiguration {
public static SupportedCredentialConfiguration fromDotNotation(String credentialId, Map<String, String> dotNotated) {
SupportedCredentialConfiguration supportedCredentialConfiguration = new SupportedCredentialConfiguration().setId(credentialId);
Optional.ofNullable(dotNotated.get(credentialId + DOT_SEPARATOR + FORMAT_KEY)).map(Format::fromString).ifPresent(supportedCredentialConfiguration::setFormat);
Optional.ofNullable(dotNotated.get(credentialId + DOT_SEPARATOR + FORMAT_KEY)).ifPresent(supportedCredentialConfiguration::setFormat);
Optional.ofNullable(dotNotated.get(credentialId + DOT_SEPARATOR + VERIFIABLE_CREDENTIAL_TYPE_KEY)).ifPresent(supportedCredentialConfiguration::setVct);
Optional.ofNullable(dotNotated.get(credentialId + DOT_SEPARATOR + SCOPE_KEY)).ifPresent(supportedCredentialConfiguration::setScope);
Optional.ofNullable(dotNotated.get(credentialId + DOT_SEPARATOR + CRYPTOGRAPHIC_BINDING_METHODS_SUPPORTED_KEY))