Affinidi Meeting Place - Control Plane API provides capabilities to enable the discovery of other participants to establish a connection and communicate securely. The Control Plane API enables participants to publish a connection offer that allows them to be discoverable and facilitates the creation of a secure communication channel with other participants.
The Control Plane API is built on Dart for a high-performance server, which provides optimal speed and stability for handling API requests.
DISCLAIMER: Affinidi provides this API as a developer tool to facilitate decentralized discovery and messaging. Any personal data exchanged or stored via this tool is entirely initiated and controlled by end-users. Affinidi does not collect, access, or process such data. Implementing parties are responsible for ensuring that their applications comply with applicable privacy laws and user transparency obligations.
- Affinidi Meeting Place - Control Plane API for Dart
-
Discovery: Enables the discovery of other participants within the Meeting Place through published invitations, enhancing digital interactions.
-
DID Authentication: Uses DID and DIDComm Message for secure authentication to generate an access token to call endpoints.
-
Out-of-Band Invitation: Enable out-of-band communication to establish a connection between participants (e.g., individuals, businesses, and AI agents).
-
Device Registration and Notification: Secure device registration ensures seamless delivery of notifications on key events, including push notifications on the user's device.
-
Group Chat: Provides group chat functionality, including management of members and sending messages to group members.
-
Decentralised Identifier (DID) - A globally unique identifier that enables secure interactions. The DID is the cornerstone of Self-Sovereign Identity (SSI), a concept that aims to put individuals or entities in control of their digital identities.
-
Out-Of-Band - The protocol defined in DIDComm enables sharing a DIDComm message or invitation through a transport method other than a direct, established DIDComm channel, such as via a QR code or a URL to create a new connection.
-
Discovery - The Control Plane API allows participants to create connection offers or invitations that other parties can claim to initiate connection requests and establish a secure communication channel.
- Install Dart SDK ^3.6.0
- Install Redis
- Install Docker
List of the environment variables required to run the Control Plane API server.
| Variable Name | Description |
|---|---|
| ENV | Specifies the environment in which the server is running. By default, it is set to DEV. |
| SERVER_PORT | Specifies the port on which the server listens for incoming requests. |
| API_ENDPOINT | Defines the API endpoint (e.g., http://localhost) to receive requests from the callers. |
| CONTROL_PLANE_DID | The DID used for authentication (e.g., did:web:yourdomain.com). The caller will resolve the CONTROL_PLANE_DID to fetch the public key information and encrypt the DIDComm message containing the auth challenge string. For testing or running the server locally, use the did:local:8080 - replace the 8080 depending on your configured SERVER_PORT. |
| STORAGE_ENDPOINT | Specifies the endpoint for the storage instance to access the stored data. Use localhost when running the instance locally. |
| STORAGE_PORT | Specifies the port used by the storage instance to handle requests. For example, if you use the default Redis configuration, the port will be 6379. |
| DIDCOMM_AUTH_SECRET | Specifies path and filename containing the didcommauth secret (e.g., secrets/didcommauth.json) |
| HASH_SECRET | A secret value to enhance the security of hashing operations within the application. |
| DID_DOCUMENT | Specifies path and filename of the DID document parameter (e.g., params/did_document.json. |
Configure the following environment variables if AWS is the selected option.
| Variable Name | Description |
|---|---|
| AWS_REGION | Specifies the AWS region to access the AWS services. |
| AWS_PROFILE | (Optional) Specifies the AWS CLI profile name to use for credentials. When set, the server will use aws configure export-credentials to fetch credentials from the specified profile. This supports SSO, assumed roles, and standard profiles. If not set, falls back to AWS_ACCESS_KEY, AWS_SECRET_KEY, and AWS_SESSION_TOKEN. |
| AWS_ACCESS_KEY | Specifies the AWS access key used when accessing AWS services. Only required if AWS_PROFILE is not set. |
| AWS_SECRET_KEY | Specifies the AWS secret key used when accessing AWS services. Only required if AWS_PROFILE is not set. |
| AWS_SESSION_TOKEN | Specifies the AWS session token used when accessing AWS services with temporary credentials. Only required if AWS_PROFILE is not set. |
Run the Control Plane API server using the persistent wallet provided by Affinidi SSI library.
Execute the following commands inside the repository folder.
-
Create a copy the required files.
Create a copy of
config.ymlfrom examples folder to the root of the directory.docker-compose -f dev/docker-compose.dev.yml up -d
-
Copy the application configuration file.
cp examples/config/config.example.yml config.yml
-
Create a .env file to setup your environment.
cp examples/env/.env.example .env
-
Create key pairs to generate JSON Web Keys (JWKs) for DIDCommAuth.
mkdir -p ./keys ./params ./secrets openssl ecparam -name secp256k1 -genkey -noout -out ./keys/secp256k1.pem openssl ecparam -name prime256v1 -genkey -noout -out ./keys/p256.pem openssl genpkey -algorithm Ed25519 -out ./keys/ed25519.pem openssl pkey -in keys/ed25519.pem -pubout -out ./keys/ed25519-pub.pem
-
Run the setup script to generate JWKs from the key pairs.
dart run script/setup.dart
The script will generate the required secrets files to run the API server.
For more info about managing secrets, go to the Secrets List section.
-
After setting up the required keys and secrets, run the server.
dart run bin/server_local.dart -e dart
Navigate to http://localhost:3000 or whichever host and port you use in the configuration to verify if the Control Plane API is running.
NOTE: The persistent wallet will be empty after each restart as it uses an in-memory storage solution.
Use nodemon to apply the code changes directly while running the API server. Use the following command to install it globally on your machine.
npm install -g nodemonAfter installing nodemon, run the API server using the following command.
nodemon -x "dart run bin/server_local.dart " -e dartThe repository provides different server_*.dart files. Depending on the implementation, Dart files ensure you run the correct server file.
To run the Control Plane API with Docker, follow these steps:
-
Create a copy the required files. Copy the example Docker Compose file to a new docker-compose.yml file:
cp examples/docker/local/docker-compose.example.yml docker-compose.yml
Create a copy of
config.ymlfrom examples folder to the root of the directory.cp examples/config/config.example.yml config.yml
-
Set environment variables in the docker file.
- Open the newly copied docker-compose.yml file and update the necessary environment variables, such as storage, API endpoint, and secrets.
- For more information about environment variables, refer to environment variables section.
-
Create key pairs to generate JSON Web Keys (JWKs) for DIDCommAuth.
mkdir -p ./keys ./params ./secrets openssl ecparam -name secp256k1 -genkey -noout -out ./keys/secp256k1.pem openssl ecparam -name prime256v1 -genkey -noout -out ./keys/p256.pem openssl genpkey -algorithm Ed25519 -out ./keys/ed25519.pem openssl pkey -in keys/ed25519.pem -pubout -out ./keys/ed25519-pub.pem
-
Run the setup script to generate JWKs from the key pairs.
dart run script/setup.dart
The script will generate the required secrets files to run the API server.
For more info about managing secrets, go to the Secrets List section.
-
Start the application using docker compose build command:
docker-compose up --build
Navigate to http://localhost:3000 or whichever host and port you use in the configuration to verify if the Control Plane API is running.
For more examples using different environment configurations, refer to the Docker examples folder for additional setup variations and use cases.
-
Ensure that the
.envfile is set up and properly configured. -
Install dependencies and prepare code.
dart pub get dart run build_runner build
-
Generate the keys when necessary. Skip if you have done this step.
dart run script/setup.dart
-
Run the server if it is not yet running.
dart run bin/server_local.dart
-
While the server is running, run the test script.
dart test --chain-stack-traces
The Control Plane API requires an access token to call the endpoints. It uses a Decentralised Identifier (DID) and a DIDComm Message to authenticate users and generate the required token.
The Control Plane API expects the Bearer Token to be present in the Authorization header of the request header. To obtain the token, a 2-step API request is required.
-
Make a POST
/authenticate/challengewith your DID as the payload.POST /v1/authenticate/challenge { "did": "did:peer:...." }The endpoint returns a challenge string response required in the subsequent request as part of a DIDComm message using the
challengeTokenproperty and your DID.{ "challenge": "string" }Sign the DIDComm message with the private key associated with your DID and encrypt it with the Control Plane API's public key published through its DID, proving ownership of the DID used on Step 1.
-
After building the DIDComm message with a challenge string and encoding it with base64, call the
/authenticateendpoint to obtain the token.POST /v1/authenticate { "challenge_response": "string" }The endpoint will return the access token, including the refresh token and duration of each token.
{ "access_token": "string", "access_expires_at": "string", "refresh_token": "string", "refresh_expires_at": "string" }
Use the access token in the Authorization header to call protected endpoints, such as device registration and publishing connection offers for discovery.
Refer to the authentication flow document for more details.
To call the authenticated API endpoints, use the DIDCommAuthToken generated from the /authenticate using DID and DIDComm Message.
Endpoint: POST /v1/check-offer-phrase
Header: Auhorization: Bearer
Request application/json
{
"offerPhrase": "ExistingOfferPhrase"
}Response application/json
{
"isInUse": true
}Refer to the list of available endpoints from the Control Plane API.
The Control Plane API currently supports two secret managers.
To define which secret manager to use, set the SECRET_MANAGER variable in the environment configuration file.
If you wish to extend the list of supported secret managers or modify the existing implementation's functionality, refer to the secret_manager.dart file.
To generate secrets automatically, run dart run script/setup.dart.
| Secret Name | Description |
|---|---|
didcommauth |
To sign and verify tokens, generate and configure the didcommauth secret. This secret is stored differently depending on the secret manager in use. The secret is a JSON string containing a list of private JWKs. |
hash_secret |
A secret value used to enhance the security of hashing operations within the application. |
If you're using a local secret manager, specify the path to the JSON file containing the secret value using the DIDCOMM_AUTH_SECRET environment variable. For example:
DIDCOMM_AUTH_SECRET=secrets/didcommauth.json
HASH_SECRET=secrets/hash-secret.txtIf you're using AWS Secrets Manager, the DIDCOMM_AUTH_SECRET environment variable must contain the secret's name stored in AWS Secrets Manager, rather than the file path.
DIDCOMM_AUTH_SECRET=<MY_AWS_SECRET_NAME>When using AWS SNS, correctly configure the necessary AWS credentials in your environment using one of these methods:
Option 1: Using AWS Profile (Recommended)
AWS_PROFILE=my-profile
AWS_REGION=us-east-1Option 2: Using Direct Credentials
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
AWS_SESSION_TOKEN=... # Optional, for temporary credentials
AWS_REGION=us-east-1When AWS_PROFILE is set, the server will use the AWS CLI to fetch credentials from the specified profile. This method supports:
- Standard IAM user profiles
- SSO (IAM Identity Center) profiles
- Assumed role profiles
- Temporary credentials with automatic expiration handling
The AWS SNS provider requires specific IAM permissions to function correctly. Ensure that your IAM policies allow the following actions:
sns:Publishsns:CreatePlatformEndpoint.
You can also set the pushNotificationCustomKeyProperty property in your configuration to match the client's setup when receiving a push notification. This property specifies the key within the push notification that contains custom metadata.
deviceNotification:
pushNotificationCustomKeyProperty: "affinidiInfo"If you face any issues or have suggestions, please don't hesitate to contact us using this link.
If you have a technical issue with the project's codebase, you can also create an issue directly in GitHub.
-
Ensure the bug was not already reported by searching on GitHub under Issues.
-
If you're unable to find an open issue addressing the problem, open a new one. Be sure to include a title and a clear description, as much relevant information as possible, and a code sample or an executable test case demonstrating the expected behaviour that is not occurring.
Want to contribute?
Head over to our CONTRIBUTING guidelines.
