Organizations

Overview

The Organizations feature adds a way for your organization to connect with users and allows you to:

  • Share the personal data your organization has about a given user with them in a secure and private

    channel (to comply with GDPR for example).

  • Have data shared with your organization from a given user in a secure and private channel

    with explicit consent and have the data updated by the user automatically updated in your

    company's systems.

Setting up an Organization

Assuming you have followed the guide from the quickstart section Quickstart section you should have a file for your user .alice.yaml. For the purposes of this example let's also create a second user .bob.yaml.

meeco users:create -p supersecretpassword > .bob.yaml

The next thing you are going to want to do is create the organization. Create a file called .organization-config.yaml with the content something like the following.

kind: Organization
metadata:
spec:
name: SuperData Inc.
description: My super data handling organization
url: https://superdata.example.com

Then run the following command

meeco organizations:create -a .alice.yaml -c .organization-config.yaml > .organization.yaml

The output .organization.yaml file will look something like the following.

kind: Organization
metadata:
privateKey: "-----BEGIN RSA PRIVATE KEY-----\r
...
-----END RSA PRIVATE KEY-----\r\n"
publicKey: "-----BEGIN PUBLIC KEY-----\r
...
-----END PUBLIC KEY-----\r\n"
spec:
id: cc656956-6fb3-4bd1-a906-81c85dd6cb7e
name: SuperData Inc.
description: My super data handling organization
url: https://superdata.example.com
status: requested
requestor_id: 33bd39f9-980f-4ea6-92d3-6a28a218e6ac
validated_by_id: null
agent_id: null
validated_at: null
created_at: 2020-10-29T03:12:18.153Z

Notice how the status field is set to requested at this stage, this means our team has been notified of your intent to create the organization and will review and get in contact with you via the email provided. At this stage only you and the team at Meeco can see the organization. You can check organization was created and in requested state waiting for approval with the following command.

meeco organizations:list -m requested -a .alice.yaml

Once your organization has been approved by the team at meeco we'll let you know via email. From this point on your organization is publicly viewable via the API in Meeco. After that you can check to see that your organization is listed with the other publicly viewable organizations with this command.

meeco organizations:list -a .alice.yaml

Which outputs like the following.

kind: Organizations
spec:
- id: cc656956-6fb3-4bd1-a906-81c85dd6cb7e
name: SuperData Inc.
description: My super data handling organization
url: https://superdata.example.com
status: validated
requestor_id: 33bd39f9-980f-4ea6-92d3-6a28a218e6ac
validated_by_id: 33bd39f9-980f-4ea6-92d3-6a28a218e6ac
agent_id: 79b75bec-aafa-4850-9c47-dfce2c633453
validated_at: 2020-10-29T05:40:22.991Z
created_at: 2020-10-29T03:12:18.153Z
...

Start adding members to your organization. To invite a user to your organization first we create an invitation using the following command.

meeco organization-members:create-invitation -o .organization.yaml -a .alice.yaml > .org-invitation.yaml

Next lets have user Bob accept this invitation to become a member of the organization.

meeco organization-members:accept-invitation -i .org-invitation.yaml -a .bob.yaml > .bob-org-membership.yaml

You can see the list of members in the organization with the command.

meeco organization-members:list -a .alice.yaml cc656956-6fb3-4bd1-a906-81c85dd6cb7e
# meeco organization-members:list -a <USER_AUTH_YAML> <ORGANIZATION_ID>

Organization Services

Organization Services are what your organization can use to connect to users, share data with them, and have data shared back with you. These services are a set of credentials that you can put into your third party systems to give them access to meeco's services. For the purposes of this guide we will complete everything using the CLI however we recommend you set up an application which performs these tasks either using the @meeco/sdk npm package or hitting our API endpoints directly using the SDK as a guide.

