Skip to content

Commit

Permalink
feat: make CredentialService URL configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
paullatzelsperger committed Nov 21, 2023
1 parent c609610 commit 36caf8e
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public class IdentityAndTrustExtension implements ServiceExtension {
@Setting(value = "DID of this connector", required = true)
public static final String ISSUER_DID_PROPERTY = "edc.iam.issuer.id";

@Setting(value = "URL of the CredentialService used to present credentials", required = true)
public static final String CREDENTIALSERVICE_URL_PROPERTY = "edc.iam.credentialservice.url";

@Inject
private SecureTokenService secureTokenService;

Expand Down Expand Up @@ -130,7 +133,8 @@ public JwtVerifier getJwtVerifier() {
@Provider
public CredentialServiceClient createClient(ServiceExtensionContext context) {
return new DefaultCredentialServiceClient(httpClient, Json.createBuilderFactory(Map.of()),
typeManager.getMapper(JSON_LD), typeTransformerRegistry, jsonLd, context.getMonitor());
typeManager.getMapper(JSON_LD), typeTransformerRegistry, jsonLd, context.getMonitor(),
context.getConfig().getString(CREDENTIALSERVICE_URL_PROPERTY));
}

private String getOwnDid(ServiceExtensionContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,20 @@ public class DefaultCredentialServiceClient implements CredentialServiceClient {
private final TypeTransformerRegistry transformerRegistry;
private final JsonLd jsonLd;
private final Monitor monitor;
private final String credentialServiceUrl;

public DefaultCredentialServiceClient(EdcHttpClient httpClient, JsonBuilderFactory jsonFactory, ObjectMapper jsonLdMapper, TypeTransformerRegistry transformerRegistry, JsonLd jsonLd, Monitor monitor) {
public DefaultCredentialServiceClient(EdcHttpClient httpClient, JsonBuilderFactory jsonFactory, ObjectMapper jsonLdMapper, TypeTransformerRegistry transformerRegistry, JsonLd jsonLd, Monitor monitor, String credentialServiceUrl) {
this.httpClient = httpClient;
this.jsonFactory = jsonFactory;
this.objectMapper = jsonLdMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
this.transformerRegistry = transformerRegistry;
this.jsonLd = jsonLd;
this.monitor = monitor;
this.credentialServiceUrl = credentialServiceUrl;
}

@Override
public Result<List<VerifiablePresentationContainer>> requestPresentation(String credentialServiceUrl, String selfIssuedTokenJwt, List<String> scopes) {
public Result<List<VerifiablePresentationContainer>> requestPresentation(String selfIssuedTokenJwt, List<String> scopes) {
var query = createPresentationQuery(scopes);

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ void setup() {
var jsonLdMock = mock(JsonLd.class);
when(jsonLdMock.expand(any())).thenAnswer(a -> success(a.getArgument(0)));
client = new DefaultCredentialServiceClient(httpClientMock, Json.createBuilderFactory(Map.of()),
createObjectMapper(), registry, jsonLdMock, mock());
createObjectMapper(), registry, jsonLdMock, mock(), CS_URL);
}

@Test
Expand All @@ -70,7 +70,7 @@ void requestPresentation_singleLdpVp() throws IOException {
when(httpClientMock.execute(any()))
.thenReturn(response(200, getResourceFileContentAsString("single_ldp-vp.json")));

var result = client.requestPresentation(CS_URL, "foo", List.of());
var result = client.requestPresentation("foo", List.of());
assertThat(result.succeeded()).isTrue();
assertThat(result.getContent()).hasSize(1).allMatch(vpc -> vpc.format() == CredentialFormat.JSON_LD);
}
Expand All @@ -81,7 +81,7 @@ void requestPresentation_singleJwtVp() throws IOException {
when(httpClientMock.execute(any()))
.thenReturn(response(200, getResourceFileContentAsString("single_jwt-vp.json")));

var result = client.requestPresentation(CS_URL, "foo", List.of());
var result = client.requestPresentation("foo", List.of());
assertThat(result.succeeded()).isTrue();
assertThat(result.getContent()).hasSize(1).allMatch(vpc -> vpc.format() == CredentialFormat.JWT);
}
Expand All @@ -92,7 +92,7 @@ void requestPresentationLdp_multipleVp_mixed() throws IOException {
when(httpClientMock.execute(any()))
.thenReturn(response(200, getResourceFileContentAsString("multiple_vp-token_mixed.json")));

var result = client.requestPresentation(CS_URL, "foo", List.of());
var result = client.requestPresentation("foo", List.of());
assertThat(result.succeeded()).isTrue();
assertThat(result.getContent()).hasSize(2)
.anySatisfy(vp -> assertThat(vp.format()).isEqualTo(CredentialFormat.JSON_LD))
Expand All @@ -105,7 +105,7 @@ void requestPresentation_mulipleVp_onlyLdp() throws IOException {
when(httpClientMock.execute(any()))
.thenReturn(response(200, getResourceFileContentAsString("multiple_vp-token_ldp.json")));

var result = client.requestPresentation(CS_URL, "foo", List.of());
var result = client.requestPresentation("foo", List.of());
assertThat(result.succeeded()).isTrue();
assertThat(result.getContent()).hasSize(2)
.allSatisfy(vp -> assertThat(vp.format()).isEqualTo(CredentialFormat.JSON_LD));
Expand All @@ -117,7 +117,7 @@ void requestPresentation_mulipleVp_onlyJwt() throws IOException {
when(httpClientMock.execute(any()))
.thenReturn(response(200, getResourceFileContentAsString("multiple_vp-token_jwt.json")));

var result = client.requestPresentation(CS_URL, "foo", List.of());
var result = client.requestPresentation("foo", List.of());
assertThat(result.succeeded()).isTrue();
assertThat(result.getContent()).hasSize(2)
.allSatisfy(vp -> assertThat(vp.format()).isEqualTo(CredentialFormat.JWT));
Expand All @@ -129,7 +129,7 @@ void requestPresentation_csReturnsError(int httpCode) throws IOException {
when(httpClientMock.execute(any()))
.thenReturn(response(httpCode, "Test failure"));

var res = client.requestPresentation(CS_URL, "foo", List.of());
var res = client.requestPresentation("foo", List.of());
assertThat(res.failed()).isTrue();
assertThat(res.getFailureDetail()).isEqualTo("Presentation Query failed: HTTP %s, message: Test failure".formatted(httpCode));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public Result<ClaimToken> verifyJwtToken(TokenRepresentation tokenRepresentation
return issuerResult.mapTo();
}

var vpResponse = credentialServiceClient.requestPresentation(null, null, null);
var vpResponse = credentialServiceClient.requestPresentation(siTokenString, scopes);

if (vpResponse.failed()) {
return vpResponse.mapTo();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,19 @@ class VerifyJwtToken {

@Test
void presentationRequestFails() {
when(mockedClient.requestPresentation(any(), any(), any())).thenReturn(failure("test-failure"));
when(mockedClient.requestPresentation(any(), any())).thenReturn(failure("test-failure"));
var token = createJwt();
var result = service.verifyJwtToken(token, "test-audience");
assertThat(result).isFailed().detail().isEqualTo("test-failure");
verifyNoInteractions(mockedVerifier);
verify(mockedClient).requestPresentation(any(), any(), any());
verify(mockedClient).requestPresentation(any(), any());

}

@Test
void cryptographicError() {
when(mockedVerifier.verifyPresentation(any())).thenReturn(Result.failure("Cryptographic error"));
when(mockedClient.requestPresentation(any(), any(), any())).thenReturn(success(List.of(createPresentationContainer())));
when(mockedClient.requestPresentation(any(), any())).thenReturn(success(List.of(createPresentationContainer())));
var token = createJwt();
var result = service.verifyJwtToken(token, "test-audience");
assertThat(result).isFailed().detail().isEqualTo("Cryptographic error");
Expand All @@ -163,7 +163,7 @@ void notYetValid() {
.build();
var vpContainer = new VerifiablePresentationContainer("test-vp", CredentialFormat.JSON_LD, presentation);
when(mockedVerifier.verifyPresentation(any())).thenReturn(success());
when(mockedClient.requestPresentation(any(), any(), any())).thenReturn(success(List.of(vpContainer)));
when(mockedClient.requestPresentation(any(), any())).thenReturn(success(List.of(vpContainer)));
var token = createJwt(CONSUMER_DID, EXPECTED_OWN_DID);
var result = service.verifyJwtToken(token, "test-audience");
assertThat(result).isFailed().messages()
Expand All @@ -184,7 +184,7 @@ void oneInvalidSubjectId() {
.build();
var vpContainer = new VerifiablePresentationContainer("test-vp", CredentialFormat.JSON_LD, presentation);
when(mockedVerifier.verifyPresentation(any())).thenReturn(success());
when(mockedClient.requestPresentation(any(), any(), any())).thenReturn(success(List.of(vpContainer)));
when(mockedClient.requestPresentation(any(), any())).thenReturn(success(List.of(vpContainer)));
var token = createJwt(CONSUMER_DID, EXPECTED_OWN_DID);
var result = service.verifyJwtToken(token, "test-audience");
assertThat(result).isFailed().messages()
Expand All @@ -209,7 +209,7 @@ void credentialHasInvalidIssuer_issuerIsUrl() {
.build();
var vpContainer = new VerifiablePresentationContainer("test-vp", CredentialFormat.JSON_LD, presentation);
when(mockedVerifier.verifyPresentation(any())).thenReturn(success());
when(mockedClient.requestPresentation(any(), any(), any())).thenReturn(success(List.of(vpContainer)));
when(mockedClient.requestPresentation(any(), any())).thenReturn(success(List.of(vpContainer)));
var token = createJwt(consumerDid, EXPECTED_OWN_DID);
var result = service.verifyJwtToken(token, "test-audience");
assertThat(result).isFailed().messages()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ public interface CredentialServiceClient {
* <p>
* Note that sending a DIF Presentation Definition is not supported yet and will result in a 5xx error.
*
* @param csUrl The URL of the CredentialService, from which the presentation is to be requested.
* @param siTokenJwt A Self-Issued ID token in JWT format, that contains the access_token
* @param scopes A list of strings, each containing a <a href="https://github.com/eclipse-tractusx/identity-trust/blob/main/specifications/M1/verifiable.presentation.protocol.md#31-access-scopes">scope definition</a>
* @return A list of {@link VerifiablePresentationContainer} objects, or a failure if the request was unsuccessful.
*/
Result<List<VerifiablePresentationContainer>> requestPresentation(String csUrl, String siTokenJwt, List<String> scopes);
Result<List<VerifiablePresentationContainer>> requestPresentation(String siTokenJwt, List<String> scopes);

//todo: add write api?
}

0 comments on commit 36caf8e

Please sign in to comment.