Skip to content

Commit

Permalink
feat: adds verification context (#3677)
Browse files Browse the repository at this point in the history
* feat: add verification context

* Update spi/common/core-spi/src/main/java/org/eclipse/edc/spi/iam/VerificationContext.java

Co-authored-by: Jim Marino <[email protected]>

* Update spi/common/core-spi/src/main/java/org/eclipse/edc/spi/iam/VerificationContext.java

Co-authored-by: Jim Marino <[email protected]>

* pr remarks

---------

Co-authored-by: Jim Marino <[email protected]>
  • Loading branch information
wolf4ood and jimmarino authored Dec 1, 2023
1 parent 94b3012 commit c756a4a
Show file tree
Hide file tree
Showing 19 changed files with 299 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.iam.VerificationContext;
import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry;
import org.eclipse.edc.spi.monitor.ConsoleMonitor;
import org.eclipse.edc.spi.protocol.ProtocolWebhook;
Expand Down Expand Up @@ -123,7 +124,7 @@ void init() {
.protocolWebhook(protocolWebhook)
.build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(token));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(token));
consumerService = new ContractNegotiationProtocolServiceImpl(consumerStore, new NoopTransactionContext(), validationService, identityService, new ContractNegotiationObservableImpl(), monitor, mock(Telemetry.class));
providerService = new ContractNegotiationProtocolServiceImpl(providerStore, new NoopTransactionContext(), validationService, identityService, new ContractNegotiationObservableImpl(), monitor, mock(Telemetry.class));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

package org.eclipse.edc.connector.service.protocol;

import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.iam.VerificationContext;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.ServiceResult;