First lets create a service configuration file .organization-service-config.yaml something like the following. (Hint: you can use the cryppo cli https://github.com/Meeco/cryppo-cli to quickly and easily create a keypair with the command cryppo genkeypair -p private.pem -P public.pem).

kind: OrganizationService
spec:
name: Data Sharing Service
description: This service is for outgoing shared data from application X
contract: A message about the contract

Next we create the service using that config file.

Ameeco organization-services:create -a .alice.yaml -c .organization-service-config.yaml cc656956-6fb3-4bd1-a906-81c85dd6cb7e > .organization-service.yaml
# meeco organization-services:create -a <USER_AUTH_YAML> -c <ORGANIZATION_SERVICE_CONFIG_FILE> <ORGANIZATION_ID> > <OUTPUT_FILE>

The .organization-service.yaml should have output like the following.

kind: OrganizationService
metadata:
privateKey: "-----BEGIN RSA PRIVATE KEY-----\r
...
-----END RSA PRIVATE KEY-----\r\n"
publicKey: "-----BEGIN PUBLIC KEY-----\r
...
-----END PUBLIC KEY-----\r\n"
spec:
id: c213d93e-32a5-4e1d-96bb-0816e7eb6c74
name: Data Sharing Service
description: This service is for outgoing shared data from application X
contract: A message about the contract
status: requested
organization_id: cc656956-6fb3-4bd1-a906-81c85dd6cb7e
validated_by_id: null
agent_id: null
validated_at: null
created_at: 2020-11-03T03:43:03.751Z

At this stage the Organization service has been requested and has the status requested. The meeco Team will again review this OrganizationService, reach out to you via email if needed, and validate your service. Once this is done we will notify you via email and you will be able to confirm that the organization service is now validated with the command. The metadata.privateKey here should be saved as configuration for your organization service application.

meeco organization-services:get -a .alice.yaml cc656956-6fb3-4bd1-a906-81c85dd6cb7e c213d93e-32a5-4e1d-96bb-0816e7eb6c74
# meeco organization-services:get -a .alice.yaml <ORGANIZATION_ID> <SERVICE_ID>

The result should be something like the following, if the list is empty it means the service has not yet been validated.

kind: OrganizationService
spec:
id: c213d93e-32a5-4e1d-96bb-0816e7eb6c74
name: Data Sharing Service
description: This service is for outgoing shared data from application X
contract: A message about the contract
status: validated
organization_id: cc656956-6fb3-4bd1-a906-81c85dd6cb7e
validated_by_id: 33bd39f9-980f-4ea6-92d3-6a28a218e6ac
agent_id: 3392a0e4-0046-40d5-a532-5bca94f1d801
validated_at: 2020-11-03T04:51:59.724Z
created_at: 2020-11-03T04:27:16.784Z

Now we have created our organization service we can request an authentication token for it.

meeco organization-services:login -a .alice.yaml -s .organization-service.yaml > .organization_service_auth.yaml

The .organization_service_auth.yaml should look like the following.

kind: Authentication
metadata:
data_encryption_key: ""
key_encryption_key: ""
keystore_access_token: ""
passphrase_derived_key: ""
secret: ""
vault_access_token: ANDJk1gJpFKmwrCjNyd7
spec: {}

The metadata.vault_access_token should be saved as configuration for your organization service application. So from now your application has a vault_access_token and a private_key, these should be set as configuration variables. But how do we use them.

Connecting your Organization to Users

Your organization first needs to connect to a user through it's organization service. To do that it will first create an invitation.

The keypair_external_id can be left blank in this case if we are using the same public key to connect with all users. In some cases you may wish to use a unique public key for each user connection, in this case you should store the related private key somewhere with reference to the user who you are connecting to.

The encrypted_recipient_name is a record to be used by your organization only, it should identify in some way who the invitation has been created for. It should encrypted and serialized using a Cryppo serialization format (see https://github.com/Meeco/cryppo-js for more details).

The public_key here can be unique per connection but in this case we are just going th use the keypair from the organization service.

# first part here just writes the json to a file removing all whitespace and newlines
cat <<'EOF' | tr -d '\040\011\012\015' > data.json
{
"public_key": {
"keypair_external_id": "string",
"public_key": "-----BEGIN PUBLIC KEY-----\rMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzao4lCviLTEg2ze8jmts\ry6iG6iKX3TGIdlcHJbFBAs0oCVp29jhlOXVfwuxX6gqplLT44rpSnYcsvKYao7ol\rt7ZadkQg/j1xm+Sw/FTyLKhNyHznclnTUXPnnvY6sHwpfaC0NBIAy1XRI8r3gqiu\rngOx4afC+PeZnrCvhjsnmR1cd/FXTWQuH8GfrqdDbH3K8ObAv4r3VT2RcUvgUEVg\r6Yg29fAF5B9Wmcwl9Kr53nryp04412QvNjlJZlilbNsmvXYnPfu4bM8kRV56iBeE\rL1OOBu65oZcBvXym3Gtd057J+0kDqGp4t76qB9DNy8n3SikvY8hyZHQsx54QBecy\rKxPETEGVWGMFHI5+UIriMr0PEF4AUE9KZWVt3bAhQPyby3Fm9dju01q9nV2qt5Cy\rZnsNui2VZ7EGDxoJPH74fsnrXX7cX8VPFgg2pxmpzmI12X1YBKdymKvCRsa+5I5S\rF2/g5pwJznx1babFSCSenmPr8eIz6Y1iJSigwr4tsUAbE1C6Vn6PEBrsmzMFhe3M\rA7YwqJvNjOZZb3Yocaf08Xn8/oISCd1ItU5W6mLW/uwRSB4cGs/D7E5mNj0bvE+1\rG94RFHSDCzIYyPtb/8dFKlwSJ3Jm2HytiN7c2dVv61KrQFRyktPHPLVR/V6r8XcB\rFR6qZSfofTNCs7HI+VAIKV8CAwEAAQ==\r-----END PUBLIC KEY-----\r\n"
},
"invitation": {
"encrypted_recipient_name": "Aes256Gcm.J9YhaGdIUBKa2dULbMU=.LS0tCml2OiAhYmluYXJ5IHwtCiAgd1JGK2QrRjYzRHJhbDRmdgphdDogIWJpbmFyeSB8LQogIGllS3JnK05iV0JVY2N3L3VVS2N6Rnc9PQphZDogbm9uZQo="
}
}
EOF
# second part here actually makes the request
curl -X POST "https://sandbox.meeco.me/vault/invitations" \
-d @data.json \
-H "Accept: application/json" \
-H "Meeco-Subscription-Key: Q7dFWQDGSsAE6tUo1G93Mlhn4SCOBrJe" \
-H "Authorization: ANDJk1gJpFKmwrCjNyd7" \
-H "Content-Type: application/json" \
| json_pp \
> invitation.json

The invitation.json file should have output that looks something like.

{
"invitation" : {
"keypair_external_id" : "string",
"token" : "cPWV4CwpWTHxhqaJGG9MRkVWxKojGhMPGs4oTuoBdTU",
"message" : null,
"user_image" : null,
"integration_data" : {
"organization_id" : "cc656956-6fb3-4bd1-a906-81c85dd6cb7e",
"intent" : "service",
"service_id" : "c213d93e-32a5-4e1d-96bb-0816e7eb6c74"
},
"id" : "62b54a86-66db-4e88-8e3d-3ce4457a2e97",
"user_name" : null,
"invited_user_id" : null,
"outgoing" : true,
"encrypted_recipient_name" : "Aes256Gcm.J9YhaGdIUBKa2dULbMU=.LS0tCml2OiAhYmluYXJ5IHwtCiAgd1JGK2QrRjYzRHJhbDRmdgphdDogIWJpbmFyeSB8LQogIGllS3JnK05iV0JVY2N3L3VVS2N6Rnc9PQphZDogbm9uZQo=",
"sent_at" : null
}
}

The invitation has been created so lets make an unrelated user to accept this connection invitation.

meeco users:create -p supersecretpassword > .dave.yaml

Then for bob to accept this invitaion (and create the connection).

We should have a new keypair and public_key somewhere that we can use for this connection for Dave, dave might use the meeco keystore to manage this but in this case lets forget about the keystore for now to keep it simple.

Again the keypair_external_id would be a reference for Dave to retrieve the appropriate keypair (when using the keystore this would be the id of the key record) but we can just put the name of the organization service in there for this reference.

The invitation_token here would be .invitation.token from the invitation.json file.

The Authorization here should be Dave's authorization token (from .dave.yaml).

# first part here just writes the json to a file removing all whitespace and newlines
cat <<'EOF' | tr -d '\040\011\012\015' > data.json
{
"public_key": {
"keypair_external_id": "DataSharingService",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqMILz56KuEsGlsEpML3h\nPN7OUf7HrLTtWkazwbNIkK3RLWtNI5X8bd0ISUuwgXQVzZuWyC6wXPiWSDwXILAf\nJPusVT6Kh0EmXhJtBRCkF64fXKz54rI/2kYpuP4HZbNStj8OIRv/ECV7glDf+4Yq\nWDdLmh2vHDHF7bIRQnuWwV3ZL10Gkuh671aJkkVRdApUZUNcDfz1VK/SDMLxuxMg\n8D78u+d0WgThXzEwlcHtRitLA4QekNjVNPkoZoRIJSWLWqwkaOd0+YAhPNso3t9Y\nwaLT0/hDe4qBRuWpkoCIIUxE1JPuUbv3ePwsvyX9ksKNwQ6zVyOBXJwjspjac3mS\nH2DXS8dwU/ObKI3v9c/aY0i4iV6xJIkDxV2V8HclMOm1cLmgoc9YMU9YuM2LZ1GX\n707XBrdRD1v/FNQa/HJjFSapXcztN03etswrJcYFxVxDWZ84uMO2TNHOsSbOgop9\nmF5hRLQ+PT45v+mNNmbJa62yRaVkIV4VvsHgBVsz6TWsZGxu+IsNLKT/OYju/zzn\nvQSig5Ue7BAZqMOlibWiB6gX8vM336okrOWASnvWZNe+a7QpQdYYbHbH/leFZFCA\nht20DXUHLXYAKk9gvdqKycYnVsaRb2dnaSdUez+AUsIme0gWPscwSf3XpARUDc5i\nEKfIKQZzxyj4Y7W6eGwAfCMCAwEAAQ==\n-----END PUBLIC KEY-----\n"
},
"connection": {
"encrypted_recipient_name": "Aes256Gcm.SjlZaGFHZElVQkthMmRVTGJNVQ==.LS0tCml2OiAhYmluYXJ5IHwtCiAgd1JGK2QrRjYzRHJhbDRmdgphdDogIWJpbmFyeSB8LQogIGllS3JnK05iV0JVY2N3L3VVS2N6Rnc9PQphZDogbm9uZQo=",
"invitation_token": "cPWV4CwpWTHxhqaJGG9MRkVWxKojGhMPGs4oTuoBdTU"
}
}
EOF
# second part here actually makes the request
curl -X POST "https://sandbox.meeco.me/vault/connections" \
-d @data.json \
-H "Accept: application/json" \
-H "Meeco-Subscription-Key: Q7dFWQDGSsAE6tUo1G93Mlhn4SCOBrJe" \
-H "Authorization: hZwx4XPj6MZJcPHPKHqc" \
-H "Content-Type: application/json" \
| json_pp \
> connection.json

The connection will have been created and the output in connection.json will look something like.

{
"connection" : {
"own" : {
"connection_type" : "service",
"integration_data" : {
"intent" : "service",
"service_id" : "c213d93e-32a5-4e1d-96bb-0816e7eb6c74",
"organization_id" : "cc656956-6fb3-4bd1-a906-81c85dd6cb7e"
},
"user_id" : "d62d37f8-9f53-4be2-9df3-af7541d08316",
"id" : "c76b28f6-ab27-4b41-a8db-3184d17b8fbc",
"user_public_key" : "-----BEGINPUBLICKEY----- ... -----ENDPUBLICKEY-----\n",
"user_type" : "human",
"user_keypair_external_id" : "DataSharingService",
"encrypted_recipient_name" : "Aes256Gcm.SjlZaGFHZElVQkthMmRVTGJNVQ==.LS0tCml2OiAhYmluYXJ5IHwtCiAgd1JGK2QrRjYzRHJhbDRmdgphdDogIWJpbmFyeSB8LQogIGllS3JnK05iV0JVY2N3L3VVS2N6Rnc9PQphZDogbm9uZQo="
},
"the_other_user" : {
"connection_type" : "service",
"id" : "359486bb-e998-4699-9eed-5e7194987565",
"user_id" : "c3482646-f6cf-48a2-877c-04857802d4de",
"integration_data" : {
"organization_id" : "cc656956-6fb3-4bd1-a906-81c85dd6cb7e",
"service_id" : "c213d93e-32a5-4e1d-96bb-0816e7eb6c74",
"intent" : "service"
},
"user_keypair_external_id" : "string",
"user_type" : "service_agent",
"user_public_key" : "-----BEGINPUBLICKEY----- ... -----ENDPUBLICKEY-----\n",
}
}
}

The OrganizationService has now made it's first connection with a user.