--- tags: DWN, proposal, interface --- # [Proposal] DWN Tenants Interface DWNs are multi-tenanted which means that a single DWN instance can receive/store messages associated to many DIDs. When sending a request to a DWN, the intended recipient is provided as the value of the `target` property. e.g. ```json= { "target": "did:ex:alice", "messages": [...] } ``` So, how does the receiving DWN know whether `did:ex:alice` is a tenant? More generally, how are tenants added/removed from a DWN? In order to support multi-tenancy, I think it may be helpful to introduce the concept of an **Operator**. An operator, identified by a DID, can be seen as an entity or individual that can add or remove tenants through an interface. **How is the Operator DID provided to a DWN?** As a configuration property **How does authentication work for the operator?** by including a signature as the value for the `authorization` property in the message. The signature must be a General JWS that meets the following requirements: * The decoded payload must be a JSON object that contains `descriptorCid` * `descriptorCid` must be a cbor-encoded, sha256-hashed v1 CID of the message `descriptor` * the protected header must include: * `kid` to lookup the respective public key in the operator's DID document * `alg` to identify the algorithm intended for use with the key * the signature must be produced with a key whose public key is present as a `verificationMethod` in the operator's DID document ## Interface Methods ### `TenantsAdd` ```json= { "descriptor": { "method": "TenantsAdd", "tenant": "did:ex:clifford" }, "authorization": { "payload": { "descriptorCid": CID(descriptor) }, "signatures": [{ "protected": { "kid": "did:ex:operator#keys-1", "alg": "OKP" }, "signature": "..." }] } } ``` * Sucessfully adding a tenant should produce a `201: Created` message result. * Failure to provide `authorization` should produce a `401: Unauthorized` message result * Failed auth should produce a `403: Forbidden` message result. * Attemping to add a tenant that has already been added should produce a: * `200: OK` :question: * `400: Bad Request` :question: ### `TenantsRemove` ```json= { "descriptor": { "method": "TenantsRemove", "tenant": "did:ex:clifford" }, "authorization": { "payload": { "descriptorCid": CID(descriptor) }, "signatures": [{ "protected": { "kid": "did:ex:operator#keys-1", "alg": "OKP" }, "signature": "..." }] } } ``` * Successfully removing a tenant should produce a `200: OK` message result * Failure to provide `authorization` should produce a `401: Unauthorized` message result * Failed auth should produce a `403: Forbidden` message result. * Attempting to remove a tenant that doesn't exist should produce a `400: Bad Request` message result. ## Tenant Authentication Tenants of a DWN are not required to invoke capabilities in order to send any messages to that DWN. Similar to Operator authentication, a tenant must include a signature as the value for the `authorization` property in the message. The signature must be a General JWS that meets the following requirements: * The decoded payload must be a JSON object that contains `descriptorCid` * `descriptorCid` must be a cbor-encoded, sha256-hashed v1 CID of the message `descriptor` * the protected header must include: * `kid` to lookup the respective public key in the operator's DID document * `alg` to identify the algorithm intended for use with the key * the signature must be produced with a key whose public key is present as a `verificationMethod` in the operator's DID document ## Open Questions **Who should the Intended Recipient be? a.k.a `request.target`** The operator DID? - That makes sense to me **Should a tenant be able to remove themselves using `TenantsRemove`**? I think so - If they are added as a DID with data in the node, then we should treat it the same as any other **What other Interface Methods might be useful and why?** - TenantsLock: Disallow further activity in relation to a given DID, but retain the data/state - TenantsBlock: wipe a DID, if data is present, and block it from having any presence in the node