Expand Down Expand Up @@ -45,7 +47,13 @@ public ServiceResult<ClaimToken> verifyToken(TokenRepresentation tokenRepresenta
// TODO: since we are pushing here the invocation of the IdentityService we don't know the audience here
// The audience removal will be tackle next. IdentityService that relies on this parameter would not work
// for the time being.
var result = identityService.verifyJwtToken(tokenRepresentation, null);

// TODO: policy extractors will be handled next
var verificationContext = VerificationContext.Builder.newInstance()
.policy(Policy.Builder.newInstance().build())
.build();

var result = identityService.verifyJwtToken(tokenRepresentation, verificationContext);

if (result.failed()) {
monitor.debug(() -> "Unauthorized: %s".formatted(result.getFailureDetail()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.iam.VerificationContext;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.result.ServiceFailure;
Expand All @@ -44,6 +45,7 @@
import static org.eclipse.edc.spi.result.ServiceFailure.Reason.UNAUTHORIZED;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
Expand All @@ -70,7 +72,7 @@ void getCatalog_shouldReturnCatalogWithConnectorDataServiceAndItsDataset() {
var participantAgent = createParticipantAgent();
var dataService = DataService.Builder.newInstance().build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(token));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(token));
when(dataServiceRegistry.getDataServices()).thenReturn(List.of(dataService));
when(datasetResolver.query(any(), any())).thenReturn(Stream.of(createDataset()));
when(participantAgentService.createFor(any())).thenReturn(participantAgent);
Expand All @@ -92,7 +94,7 @@ void getCatalog_shouldFail_whenTokenValidationFails() {
var message = CatalogRequestMessage.Builder.newInstance().protocol("protocol").querySpec(querySpec).build();
var tokenRepresentation = createTokenRepresentation();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.failure("unauthorized"));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.failure("unauthorized"));

var result = service.getCatalog(message, tokenRepresentation);

Expand All @@ -107,7 +109,7 @@ void getDataset_shouldReturnDataset() {
var participantAgent = createParticipantAgent();
var dataset = createDataset();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(participantAgentService.createFor(any())).thenReturn(participantAgent);
when(datasetResolver.getById(any(), any())).thenReturn(dataset);

Expand All @@ -125,7 +127,7 @@ void getDataset_shouldFail_whenDatasetIsNull() {
var tokenRepresentation = createTokenRepresentation();
var participantAgent = createParticipantAgent();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(participantAgentService.createFor(any())).thenReturn(participantAgent);
when(datasetResolver.getById(any(), any())).thenReturn(null);

Expand All @@ -139,7 +141,7 @@ void getDataset_shouldFail_whenTokenValidationFails() {
var querySpec = QuerySpec.none();
var tokenRepresentation = createTokenRepresentation();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.failure("unauthorized"));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.failure("unauthorized"));

var result = service.getDataset("datasetId", tokenRepresentation);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.iam.VerificationContext;
import org.eclipse.edc.spi.message.RemoteMessageDispatcher;
import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry;
import org.eclipse.edc.spi.protocol.ProtocolWebhook;
Expand All @@ -59,6 +60,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -97,7 +99,7 @@ void shouldDispatchEventsOnProviderContractNegotiationStateChanges(EventRouter e
AssetIndex assetIndex) {
dispatcherRegistry.register(succeedingDispatcher());

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(token));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(token));
eventRouter.register(ContractNegotiationEvent.class, eventSubscriber);
var policy = Policy.Builder.newInstance().build();
var contractDefinition = ContractDefinition.Builder.newInstance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.iam.VerificationContext;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.result.ServiceFailure;
import org.eclipse.edc.spi.result.ServiceResult;
Expand Down Expand Up @@ -71,6 +72,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
Expand Down Expand Up @@ -111,7 +113,7 @@ void notifyRequested_shouldInitiateNegotiation_whenNegotiationDoesNotExist() {
.processId("processId")
.build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease(any())).thenReturn(StoreResult.notFound("not found"));
when(validationService.validateInitialOffer(claimToken, contractOffer)).thenReturn(Result.success(validatedOffer));

Expand Down Expand Up @@ -147,7 +149,7 @@ void notifyRequested_shouldTransitionToRequested_whenNegotiationFound() {
.processId("processId")
.build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease(any())).thenReturn(StoreResult.success(negotiation));
when(validationService.validateInitialOffer(claimToken, contractOffer)).thenReturn(Result.success(validatedOffer));

Expand Down Expand Up @@ -185,7 +187,7 @@ void notifyOffered_shouldTransitionToOffered_whenNegotiationFound() {
.build();
var negotiation = createContractNegotiationRequested();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease(processId)).thenReturn(StoreResult.success(negotiation));
when(validationService.validateRequest(claimToken, negotiation)).thenReturn(Result.success());

Expand Down Expand Up @@ -213,7 +215,7 @@ void notifyAccepted_shouldTransitionToAccepted() {
.policy(Policy.Builder.newInstance().build())
.build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease("processId")).thenReturn(StoreResult.success(contractNegotiation));
when(validationService.validateRequest(eq(claimToken), any(ContractNegotiation.class))).thenReturn(Result.success());

Expand Down Expand Up @@ -241,7 +243,7 @@ void notifyAgreed_shouldTransitionToAgreed() {
.contractAgreement(contractAgreement)
.build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease("processId")).thenReturn(StoreResult.success(negotiationConsumerRequested));
when(validationService.validateConfirmed(eq(claimToken), eq(contractAgreement), any(ContractOffer.class))).thenReturn(Result.success());

Expand All @@ -268,7 +270,7 @@ void notifyVerified_shouldTransitionToVerified() {
.processId("processId")
.build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease("processId")).thenReturn(StoreResult.success(negotiation));
when(validationService.validateRequest(any(), any(ContractNegotiation.class))).thenReturn(Result.success());

Expand All @@ -293,7 +295,7 @@ void notifyFinalized_shouldTransitionToFinalized() {
var claimToken = ClaimToken.Builder.newInstance().build();
var tokenRepresentation = tokenRepresentation();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease("processId")).thenReturn(StoreResult.success(negotiation));
when(validationService.validateRequest(any(), any(ContractNegotiation.class))).thenReturn(Result.success());

Expand All @@ -318,7 +320,7 @@ void notifyTerminated_shouldTransitionToTerminated() {
var claimToken = claimToken();
var tokenRepresentation = tokenRepresentation();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease("processId")).thenReturn(StoreResult.success(negotiation));
when(validationService.validateRequest(any(), any(ContractNegotiation.class))).thenReturn(Result.success());

Expand All @@ -338,7 +340,7 @@ void findById_shouldReturnNegotiation_whenValidCounterParty() {
var tokenRepresentation = tokenRepresentation();
var negotiation = contractNegotiationBuilder().id(id).type(PROVIDER).state(VERIFIED.code()).build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findById(id)).thenReturn(negotiation);
when(validationService.validateRequest(claimToken, negotiation)).thenReturn(Result.success());

Expand All @@ -354,7 +356,7 @@ void findById_shouldReturnNotFound_whenNegotiationNotFound() {
var claimToken = claimToken();
var tokenRepresentation = tokenRepresentation();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findById(any())).thenReturn(null);

var result = service.findById("invalidId", tokenRepresentation);
Expand All @@ -370,7 +372,7 @@ void findById_shouldReturnBadRequest_whenCounterPartyUnauthorized() {
var id = "negotiationId";
var claimToken = claimToken();
var tokenRepresentation = tokenRepresentation();
when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));

var negotiation = contractNegotiationBuilder().id(id).type(PROVIDER).state(VERIFIED.code()).build();

Expand All @@ -390,7 +392,7 @@ void findById_shouldReturnBadRequest_whenCounterPartyUnauthorized() {
<M extends RemoteMessage> void notify_shouldReturnNotFound_whenNotFound(MethodCall<M> methodCall, M message) {
var claimToken = claimToken();
var tokenRepresentation = tokenRepresentation();
when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease(any())).thenReturn(StoreResult.notFound("not found"));

// currently ContractRequestMessage cannot happen on an already existing negotiation
Expand All @@ -409,7 +411,7 @@ <M extends RemoteMessage> void notify_shouldReturnBadRequest_whenValidationFails
var claimToken = claimToken();
var tokenRepresentation = tokenRepresentation();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(claimToken));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(claimToken));
when(store.findByCorrelationIdAndLease(any())).thenReturn(StoreResult.success(createContractNegotiationOffered()));
when(validationService.validateRequest(any(), any(ContractNegotiation.class))).thenReturn(Result.failure("validation error"));
when(validationService.validateInitialOffer(any(), any(ContractOffer.class))).thenReturn(Result.failure("error"));
Expand All @@ -427,7 +429,7 @@ <M extends RemoteMessage> void notify_shouldReturnBadRequest_whenValidationFails
<M extends RemoteMessage> void notify_shouldReturnBadRequest_whenTokenValidationFails(MethodCall<M> methodCall, M message) {
var tokenRepresentation = tokenRepresentation();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.failure("unauthorized"));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.failure("unauthorized"));

var result = methodCall.call(service, message, tokenRepresentation);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.iam.VerificationContext;
import org.eclipse.edc.spi.message.RemoteMessageDispatcher;
import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry;
import org.eclipse.edc.spi.protocol.ProtocolWebhook;
Expand Down Expand Up @@ -73,6 +74,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -131,8 +133,8 @@ void shouldDispatchEventsOnTransferProcessStateChanges(TransferProcessService se
var token = ClaimToken.Builder.newInstance().build();
var tokenRepresentation = TokenRepresentation.Builder.newInstance().token(UUID.randomUUID().toString()).build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), any())).thenReturn(Result.success(token));
when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(token));

var agent = mock(ParticipantAgent.class);
var agreement = mock(ContractAgreement.class);
var providerId = "ProviderId";
Expand Down
Loading

0 comments on commit c756a4a

Please sign in to comment.