Skip to content

Commit

Permalink
feat: add token handling technical specification (#3891)
Browse files Browse the repository at this point in the history
* Sdd token handling technical specification

* Change names and spaacing
  • Loading branch information
jimmarino authored Feb 22, 2024
1 parent 34c3285 commit 09f2bc7
Showing 1 changed file with 172 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# EDC Data Plane EDR Handling and Extensibility

A prerequisite for the changes described here
is [Data Plane Signaling](data-plane-signaling.md).
The signaling architecture transitions responsibility for EDR creation and data plane access token handling from Control
Plane services to the Data Plane. As a companion to that work, the refactoring effort outlined in this document adds key
features to access token handling in the Data Plane Framework (DPF). Specifically, the following will be introduced:

- Client-side management and API for Endpoint Data References (EDR). Facilities for persisting and updating EDRs
received from data providers will be implemented. The API will provide a RESTful query interface to client
applications for retrieving EDRs.
- An extension point for integrating custom authorization token handling. For example, a third-party authorization
server can be used to create and verify access tokens, or custom access logic can be introduced into the authorization
flow.

> Note that the DPF also supports OAuth client authentication flows for accessing backend data sources and sinks. That
> feature will not be affected by this refactoring.
## 1. Client-Side EDR Management

The Client EDC will expose an EDR API that provides operations to resolve EDRs as `DataAddress` types by asset ID,
contract agreement ID, and transfer process ID.

A modified version of
the [EndpointDataReferenceCache‎](spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/store/EndpointDataReferenceCache.java)
and EDR API will be upstreamed to EDC as part of that work. The `EndpointDataReferenceCache` will receive and
persist `EDRs` sent from provider control planes (e.g., when a transfer process has been `STARTED`). The EDR API is
intended to be used by client applications to resolve `EDRs` granting access to provider data endpoints.

> The API must be segmented from the rest of the management API using a separate API key or role (TBD).
## 2. Updates to the`DataAddress` Format

The format of the Data Address returned by the EDR API will be updated to align with the current DSP specifications (
backward compatibility to the existing format should be maintained by retaining the previous fields):

```json
{
"dspace:dataAddress": {
"@type": "dspace:DataAddress",
"dspace:endpointType": "https://w3id.org/idsa/v4.1/HTTP",
"dspace:endpoint": "http://example.com",
"dspace:endpointProperties": [
{
"@type": "dspace:EndpointProperty",
"dspace:name": "authorization",
"dspace:value": "token"
},
{
"@type": "dspace:EndpointProperty",
"dspace:name": "authType",
"dspace:value": "bearer"
}
]
}
}
```

Support for the optional DSP `authType` property will be added. If present, its value must be `bearer,` which indicates
clients must present the contained token as a bearer token to the associated HTTP endpoint.

## 3. Data Plane Authorization

Data Plane authorization involves creating an access token as part of the EDR when a `DataFlowStartMessage` is received
and performing authorization checks against the token presented by the client when a data request is issued to the
provider data plane.

These operations will be encapsulated in the `DataPlaneAuthorizationService`:

```java
public interface DataPlaneAuthorizationService {

Result<DataAddress> createEndpointDataReference(DataFlowStartMessage message);

Result<DataAddress> authorize(String token, Map<String, Object> requestData);

}
```

### EDR and Token Creation

When `DataPlaneAuthorizationService.createEndpointDataReference()` is invoked, the service will delegate to
the `DataPlaneTokenService.obtainToken()` to create the authorization token and package it in an EDR.

The `DataPlaneAccessTokenService` is a defined extensibility point that can be used to integrate third-party
authorization servers:

```java
public interface DataPlaneAccessTokenService {

Result<TokenRepresentation> obtainToken(TokenParameters parameters, DataAddress address);

Result<AccessTokenData> resolve(String token);

}

public record AccessTokenData(ClaimToken claimToken, DataAddress address) {
}
```

When `DataPlaneAccessTokenService.obtainToken()` is called, `TokenParameters` will contain (at least) the
following claims:

```java
String participantId;
String processId;
String assetId;
String agreementId;
String transferType
```

The returned `TokenRepresentation` may contain an additional parameter `tokenType` indicating the token type,
e.g., `bearer`.

Additional parameters may be added in the future so `DataPlaneAccessTokenService` implementations must take care to
handle them.

A default in-process `DataPlaneAccessTokenService` implementation will delegate to the existing `TokenGenerationService`
and `TokenValidationService` using a custom token decorator context (`edc:dataplane`).

### Request Authorization

Request authorization is performed when a client issues a request to the provider Data Plane by dispatching
to `DataPlaneAuthorizationService.authorize()`. The `authorize` method takes the `token` and `requestData`, which
encapsulates the token and transport-specific request information as a `Map`, e.g., the HTTP request path:

```java
Result<DataAddress> authorize(String token, Map<String, Object> requestData);
```

`DataPlaneAuthorizationService.authorize`, in turn, will perform a two-step process.

##### `AccessTokenData` Resolution

First, the `DataPlaneAuthorizationService.authorize` implementation will
invoke `DataPlaneAccessTokenService.resolve()` to resolve the `AccessTokenData` containing the `DataAddress` and
claims associated with the token:

```java
public record AccessTokenData(ClaimToken claimToken, DataAddress address)
```

The `ClaimToken` will contain the claims originally passed in the `TokenParameters` used to create the token:

```java
String participantId;
String processId;
String assetId;
String agreementId;
String transferType
```

#### Authorization Check

After the `AccessTokenData` is resolved, the `DataPlaneAuthorizationService.authorize` implementation will delegate
to `DataPlaneAccessControlService.checkAccess`:

```java
public interface DataPlaneAccessControlService {

boolean checkAccess(ClaimToken claimToken, DataAddress address, Map<String, Object> requestData)

}
```

A default implementation will be provided that always returns true. Extensions can supply alternative implementations
that perform use-case-specific authorization checks.

> Please note that `DataPlaneAccessControlService` implementation must handle all request types (including transport
> types) in a data plane runtime. If multiple access check implementations are required, creating a multiplexer or
> individual data plane runtimes is recommended.

0 comments on commit 09f2bc7

Please sign in to comment.