From 5a68056f2aa67851879dfdd340c4cb0daa801d07 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Mon, 27 May 2024 11:28:46 +0200 Subject: [PATCH] Fix oid4vc mappers Closes #29805 Signed-off-by: Stefan Wiedemann --- .../oid4vc/issuance/OID4VCIssuerEndpoint.java | 4 ++++ .../issuance/signing/OID4VCIssuerEndpointTest.java | 10 ++++++++-- .../oid4vc/issuance/signing/OID4VCTest.java | 13 +++++++------ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java index 4d42093fac..b1fc55c697 100644 --- a/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java @@ -373,11 +373,15 @@ public class OID4VCIssuerEndpoint { Map subjectClaims = new HashMap<>(); protocolMappers + .stream() + .filter(mapper -> mapper.isTypeSupported(vcType)) .forEach(mapper -> mapper.setClaimsForSubject(subjectClaims, userSessionModel)); subjectClaims.forEach((key, value) -> vc.getCredentialSubject().setClaims(key, value)); protocolMappers + .stream() + .filter(mapper -> mapper.isTypeSupported(vcType)) .forEach(mapper -> mapper.setClaimsForCredential(vc, userSessionModel)); LOGGER.debugf("The credential to sign is: %s", vc); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCIssuerEndpointTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCIssuerEndpointTest.java index c29721834a..efd0518fb4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCIssuerEndpointTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCIssuerEndpointTest.java @@ -76,7 +76,6 @@ import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -335,6 +334,7 @@ public class OID4VCIssuerEndpointTest extends OID4VCTest { @Test public void testRequestCredential() { String token = getBearerToken(oauth); + ObjectMapper objectMapper = new ObjectMapper(); testingClient .server(TEST_REALM_NAME) .run((session -> { @@ -349,8 +349,12 @@ public class OID4VCIssuerEndpointTest extends OID4VCTest { assertNotNull("A credential should be responded.", credentialResponse.getEntity()); CredentialResponse credentialResponseVO = OBJECT_MAPPER.convertValue(credentialResponse.getEntity(), CredentialResponse.class); JsonWebToken jsonWebToken = TokenVerifier.create((String) credentialResponseVO.getCredential(), JsonWebToken.class).getToken(); - // correct signing and contents are verified in the JwtSigningServiceTest, thus we only check that it is a JWT + assertNotNull("A valid credential string should have been responded", jsonWebToken); + assertNotNull("The credentials should be included at the vc-claim.", jsonWebToken.getOtherClaims().get("vc")); + VerifiableCredential credential = objectMapper.convertValue(jsonWebToken.getOtherClaims().get("vc"), VerifiableCredential.class); + assertTrue("The static claim should be set.", credential.getCredentialSubject().getClaims().containsKey("VerifiableCredential")); + assertFalse("Only mappers supported for the requested type should have been evaluated.", credential.getCredentialSubject().getClaims().containsKey("AnotherCredentialType")); })); } @@ -482,6 +486,8 @@ public class OID4VCIssuerEndpointTest extends OID4VCTest { assertEquals(List.of("VerifiableCredential"), credential.getType()); assertEquals(URI.create("did:web:test.org"), credential.getIssuer()); assertEquals("john@email.cz", credential.getCredentialSubject().getClaims().get("email")); + assertTrue("The static claim should be set.", credential.getCredentialSubject().getClaims().containsKey("VerifiableCredential")); + assertFalse("Only mappers supported for the requested type should have been evaluated.", credential.getCredentialSubject().getClaims().containsKey("AnotherCredentialType")); } @Override diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCTest.java index a953aeb835..3b4500cefb 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCTest.java @@ -188,7 +188,8 @@ public abstract class OID4VCTest extends AbstractTestRealmKeycloakTest { getRoleMapper(clientId), getEmailMapper(), getIdMapper(), - getStaticClaimMapper() + getStaticClaimMapper("VerifiableCredential"), + getStaticClaimMapper("AnotherCredentialType") ) ); return clientRepresentation; @@ -253,17 +254,17 @@ public abstract class OID4VCTest extends AbstractTestRealmKeycloakTest { return protocolMapperRepresentation; } - public static ProtocolMapperRepresentation getStaticClaimMapper() { + public static ProtocolMapperRepresentation getStaticClaimMapper(String supportedType) { ProtocolMapperRepresentation protocolMapperRepresentation = new ProtocolMapperRepresentation(); - protocolMapperRepresentation.setName("static-mapper"); + protocolMapperRepresentation.setName(UUID.randomUUID().toString()); protocolMapperRepresentation.setProtocol("oid4vc"); protocolMapperRepresentation.setId(UUID.randomUUID().toString()); protocolMapperRepresentation.setProtocolMapper("oid4vc-static-claim-mapper"); protocolMapperRepresentation.setConfig( Map.of( - "subjectProperty", "static", - "subjectValue", "Value", - "supportedCredentialTypes", "VerifiableCredential") + "subjectProperty", supportedType, + "staticValue", "true", + "supportedCredentialTypes", supportedType) ); return protocolMapperRepresentation; }