A .NET library for implementing iSHARE Trust Framework functionality in your applications. This package provides essential services for building iSHARE-compliant Service Providers and Service Consumers.
Compatible with iSHARE Trust Framework 2.2
For more information about iSHARE, visit the iSHARE Developer Portal.
This package is open sourced by Poort8 to facilitate others in connecting to iSHARE data spaces.
📋 Important notes:
- 🔄 Poort8 actively uses this package themselves and updates it when they need new features or fixes
- 🐛 Bugs, feature requests, and questions: Submit them via GitHub Issues only
⚠️ No official support: Poort8 does not provide support and gives no commitments on bug fixes- 🤝 Community support only: The community may help, but there are no guarantees or SLAs
💡 If you need guaranteed support or specific features, consider contributing to the project or forking it for your own needs.
This package helps you implement iSHARE functionality for secure data sharing in data ecosystems. For a complete understanding of iSHARE concepts and workflows, please refer to the iSHARE Getting Started Guide.
Quick terminology reference:
- EORI: Your unique identifier (e.g.,
EU.EORI.NL000000001) - Service Provider: You expose APIs with data (implement token validation)
- Service Consumer: You call other APIs to get data (use access tokens)
- M2M: Machine-to-Machine authorization (system-to-system)
- H2M: Human-to-Machine authorization (users acting on behalf of organizations)
For detailed concepts, see iSHARE Authorization and Authentication.
- .NET 8.0 or higher
- Basic understanding of JWT tokens and dependency injection
- iSHARE certificate and participant registration
- Get test certificates: Request here
- Register as participant: Contact a Participant Registry
- Determine your role: Service Provider, Consumer, or both
Install the NuGet package:
dotnet add package Poort8.Ishare.CoreRegister the services in your application (e.g., ASP.NET Core):
builder.Services.AddIshareCoreServices(builder.Configuration);Add the following configuration section to your appsettings.json:
{
"IshareCoreOptions": {
"ClientId": "EU.EORI.NLXXXXXXXXX",
"SatelliteId": "EU.EORI.NLXXXXXXXXX",
"SatelliteUrl": "https://satellite.example.com",
"AuthorizationRegistryId": "EU.EORI.NLXXXXXXXXX",
"AuthorizationRegistryUrl": "https://ar.example.com"
}
}ClientId: Your organization's EORI identifierSatelliteId: The dataspace satellite's EORI identifierSatelliteUrl: URL of the dataspace satellite
AuthorizationRegistryId: Authorization Registry EORI identifierAuthorizationRegistryUrl: Authorization Registry URL
You need certificates for: Authenticating your organization in the iSHARE network.
Choose either Azure Key Vault or file-based certificates:
Use this if: You're running in Azure and want centralized certificate management.
{
"IshareCoreOptions": {
"AzureKeyVaultUrl": "https://your-keyvault.vault.azure.net/",
"CertificateName": "your-certificate-name"
}
}Use this if: You want to store certificates directly in your application configuration.
{
"IshareCoreOptions": {
"Certificate": "base64-encoded-pfx-certificate",
"CertificatePassword": "certificate-password",
"CertificateChain": "base64-encoded-certificate-chain",
"CertificateChainPassword": "chain-password"
}
}Here's a practical example: You're building a logistics app that needs truck location data from a transport company's API.
// Inject the required services in your controller or service class
public class LogisticsService
{
private readonly IAccessTokenService _accessTokenService;
private readonly IAuthenticationService _authenticationService;
private readonly IHttpClientFactory _httpClientFactory;
public LogisticsService(
IAccessTokenService accessTokenService,
IAuthenticationService authenticationService,
IHttpClientFactory httpClientFactory)
{
_accessTokenService = accessTokenService;
_authenticationService = authenticationService;
_httpClientFactory = httpClientFactory;
}
// SCENARIO 1: You're consuming data (Service Consumer)
public async Task<TruckLocation[]> GetTruckLocations()
{
// Step 1: Get access token from the transport company
var transportCompanyEori = "EU.EORI.NL000000123";
var tokenUrl = "https://transport-api.com/connect/token";
string accessToken = await _accessTokenService.GetAccessTokenAtParty(
transportCompanyEori, tokenUrl);
// Step 2: Use token to fetch truck data
using var httpClient = _httpClientFactory.CreateClient();
httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var response = await httpClient.GetAsync("https://transport-api.com/api/trucks/locations");
// Handle response...
return Array.Empty<TruckLocation>(); // Your deserialization logic here
}
// SCENARIO 2: You're providing data (Service Provider)
// This would be in your API controller's token endpoint
public async Task ValidateIncomingRequest(string clientAssertion, string clientId)
{
try
{
// Validate that the requesting party is legitimate
await _authenticationService.ValidateClientAssertion(clientAssertion, clientId);
// If this succeeds, create and return an access token
}
catch (Exception)
{
// Reject the request - invalid client
throw;
}
}
}
public class TruckLocation
{
public string TruckId { get; set; } = "";
public double Latitude { get; set; }
public double Longitude { get; set; }
}When to use: When you need to call another party's API (you're a Service Consumer).
// Get access token from a specific party
// Parameters:
// - partyId: The EORI of the party you want to call
// - tokenUrl: Their token endpoint URL (usually ends with /connect/token)
string token = await accessTokenService.GetAccessTokenAtParty(
"EU.EORI.NL000000123",
"https://transport-company.com/connect/token");When to use: When validating incoming requests to your API (you're a Service Provider).
// Validate client assertion - use this in your /connect/token endpoint
// This checks if the requesting party is legitimate and their certificate is valid
await authenticationService.ValidateClientAssertion(clientAssertion, clientIdHeader);When to use: For M2M authorization scenarios requiring delegation evidence validation. See iSHARE Authorization for complete delegation flows.
// Simplified delegation check - just the essence
var delegationMask = new DelegationMask
{
DelegationRequest = new DelegationMask.DelegationRequestObject
{
PolicyIssuer = "EU.EORI.NL000000001", // Policy issuer (data owner)
Target = new DelegationMask.DelegationRequestObject.TargetObject
{
AccessSubject = "EU.EORI.NL000000002" // Access subject (who wants access)
},
PolicySets = new List<DelegationMask.DelegationRequestObject.PolicySet>
{
new DelegationMask.DelegationRequestObject.PolicySet
{
Policies = new List<DelegationMask.DelegationRequestObject.PolicySet.Policy>
{
new DelegationMask.DelegationRequestObject.PolicySet.Policy
{
Target = new DelegationMask.DelegationRequestObject.PolicySet.Policy.TargetObject
{
Resource = new DelegationMask.DelegationRequestObject.PolicySet.Policy.TargetObject.ResourceObject
{
Type = "resource-type",
Identifiers = new List<string> { "*" },
Attributes = new List<string> { "*" }
},
Actions = new List<string> { "read" },
Environment = new DelegationMask.DelegationRequestObject.PolicySet.Policy.TargetObject.EnvironmentObject
{
ServiceProviders = new List<string> { "EU.EORI.NL000000003" }
}
},
Rules = new List<DelegationMask.DelegationRequestObject.PolicySet.Policy.Rule>
{
new DelegationMask.DelegationRequestObject.PolicySet.Policy.Rule { Effect = "Permit" }
}
}
}
}
}
}
};
// Get delegation evidence
var evidence = await authorizationRegistryService.GetDelegationEvidence(delegationMask);
bool hasAccess = authorizationRegistryService.VerifyDelegationEvidencePermit(
evidence, "EU.EORI.NL000000001", "EU.EORI.NL000000002", "EU.EORI.NL000000003",
"resource-type", "resource-id", "read");When to use: When you need to authenticate with other parties or when Service Providers collect delegation evidence on behalf of clients.
// Create client assertion for authentication with another party
string clientAssertion = clientAssertionCreator.CreateClientAssertion("audience-eori");When to use: When you need to verify if parties are legitimate or get trusted certificate authorities.
// Verify party using certificate thumbprint
PartyInfo partyInfo = await satelliteService.VerifyParty("EU.EORI.NLXXXXXXXXX", "certificateThumbprint");
// Verify party using client assertion
PartyInfo partyInfo = await satelliteService.VerifyPartyWithClientAssertion("EU.EORI.NLXXXXXXXXX", "clientAssertion");
// Get valid trusted list
IEnumerable<TrustedListAuthority> trustedList = await satelliteService.GetValidTrustedList();You're a Service Provider if: You have data/services that other companies want to access through APIs.
You must implement these required endpoints: Access Token, Capabilities, and Return. For complete implementation details, see Service Provider Role.
// Validate client assertion in your token endpoint
try
{
await authenticationService.ValidateClientAssertion(request.ClientAssertion, request.ClientId);
// Create and return access token
}
catch (Exception ex)
{
// Handle validation failure
}// In your data endpoints, validate access token first (your implementation)
// Then optionally validate delegation evidence
bool isAuthorized = authorizationRegistryService.VerifyDelegationEvidencePermit(
delegationEvidence,
"policyIssuer",
"accessSubject",
"serviceProvider",
"resourceType",
"resourceIdentifier",
"action");Delegation Evidence: Following iSHARE M2M authorization patterns, the preferred approach is for Service Providers to fetch and validate delegation evidence themselves rather than relying on Service Consumers to provide it. This provides better security and control over authorization decisions.
For a step-by-step tutorial on building a Service Provider with ASP.NET Core Minimal API, see our Service Provider Implementation Guide.
You're a Service Consumer if: You want to call other companies' APIs to get their data.
For complete implementation scenarios and workflows, see Service Consumer Role.
For a step-by-step tutorial on building a Service Consumer with ASP.NET Core Minimal API, see our Service Consumer Implementation Guide.
// 1. Get access token from Service Provider
string accessToken = await accessTokenService.GetAccessTokenAtParty(
"EU.EORI.NL000000123",
"https://service-provider.com/connect/token");
// 2. Use token in HTTP requests to their APIs
using var httpClient = httpClientFactory.CreateClient();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
var response = await httpClient.GetAsync("https://service-provider.com/api/data");You need this if: You're accessing data on behalf of another organization following iSHARE M2M authorization.
public class BrokerService
{
private readonly IAuthorizationRegistryService _authService;
public async Task<bool> CheckDelegationRights(string dataOwnerEori, string serviceProviderEori)
{
// Request delegation evidence to verify access rights
var delegationMask = new DelegationMask
{
DelegationRequest = new DelegationMask.DelegationRequestObject
{
PolicyIssuer = dataOwnerEori, // Data owner who issued the policy
Target = new DelegationMask.DelegationRequestObject.TargetObject
{
AccessSubject = "EU.EORI.NL000000789" // Your organization's EORI
},
PolicySets = new List<DelegationMask.DelegationRequestObject.PolicySet>
{
new DelegationMask.DelegationRequestObject.PolicySet
{
Policies = new List<DelegationMask.DelegationRequestObject.PolicySet.Policy>
{
new DelegationMask.DelegationRequestObject.PolicySet.Policy
{
Target = new DelegationMask.DelegationRequestObject.PolicySet.Policy.TargetObject
{
Resource = new DelegationMask.DelegationRequestObject.PolicySet.Policy.TargetObject.ResourceObject
{
Type = "data-container",
Identifiers = new List<string> { "*" },
Attributes = new List<string> { "*" }
},
Actions = new List<string> { "read" },
Environment = new DelegationMask.DelegationRequestObject.PolicySet.Policy.TargetObject.EnvironmentObject
{
ServiceProviders = new List<string> { serviceProviderEori }
}
},
Rules = new List<DelegationMask.DelegationRequestObject.PolicySet.Policy.Rule>
{
new DelegationMask.DelegationRequestObject.PolicySet.Policy.Rule { Effect = "Permit" }
}
}
}
}
}
}
};
try
{
var evidence = await _authService.GetDelegationEvidence(delegationMask);
// Verify the evidence contains the required permissions
return _authService.VerifyDelegationEvidencePermit(
evidence, dataOwnerEori, "EU.EORI.NL000000789", serviceProviderEori,
"data-container", "*", "read");
}
catch
{
return false; // No delegation rights
}
}
}Note: Following iSHARE best practices, Service Providers should fetch and validate delegation evidence themselves rather than requiring Service Consumers to provide it.
When to use this: Always wrap iSHARE operations in try-catch blocks for production code following zero trust principles.
The library throws exceptions for various error conditions:
try
{
await authenticationService.ValidateClientAssertion(clientAssertion, clientId);
}
catch (SatelliteException ex)
{
// Handle satellite-specific errors (party verification, certificate validation)
logger.LogError("P8.err - Satellite error: {Message}", ex.Message);
}
catch (Exception ex)
{
// Handle general validation errors (token validation, delegation evidence)
logger.LogError("P8.err - Validation failed: {Message}", ex.Message);
}This package includes the following key dependencies:
- System.IdentityModel.Tokens.Jwt: JWT token handling
- Azure.Security.KeyVault.Certificates: Azure Key Vault integration
- LazyCache.AspNetCore: Caching functionality
- Microsoft.Extensions.Http: HTTP client factory support
- iSHARE Developer Portal
- iSHARE Trust Framework Specification
- Service Provider Implementation Guide
- Service Consumer Implementation Guide
- Common Endpoints
- iSHARE Authorization Concepts
- iSHARE Authentication Concepts
- Data Sharing Principles
This project is licensed under the MPL-2.0 license - see the LICENSE file for details.