Access Management
PrivMX platform offers versatile containers like Threads, Stores, and Inboxes to support secure collaboration and communication. Access to these containers is managed based on different user roles and the type of container setup. This ensures that only authorized participants can view and modify the content. Here’s a breakdown of how these elements function:
-
Private Users - Private containers are created and managed by one of the participants (not the owner). In this scenario, access to the container's content is controlled by the participants, not by the system owner. The owner can view content they’ve been granted access to by participants, but cannot modify it. The keys remain entirely with the users, ensuring a high level of privacy.
-
Managed Users - Managed containers, on the other hand, are created and managed directly by the owner, who has access to all the content within the container. While this setup allows the owner to monitor and modify everything that flows through the container, it also provides a standardized access experience common in many communication systems.
In practice, these two modes allow PrivMX to balance privacy and control, enabling both highly secure user-controlled spaces and owner-managed containers suited to organizational needs.
Scenarios
Private Channel | Managed Channel | |
---|---|---|
Private Users | Full User Privacy - The owner can only access the content they were granted permission to by the other participants of the container. Therefore, the owner should be directly added as a participant to gain the necessary access. | Partially Managed Accounts - The owner has access to the entire content of the container. However, without the necessary private keys, they cannot make any modifications to the content. |
Managed Users | Managed Users with Impersonation - The owner can access the content by using the users' private keys. This is possible because the system owner has ownership of the keys, which are stored in the management system. | Full Access Management - The owner can view and modify everything that is transmitted through the container - it's a full access mode to the container's content (which is the standard in typical communication systems). |
Potential Threats
Each scenario introduces distinct security challenges and privacy implications:
- Full User Privacy – ensures maximum privacy, but carries the risk of data loss if users lose access to their accounts. Additionally, there is a potential for undetected breaches if a user’s device is compromised (if the private key is stored locally). However, the keys can be deterministically generated from user-provided data as an alternative.
- Partially Managed Accounts – faces risks related to insider threats and potential misuse of read-only access, as administrators may still view sensitive data under certain conditions.
- Managed Users with Impersonation – introduces the risk of unauthorized access, if the owner's credentials or users' private keys are compromised. Since the users' private keys are stored by the system's owner, they could be vulnerable to breaches. It's up to the developer to secure them properly.
- Full Access Management – presents a heightened risk of data manipulation, insider threats, and challenges in securely managing and storing private keys within the system.
PrivMX offers flexible configurations to address diverse privacy and management needs. The selected scenario should align with the organization's specific security, compliance, and operational requirements.
User Management
General info
PrivMX does not provide a user management service. However, each application user has to be granted access to specific resources within the Platform.
The access is granted in the following way:
- PrivMX uses public keys to identify users.
- Each user's public key is linked to Contexts they are in.
- An access control list (ACL) is set up for each user.
- The ACL defines which PrivMX functions the user can access.
Automated User Management
To automate User Management, the developer must provide an application server (later also called the server), which:
- is exclusively managed by the developer;
- is responsible for handling users' public keys;
- stores information about user profiles.
When a user's key pair is generated (which should happen on the user’s device, not the server), only the public key needs to be sent to the application server (using a secure, authorized container). The server can then assign the user to the desired Context.
This process ensures secure key management while allowing the application to control user access.
Requirements
To enable communication between the application server and PrivMX, the server needs to use an access key.
Each generated access key consists of a key (ACCESS_KEY) and a secret (ACCESS_KEY_SECRET). Both need to be stored in environment variables. Access key also has an associated access control list, which defines the PrivMX functions it can execute.
Using the Access Key on the Server
To use the access key, application server must sign requests to the API server using the provided data. Below is an example request for creating a new Context on the server:
async function getAccessSig(requestPayload: string): Promise<string> {
const timestamp = Date.now();
const nonce = generateNonce();
const dataToSign =
`${ACCESS_KEY};1;${timestamp};${nonce};${ACCESS_KEY_SECRET};${requestPayload}`;
const signature = (await sha256(dataToSign)).slice(0, 20).toString('base64');
return `${ACCESS_KEY};1;${timestamp};${nonce};${signature}`;
}
async function sha256(data: string): Promise<Buffer> {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
let hashBuffer: ArrayBuffer;
if (typeof window === 'undefined') {
hashBuffer = await require('crypto').webcrypto.subtle.digest('SHA-256', dataBuffer);
} else {
hashBuffer = await window.crypto.subtle.digest('SHA-256', dataBuffer);
}
return Buffer.from(hashBuffer);
}
const requestBody = {
jsonrpc: '2.0',
id: 0,
method: 'context/createContext',
params: {
solutionId: SOLUTION_ID,
profile: { name, description: '', scope: 'private' }
}
};
const addToContextRequest = await fetch(CLOUD_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Access-Sig': await getAccessSig(JSON.stringify(requestBody))
},
body: JSON.stringify(requestBody)
});