NAV
http cURL go

Introduction

alt text

Welcome to UserClouds! This page provides helpful resources for getting started and documents our APIs for:

  1. Authentication
  2. Authorization
  3. Invites
  4. User Data Vault
  5. Tokenizer

Supported Langauges & Frameworks

We have API documentation & samples for:

You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

Configuring Your Tenant

All of these examples assume you have configured a Tenant with the system. A Tenant is a dedicated data store for your application's user data with several APIs built on top: Plex (Authentication), IDP (User Store), and AuthZ (Authorization). These APIs are all callable via your Tenant's custom base URL, known as the "Tenant URL".

For OIDC-compliant authentication via Plex, you must also configure Plex Applications (which map to OAuth2/OIDC Clients).

You may sign up and configure your tenant in the Developer Console.

For all examples below, make sure to replace the sample values (Tenant URLs, nonces & random values, redirect URLs, app/client IDs & secrets, etc) with values appropriate to your application.

Authentication

Authentication is handled on the front-end by Plex, an OIDC/OAuth-conformant authentication API with support for multiple underlying IDentity Providers (IDPs) such as:

Plex was built with flexibility in mind to allow for:

  1. Easy initial setup on UserClouds, ideal for new apps or apps without large existing user account pools.
  2. Non-disruptive migration to UserClouds from an existing IDP, ideal for when you want to keep existing user accounts & credentials but transparently migrate users to UserClouds without disruption.
  3. Long-term use of a 3rd party IDP, fronted by Plex, ideal for augmenting your current Idnetity system with UserClouds' rich Authorization, Delegation, and User Data Vault features.

In all 3 cases, you can configure your application to authenticate users via Plex, and set up Plex Applications in the Developer Console which are backed by UserClouds' IDP and/or a 3rd party IDP. This lets you control where the "source-of-truth" for authentication lives, while allowing you to leverage UserClouds features at any layer of the stack.

Getting Started

Setting up authentication in your application with UserClouds is a breeze using the OAuth2/OIDC libraries/frameworks available in virtually every major langauge.

Currently, UserClouds supports standard OAuth2 and OpenID Connect (OIDC) methods for authenticating users and non-user/service accounts across a variety of environments: web, mobile, server, machine-to-machine (M2M), etc.

To authenticate users or non-users, an application triggers an authentication "flow", which consists of 1 or more steps that allow a user or non-user account to prove their identity. On success, the application receives one or more tokens (typically JWTs) which attest to the identity (and possibly permissions) of the user or non-user account. An application here may refer to code running on a web/mobile/desktop client, server, etc. The specific flow you should use depends on the structure, trust model, and needs of the application. ID tokens are used to confirm identity, while Access Tokens are used to confirm permissions or scopes for a particular application. They are similar conceptually but should not be used interchangeably for security reasons.

For users to sign in your app, there are a few primary/recommended "flows":

  1. Authorization Code Flow.
  2. Hybrid Flow
  3. Implicit Flow

Which flow you use depends on whether your application can securely store secrets (clients generally can't, while servers generally can), how & where the resulting ID and Access Tokens will be used (if at all), and how much you value flexibility/simplicity vs. a tightly controlled user experience on login.

To authenticate non-user services/machines (which must be able to store a secret), applications should use the Client Credentials Flow.

Authorization Code Flow (with or without Proof Key Code Exchange)

import "golang.org/x/oauth2"

prov, _ := oidc.NewProvider(context.Background(), "https://sample.tenant.userclouds.com")

oauthConfig := oauth2.Config{
  ClientID:     "5f107e226353791560f93164a09f7e0f",
  Endpoint:     prov.Endpoint(),
  RedirectURL:  "https://contoso.com/callback",
  Scopes:       []string{"openid <ADDITIONAL_SCOPES>"},
}

Without PKCE:

GET /oidc/authorize?response_type=code&client_id=5f107e226353791560f93164a09f7e0f&redirect_uri=https%3A%2F%contoso.com%2Fcallback&scope=openid+profile+email&state=n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk HTTP/1.1
Host: sample.tenant.userclouds.com
curl 'https://sample.tenant.userclouds.com/oidc/authorize?response_type=code&client_id=5f107e226353791560f93164a09f7e0f&redirect_uri=https%3A%2F%contoso.com%2Fcallback&&scope=openid+profile+email&state=n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk'
// Authorization Code Flow without Proof Key Code Exchange (PKCE)
url := oauthConfig.AuthCodeURL("n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk")

// Redirect user agent to URL authorize endpoint
http.Redirect(w, r, url, http.StatusTemporaryRedirect)

With PKCE:

GET /oidc/authorize?response_type=code&client_id=5f107e226353791560f93164a09f7e0f&redirect_uri=https%3A%2F%contoso.com%2Fcallback&scope=openid+profile+email&state=n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk&code_challenge=fJy4Nvl38sFmKyYUMZC1klsg9kn5HKXDUHEdeIuZnyc&code_challenge_method=S256 HTTP/1.1
Host: sample.tenant.userclouds.com
curl 'https://sample.tenant.userclouds.com/oidc/authorize?response_type=code&client_id=5f107e226353791560f93164a09f7e0f&redirect_uri=https%3A%2F%contoso.com%2Fcallback&&scope=openid+profile+email&state=n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk&code_challenge=fJy4Nvl38sFmKyYUMZC1klsg9kn5HKXDUHEdeIuZnyc&code_challenge_method=S256'
// Authorization Code Flow *with* Proof Key Code Exchange (PKCE) using SHA256 (the only supported method)
url := oauthConfig.AuthCodeURL(
  state,
  oauth.SetAuthURLParam("code_challenge_method", "S256"),
  oauth.SetAuthURLParam("code_challenge", "<CODE_CHALLENGE>"))

// Redirect user agent to URL authorize endpoint
http.Redirect(w, r, url, http.StatusTemporaryRedirect)

The Authorization Code flow is the most commonly used and recommended way for client applications (web, mobile) to allow users to log in.

If the application can be trusted to hold a secret (e.g. a web application with secure backend), the standard Authorization Code flow can be used.

If the application cannot securely hold a secret (e.g. web single-page app or mobile app), and particularly if access tokens are needed, it should utilize the Proof Key Code Exchange feature to prevent token hijacking.

Request

Because this is a GET request, all parameters should be specified as query parameters in the URL.

Parameter Type Required? Description
response_type string yes code
client_id string yes The Client ID of a registered app/client in your UserClouds tenant.
redirect_uri string yes A URL to your application where the user agent will be redirected on completion. Must use https:// for production web apps, or a mobile custom scheme for mobile apps. Can use http:// for localhost and development tenants.
scope string yes Must specify openid in order to get an ID token from the token exchange endpoint later. May also specify profile, email, or other common scopes (see OIDC Spec for details).
state string yes An application-defined value used for 2 purpose: encode application state/context for a request, and to prevent CSRF attacks. See OAuth Security Topics for details.
code_challenge_method string no Indicates that PKCE should be used with a given method. Only 'S256' (SHA 256) is currently supported.
code_challenge string no A value generated by applying code_challenge_method (i.e. SHA 256) to a code_verifier value generated by the client. See the PKCE spec for more details. NOTE: this value is required iff code_challenge_method is specified.

Response

On Success:

HTTP/1.1 302 Found

Location: https://contoso.com/callback?code=VieHyGShFqT57%2FjSeqTxQQEraGKhkYK0IMIyFzRRziQKy6G7eMPXDy0s8AiWSwNy&state=n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk

On Error:

HTTP/1.1 302 Found

Location: https://contoso.com/callback?error=invalid_grant&error_description=The+credentials+were+invalid

If the request is valid, the immediate GET call to the authorize endpoint will redirect to Plex's internal endpoint(s) for the user to perform an interactive login. After the user sucessfully authenticates (or in case of an error in the process), the user agent will ultimately be redirected (HTTP 302) to the application-provided (and pre-registered) redirect URL, unless the redirect URL and/or Client ID are invalid (in which case the response will be a 400 Bad Request).

Parameter Type Condition Description
code string success Cryptographically secure token which can be exchanged with the Token endpoint.
state string success The application-defined value passed in to the Authorize call. The client should validate that this matches to prevent attacks (hijacks, replays, etc.).
error string failure One of the OAuth/OIDC-spec defined error values. See the OAuth 2.0 spec for more details.
error_description string failure A human readable explanation of the error.

Hybrid Flow

Docs coming soon.

Implicit Flow with Form Post

Docs coming soon.

Token Exchange for Authorization Code Flow (with or without Proof Key Code Exchange)

To exchange an authorization code for an access and/or ID token, use this code:

POST /oidc/token HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&client_id=5f107e226353791560f93164a09f7e0f&client_secret=iStpcFf3gfiUjnsbWGFY0C9aWkPzDqT14eyp23ysKuI6iBbOAWcode=VieHyGShFqT57%2FjSeqTxQQEraGKhkYK0IMIyFzRRziQKy6G7eMPXDy0s8AiWSwNy&redirect_uri=https%3A%2F%contoso.com%2Fcallback&code_verifier=iyMU3Af48ZZSPCbJGSxaUGmUJa-6uGiyTq5dwOvuvpg
curl --X POST \
  -H 'content-type: application/x-www-form-urlencoded' \
  -d '{"response_type":"code", "client_id":"5f107e226353791560f93164a09f7e0f", "client_secret":"iStpcFf3gfiUjnsbWGFY0C9aWkPzDqT14eyp23ysKuI6iBbOAW", "code":"VieHyGShFqT57%2FjSeqTxQQEraGKhkYK0IMIyFzRRziQKy6G7eMPXDy0s8AiWSwNy", "redirect_uri":"https://contoso.com/callback" "code_verifier":"iyMU3Af48ZZSPCbJGSxaUGmUJa-6uGiyTq5dwOvuvpg"}'
  'https://sample.tenant.userclouds.com/oidc/token'
import "golang.org/x/oauth2"

prov, _ := oidc.NewProvider(context.Background(), "https://sample.tenant.userclouds.com")

oauthConfig := oauth2.Config{
  ClientID:     "5f107e226353791560f93164a09f7e0f",
  ClientSecret: "iStpcFf3gfiUjnsbWGFY0C9aWkPzDqT14eyp23ysKuI6iBbOAW", // Only specified when NOT using PKCE
  Endpoint:     prov.Endpoint(),
  RedirectURL:  "https://contoso.com/callback",
}

// Authorization Code Flow without Proof Key Code Exchange (PKCE)
tokenResponse, err := oauthConfig.Exchange(ctx, "VieHyGShFqT57%2FjSeqTxQQEraGKhkYK0IMIyFzRRziQKy6G7eMPXDy0s8AiWSwNy")

// -- OR --

// Authorization Code Flow *with* Proof Key Code Exchange (PKCE) using SHA256 (the only supported method)
tokenResponse, err := oauthConfig.Exchange(ctx, "VieHyGShFqT57%2FjSeqTxQQEraGKhkYK0IMIyFzRRziQKy6G7eMPXDy0s8AiWSwNy", oauth.SetAuthURLParam("code_verifier", "iyMU3Af48ZZSPCbJGSxaUGmUJa-6uGiyTq5dwOvuvpg"))

if err { ... }

rawIDToken, ok := tokenResponse.Extra("id_token").(string)
if !ok { ... }

accessToken := tokenResponse.AccessToken

The application uses this endpoint to exchange the code (returned after successful authorization) for a access_token and/or id_token (depending on the authorization flow used).

See Authorization Code Flow and Hybrid Flow for details on how to get a code in the first place.

Request

This is a POST request with all parameters form encoded in the body.

Parameter Type Required? Description
grant_type string yes authorization_code
client_id string yes The Client ID of a registered app/client in your UserClouds tenant.
client_secret string no The Client Secret of a registered app/client in your UserClouds tenant. Note that this is used only for the non-PKCE flow.
redirect_uri string yes A URL to your application where the user agent will be redirected on completion. Must use https:// for production web apps, or a mobile custom scheme for mobile apps. Can use http:// for localhost and development tenants.
code_verifier string no If PKCE was used to issue the authorization code, then this value must be specified and valid for the token exchange instead of client_secret. See the PKCE spec for more details.

Response

TODO: refresh token support, token expiry

HTTP/1.1 200 OK
Content-Type: application/json
{
  "access_token":"<ACCESS_TOKEN>",
  "id_token":"<ID_TOKEN>",
  "token_type":"Bearer",
}

If the request is valid, the endpoint returns a json struct with an access token and/or ID token (depending on the scopes of the original request), as well as the token type which is always "Bearer".

Parameter Type Condition Description
access_token string success Cryptographically secure token which can be used to make API calls.
id_token string success A raw three-part JWT which contains information about the resource owner / user.
token_type string success Always "Bearer"

Refresh Token Exchange

Docs coming soon.

Client Credentials Flow

Docs coming soon.

Social Login

To access the underlying social IDP's token (eg. to access Google APIs directly on behalf of the user)

GET /social/underlying HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer [access_token]

{
  "RawIDToken":"eyJ...",
  "AccessToken":"ya29...",
  "Profile": {
    "email":"me@example.org",
    "email_verified":true,
    "family_name":"Mine",
    "given_name":"Me",
    "hd":"example.org",
    "locale":"en",
    "name":"Me Mine",
    "picture":"https://lh3.googleusercontent.com/a/...",
    "sub":"123"
  },
  "Claims": {
    "name":"Me Mine",
    "email":"me@exampke.org",
    "email_verified":true,
    "picture":"https://lh3.googleusercontent.com/a/...",
    "sub":"123"
  }
}
curl -X GET \
  -H 'Authorization: Bearer [access_token]'
https://sample.tenant.userclouds.com/social/underlying

Plex exposes the underlying social tokens to enable using Google / Facebook / etc APIs directly if your application requires that.

Calling this endpoint requires the access token of the user who logged in via social login. (Note: we have plans in the future to enable offline access to these tokens using M2M auth, but haven't rolled it out yet).

Please contact support@userclouds.com to enable this, as it is disabled by default for security reasons.

Invites

Send Invite

TODO: should "expires" be an int64 unix timestamp?

TODO: bearer token

POST /invite/send HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json

{
  "invitee_email": "alice@contoso.com",
  "inviter_user_id": "68d69e31-6423-43e7-8e1b-c44956360410",
  "client_id": "5f107e226353791560f93164a09f7e0f",
  "state": "n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk",
  "redirect_url": "https://contoso.com/invitecallback",
  "invite_text": "Alice is inviting you to join the group",
  "expires": "2022-03-28T01:48:31.267756Z"
}
curl -X POST \
  -H 'Content-Type: application/json' \
  -d '{ "invitee_email": "alice@contoso.com", "inviter_user_id": "68d69e31-6423-43e7-8e1b-c44956360410", "client_id": "5f107e226353791560f93164a09f7e0f", "state": "n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk", "redirect_url": "https://contoso.com/invitecallback", "invite_text": "Alice is inviting you to join the group", "expires": "2022-03-28T01:48:31.267756Z" }' 'https://sample.tenant.userclouds.com/invite/send'
plexClient := plex.NewClient("https://sample.tenant.userclouds.com")
inviteReq := plex.SendInviteRequest{
  InviteeEmail:  "alice@contoso.com",
  InviterUserID: "68d69e31-6423-43e7-8e1b-c44956360410",
  ClientID:      "5f107e226353791560f93164a09f7e0f",
  State:         "n9ftgCrrLNQ7sfxnnFmNcabEn8hFvAypP6Hu625WtBk",
  RedirectURL:   "https://contoso.com/invitecallback",
  InviteText:    "Alice is inviting you to join the group",
  Expires:       time.Now().UTC().Add(time.Hour * 24 * 30),
}

if err := plexClient.SendInvite(ctx, inviteReq); err != nil {
  ...
}

Plex supports inviting users to join a tenant, which serves 3 main purposes:

  1. Reduce friction for new users to sign-up & sign-in to your application by emailing them a magic link which takes them to the right place to sign up or sign in to an existing account.
  2. Limit new user sign-ups for an application to only users who have been invited. NOTE: invites may still be useful even if a tenant allows new user sign ups.
  3. Perform special one-time actions (e.g. add user to a group, confer new permissions, etc) associated with the invite.

Once a user acts on an invite and either signs up for a new account or signs in with an existing account, their user agent will be redirected to the callback URL provided in the request which allows your application to perform one-time actions for a newly invited user.

Request

Parameter Type Required? Description
invitee_email string yes Email address of user to be invited
inviter_user_id string yes User ID of the inviting user. It's a string, not a UUID, because the format depends on the underlying IDP (UUIDs for UserClouds, strings for others)
client_id string yes Client ID of the app within the tenant that the invite is intended for (though the user will be invited to the overall tenant user pool, specific client IDs may have different rules)
state string yes An application-defined value used for 2 purpose: encode application state/context for a request, and to prevent CSRF attacks. See OAuth Security Topics for details.
redirect_uri string yes A URL to your application where the user agent will be redirected after successfully accepting the invite. Must use https:// for production web apps, or a mobile custom scheme for mobile apps. Can use http:// for localhost and development tenants.
invite_text string no An optional tag line included in the invite to provide app-specific or custom context.
expires datetime no An optional expiration time for the invite. If not specified, defaults to 1 week.

Response

HTTP/1.1 204 No Content

204 No Content on success, or one of the following errors:

Code Reason
400 TODO
401 TODO

Authorization

List Objects

GET /authz/objects HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/objects/'
c := authz.NewClient("https://sample.tenant.userclouds.com")
objs, err := c.ListObjects(ctx)
fmt.Printf("Object count: %d, objects: %v", len(objs), objs

Lists all objects in the AuthZ system for a given tenant.

Request

Parameter Type Required Description
name query optional Alias of the object to filter on. Must currently be specified with 'type_id'.
type_id query optional Type ID of the object type to filter on. Must currently be specified with 'name'.

TODO: rename 'name' to 'alias' for consistency.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

[{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "created":"2022-03-28T21:43:36.099293Z",
  "updated":"2022-03-28T21:43:36.099293Z",
  "deleted":"0001-01-01T00:00:00Z",
  "alias":"some widget",
  "type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c"
},{
  "id":"1f4b0b03-4af0-409a-9769-50ce59526956",
  "created":"2022-05-07T19:25:17.435965Z",
  "updated":"2022-05-07T19:25:17.435965Z",
  "deleted":"0001-01-01T00:00:00Z",
  "alias":"a wodget",
  "type_id":"2476b545-9d7b-4606-aa14-491add99213c"
}]
Parameter Type Description
id UUIDv4 ID of the object retrieved.
created datetime Timestamp of the object's creation.
updated datetime Timestamp of the object's most recent update.
deleted datetime Timestamp of the object's deletion, or the "0" timestamp if alive.
alias string Application-provided human-readable alias for the object.
type_id UUIDv4 ID of the object type.

Get Object

GET /authz/objects/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/objects/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := authz.NewClient("https://sample.tenant.userclouds.com")
obj, err := c.GetObject(ctx, uuid.Must(uuid.FromString('60b2f286-f051-444f-9b08-4b67129dcb7b')))
fmt.Printf("Object type ID: %s, alias: %s", obj.TypeID, obj.Alias)

Retrieves a single AuthZ object by ID. If the ID provided is that of a User in the IDP, it rerturns an object representing the user.

Request

Parameter Type Required Description
/objects/{id} UUIDv4 (in path) yes ID of the object to get.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "created":"2022-03-28T21:43:36.099293Z",
  "updated":"2022-03-28T21:43:36.099293Z",
  "deleted":"0001-01-01T00:00:00Z",
  "alias":"some widget",
  "type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the object retrieved.
created datetime Timestamp of the object's creation.
updated datetime Timestamp of the object's most recent update.
deleted datetime Timestamp of the object's deletion, or the "0" timestamp if alive.
alias string Application-provided human-readable alias for the object.
type_id UUIDv4 ID of the object type.

Create Object

POST /authz/objecttypes HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "type_id":"8775116f-86cd-4f44-8023-e3108a901abd",
  "alias":"blue widget",
}
curl -X 'POST' \
  -H 'Content-Type: application/json' \
  -d '{"id":"60b2f286-f051-444f-9b08-4b67129dcb7b", type_id":"8775116f-86cd-4f44-8023-e3108a901abd", "alias":"blue widget"}' \
  'https://sample.tenant.userclouds.com/authz/objects'
c := authz.NewClient("https://sample.tenant.userclouds.com")
object, err := c.CreateObject(ctx, uuid.Must(uuid.NewV4()), uuid.Must(uuid.FromString("8775116f-86cd-4f44-8023-e3108a901abd")), "blue widget")

Creates an object with a given ID, Type ID, and Alias. See Create Object Type for details on how to create an object type.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the newly created object.
type_id UUIDv4 yes Existing Type ID of the object's type.
alias string yes Application-provided human-readable alias for the object

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "created":"2022-03-28T21:43:36.099293Z",
  "updated":"2022-03-28T21:43:36.099293Z",
  "deleted":"0001-01-01T00:00:00Z",
  "alias":"some widget",
  "type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the newly created object.
created datetime Timestamp of the object's creation.
updated datetime Timestamp of the object's most recent update.
deleted datetime Timestamp of the object's deletion, or the "0" timestamp if alive.
type_id UUIDv4 Existing Type ID of the object's type.
alias string Application-provided human-readable alias for the object

Update Object

POST /authz/objects HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "type_id":"8775116f-86cd-4f44-8023-e3108a901abd",
  "alias":"new alias",
}
curl -X 'POST' \
  -H 'Content-Type: application/json' \
  -d '{"id":"60b2f286-f051-444f-9b08-4b67129dcb7b", type_id":"8775116f-86cd-4f44-8023-e3108a901abd", "alias":"new alias"}' \
  'https://sample.tenant.userclouds.com/authz/objects'
c := authz.NewClient("https://sample.tenant.userclouds.com")
// NOTE: separate client method for update coming soon
object, err := c.CreateObject(ctx, uuid.FromStringOrNil("60b69666-4a8a-4eb3-94dd-621298fb365d"), uuid.FromStringOrNil("8775116f-86cd-4f44-8023-e3108a901abd"), "new alias")

Update an object with a given ID, Type ID, and Alias. The Type ID cannot be changed in an Update operation, because doing so would invalidate existing edges (which are strongly typed).

Request

Parameter Type Required Description
id UUIDv4 yes ID of the existing object.
type_id UUIDv4 yes Existing Type ID of the object's type. Must not change from original creation.
alias string yes Application-provided human-readable alias for the object

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "created":"2022-03-28T21:43:36.099293Z",
  "updated":"2022-03-28T21:43:36.099293Z",
  "deleted":"0001-01-01T00:00:00Z",
  "alias":"some widget",
  "type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the existing created object.
created datetime Timestamp of the object's creation.
updated datetime Timestamp of the object's most recent update.
deleted datetime Timestamp of the object's deletion, or the "0" timestamp if alive.
type_id UUIDv4 Existing Type ID of the object's type.
alias string Application-provided human-readable alias for the object

Delete Object

DELETE /authz/objects/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'DELETE' \
  'https://sample.tenant.userclouds.com/authz/objects/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := authz.NewClient("https://sample.tenant.userclouds.com")
err := c.DeleteObject(ctx, uuid.Must(uuid.FromString('60b2f286-f051-444f-9b08-4b67129dcb7b')))

Delete an object with the given ID.

Request

Parameter Type Required Description
/objects/{id} UUIDv4 (in path) yes ID of the object to delete.

Response

HTTP/1.1 204 No Content

204 No Content on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Object with ID not found
500 Internal error occurred processing the request

List Edges On Object

GET /authz/objects/60b2f286-f051-444f-9b08-4b67129dcb7b/edges HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/objects/60b2f286-f051-444f-9b08-4b67129dcb7b/edges'
c := authz.NewClient("https://sample.tenant.userclouds.com")
err := c.ListEdges(ctx, uuid.Must(uuid.FromString('60b2f286-f051-444f-9b08-4b67129dcb7b')))

List all incoming and outgoing edges on an object (i.e. all edges where the provided object is a source or target).

Request

Parameter Type Required Description
/objects/{id} UUIDv4 (in path) yes ID of the object to list edges for.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

[
  {
    "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
    "created":"2022-03-28T21:43:36.099293Z",
    "updated":"2022-03-28T21:43:36.099293Z",
    "deleted":"0001-01-01T00:00:00Z",
    "edge_type_id":"79c68abe-6227-4a2f-a2eb-6d7bc8e86766",
    "source_object_id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
    "target_object_id":"70a8c988-265a-494d-81f5-43bc4bbd0df8"
  }
]

200 OK on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Object with ID not found
500 Internal error occurred processing the request

List Edges Between Objects

GET /authz/edges?source_object_id=60b2f286-f051-444f-9b08-4b67129dcb7b&target_object_id=70a8c988-265a-494d-81f5-43bc4bbd0df8 HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/authz/edges?source_object_id=60b2f286-f051-444f-9b08-4b67129dcb7b&target_object_id=70a8c988-265a-494d-81f5-43bc4bbd0df8'
c := authz.NewClient("https://sample.tenant.userclouds.com")
err := c.ListEdgesBetweenObjects(ctx,
                                 uuid.Must(uuid.FromString('60b2f286-f051-444f-9b08-4b67129dcb7b')),
                                 uuid.Must(uuid.FromString('70a8c988-265a-494d-81f5-43bc4bbd0df8')))

List all edges between two objects.

Request

Parameter Type Required Description
source_object_id UUIDv4 yes ID of the source object to list edges for.
target_object_id UUIDv4 yes ID of the source object to list edges for.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

[
  {
    "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
    "created":"2022-03-28T21:43:36.099293Z",
    "updated":"2022-03-28T21:43:36.099293Z",
    "deleted":"0001-01-01T00:00:00Z",
    "edge_type_id":"79c68abe-6227-4a2f-a2eb-6d7bc8e86766",
    "source_object_id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
    "target_object_id":"70a8c988-265a-494d-81f5-43bc4bbd0df8"
  }
]

200 OK on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Object with ID not found
500 Internal error occurred processing the request

Get Edge

GET /authz/edges/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/authz/edges/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := authz.NewClient("https://sample.tenant.userclouds.com")
err := c.GetEdge(ctx, uuid.Must(uuid.FromString('60b2f286-f051-444f-9b08-4b67129dcb7b')))

Describe an edge given its edge ID.

Request

Parameter Type Required Description
/edges/[ID] UUIDv4 (in path) yes ID of the edge

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

[
  {
    "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
    "created":"2022-03-28T21:43:36.099293Z",
    "updated":"2022-03-28T21:43:36.099293Z",
    "deleted":"0001-01-01T00:00:00Z",
    "edge_type_id":"79c68abe-6227-4a2f-a2eb-6d7bc8e86766",
    "source_object_id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
    "target_object_id":"70a8c988-265a-494d-81f5-43bc4bbd0df8"
  }
]

200 OK on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Edge with ID not found
500 Internal error occurred processing the request

Create Edge

POST /authz/edges HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
  "id":"8775116f-86cd-4f44-8023-e3108a901abd",
  "source_object_id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "target_object_id":"70a8c988-265a-494d-81f5-43bc4bbd0df8",
  "edge_type_id":"79c68abe-6227-4a2f-a2eb-6d7bc8e86766"
}
curl -X 'POST' \
  -H 'Content-Type: application/json' \
  -d '{"id":"8775116f-86cd-4f44-8023-e3108a901abd","source_object_id":"60b2f286-f051-444f-9b08-4b67129dcb7b","target_object_id":"70a8c988-265a-494d-81f5-43bc4bbd0df8","edge_type_id":"79c68abe-6227-4a2f-a2eb-6d7bc8e86766"}' \
  'https://sample.tenant.userclouds.com/authz/edges'
c := authz.NewClient("https://sample.tenant.userclouds.com")
objectType, err := c.CreateEdge(ctx,
                                uuid.Must(uuid.NewV4()),
                                uuid.Must(uuid.FromString("60b2f286-f051-444f-9b08-4b67129dcb7b")),
                                uuid.Must(uuid.FromString("70a8c988-265a-494d-81f5-43bc4bbd0df8")),
                                uuid.Must(uuid.FromString("79c68abe-6227-4a2f-a2eb-6d7bc8e86766")))

Create a directed edge of a given type between a specified 'source' and 'target' objects.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the newly created edge.
source_object_id UUIDv4 yes ID of the source object.
target_object_id UUIDv4 yes ID of the target object.
edge_type_id UUIDv4 yes ID of the edge type.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"8775116f-86cd-4f44-8023-e3108a901abd",
  "created":"2022-03-28T21:43:36.099293Z",
  "updated":"2022-03-28T21:43:36.099293Z",
  "deleted":"0001-01-01T00:00:00Z",
  "source_object_id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "target_object_id":"70a8c988-265a-494d-81f5-43bc4bbd0df8",
  "edge_type_id":"79c68abe-6227-4a2f-a2eb-6d7bc8e86766"
}
Parameter Type Description
id UUIDv4 ID of the newly created object.
created datetime Timestamp of the object type's creation.
updated datetime Timestamp of the object type's most recent update.
deleted datetime Timestamp of the object type's deletion, or the "0" timestamp if alive.
source_object_id UUIDv4 ID of the source object.
target_object_id UUIDv4 ID of the target object.
edge_type_id UUIDv4 ID of the edge type.

Delete Edge

DELETE /authz/edges/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'DELETE' \
  'https://sample.tenant.userclouds.com/authz/edges/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := authz.NewClient("https://sample.tenant.userclouds.com")
err := c.DeleteEdge(ctx, uuid.Must(uuid.FromString('60b2f286-f051-444f-9b08-4b67129dcb7b')))

Delete an edge by its ID.

Request

Parameter Type Required Description
/edges/{id} UUIDv4 (in path) yes ID of the object to delete.

Response

HTTP/1.1 204 No Content

204 No Content on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Edge with ID not found
500 Internal error occurred processing the request

List Object Types

GET /authz/objecttypes HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/authz/objecttypes'
c := authz.NewClient("https://sample.tenant.userclouds.com")
objectTypes, err := c.ListObjectTypes(ctx)

Lists all registered object types for this tenant.

Request

No parameters

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
[{
  "id":"1634c490-20dc-4ded-abd1-9d2cafd8f08a",
  "created":"2022-05-06T20:58:46.978552Z",
  "updated":"2022-05-06T20:58:46.978552Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"widget"
},{
  "id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe",
  "created":"2022-03-30T03:10:28.169178Z",
  "updated":"2022-04-30T21:16:01.763461Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"_user"
},{
  "id":"f5bce640-f866-4464-af1a-9e7474c4a90c",
  "created":"2022-03-30T03:10:28.132552Z",
  "updated":"2022-04-30T21:16:01.741283Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"_group"
}]
Parameter Type Description
id UUIDv4 ID of the object type.
created datetime Timestamp of the object type's creation.
updated datetime Timestamp of the object type's most recent update.
deleted datetime Timestamp of the object type's deletion, or the "0" timestamp if alive.
type_name string Application-provided human-readable name for the object type

Get Object Type

GET /authz/objecttypes/60b69666-4a8a-4eb3-94dd-621298fb365d HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/authz/objecttypes/60b69666-4a8a-4eb3-94dd-621298fb365d'
c := authz.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.GetObjectType(ctx, uuid.FromStringOrNil("60b69666-4a8a-4eb3-94dd-621298fb365d"))

Gets the definition of a single object type.

Request

Parameter Type Required Description
/objecttypes/{id} UUIDv4 (in path) yes ID of the object type to get.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"069d6e9a-f31f-4514-a37f-78e8fdace9e0",
  "created":"2022-05-07T01:34:57.405258Z",
  "updated":"2022-05-07T01:34:57.405258Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"widget_owner"
}
Parameter Type Description
id UUIDv4 ID of the edge type.
created datetime Timestamp of the edge type's creation.
updated datetime Timestamp of the edge type's most recent update.
deleted datetime Timestamp of the edge type's deletion, or the "0" timestamp if alive.
type_name string Application-provided human-readable name for the edge type.

Create Object Type

POST /authz/objecttypes HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
  "id":"8775116f-86cd-4f44-8023-e3108a901abd",
  "type_name":"widget",
}
curl -X 'POST' \
  -H 'Content-Type: application/json' \
  -d '{"id":"8775116f-86cd-4f44-8023-e3108a901abd","type_name":"widget"}' \
  'https://sample.tenant.userclouds.com/authz/objecttypes'
c := authz.NewClient("https://sample.tenant.userclouds.com")
objectType, err := c.CreateObjectType(ctx, uuid.Must(uuid.NewV4()), "widget")

Creates a new object type.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the newly created object.
type_name string yes Application-provided human-readable name for the object type.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "created":"2022-03-28T21:43:36.099293Z",
  "updated":"2022-03-28T21:43:36.099293Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"widget",
}
Parameter Type Description
id UUIDv4 ID of the newly created object.
created datetime Timestamp of the object type's creation.
updated datetime Timestamp of the object type's most recent update.
deleted datetime Timestamp of the object type's deletion, or the "0" timestamp if alive.
type_name string Application-provided human-readable name for the object type.

Delete Object Type

DELETE /authz/objecttypes/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'DELETE' \
  'https://sample.tenant.userclouds.com/objecttypes/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := authz.NewClient("https://sample.tenant.userclouds.com")
err := c.DeleteObjectType(ctx, uuid.FromStringOrNil("60b2f286-f051-444f-9b08-4b67129dcb7b"))

Delete a previously-registered object type with a given ID.

Request

Parameter Type Required Description
/objecttypes/{id} UUIDv4 (in path) yes ID of the object type to delete.

Response

HTTP/1.1 204 No Content

204 No Content on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Object with ID not found
500 Internal error occurred processing the request

List Edge Types

GET /authz/edgetypes HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/authz/edgetypes'
c := authz.NewClient("https://sample.tenant.userclouds.com")
edgeTypes, err := c.ListEdgeTypes(ctx)

Lists all registered edge types for this tenant.

Request

No parameters

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

[{
  "id":"069d6e9a-f31f-4514-a37f-78e8fdace9e0",
  "created":"2022-05-07T01:34:57.405258Z",
  "updated":"2022-05-07T01:34:57.405258Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"widget_owner",
  "source_object_type_id":"2476b545-9d7b-4606-aa14-491add99213c",
  "target_object_type_id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe"
},{
  "id":"1eec16ec-6130-4f9e-a51f-21bc19b20d8f",
  "created":"2022-03-30T03:10:28.301931Z",
  "updated":"2022-04-30T21:16:01.844554Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"_member",
  "source_object_type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c",
  "target_object_type_id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe"
},{
  "id":"60b69666-4a8a-4eb3-94dd-621298fb365d",
  "created":"2022-03-30T03:10:28.269905Z",
  "updated":"2022-04-30T21:16:01.813831Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"_admin",
  "source_object_type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c",
  "target_object_type_id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe"
}]
Parameter Type Description
id UUIDv4 ID of the edge type.
created datetime Timestamp of the edge type's creation.
updated datetime Timestamp of the edge type's most recent update.
deleted datetime Timestamp of the edge type's deletion, or the "0" timestamp if alive.
type_name string Application-provided human-readable name for the edge type.

Get Edge Type

GET /authz/edgetypes/60b69666-4a8a-4eb3-94dd-621298fb365d HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
  'https://sample.tenant.userclouds.com/authz/edgetypes/60b69666-4a8a-4eb3-94dd-621298fb365d'
c := authz.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.GetEdgeType(ctx, uuid.FromStringOrNil("60b69666-4a8a-4eb3-94dd-621298fb365d"))

Gets the definition of a single edge type.

Request

Parameter Type Required Description
/edgetypes/{id} UUIDv4 (in path) yes ID of the edge type to get.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"069d6e9a-f31f-4514-a37f-78e8fdace9e0",
  "created":"2022-05-07T01:34:57.405258Z",
  "updated":"2022-05-07T01:34:57.405258Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"widget_owner",
  "source_object_type_id":"2476b545-9d7b-4606-aa14-491add99213c",
  "target_object_type_id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe"
}
Parameter Type Description
id UUIDv4 ID of the edge type.
created datetime Timestamp of the edge type's creation.
updated datetime Timestamp of the edge type's most recent update.
deleted datetime Timestamp of the edge type's deletion, or the "0" timestamp if alive.
type_name string Application-provided human-readable name for the edge type.

Create Edge Type

POST /authz/edgetypes HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
  "id":"8775116f-86cd-4f44-8023-e3108a901abd",
  "type_name":"invitee",
  "source_object_type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c",
  "target_object_type_id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe"
}
curl -X 'POST' \
  -H 'Content-Type: application/json' \
  -d '{"id":"8775116f-86cd-4f44-8023-e3108a901abd","type_name":"invitee","source_object_type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c","target_object_type_id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe"}' \
  'https://sample.tenant.userclouds.com/authz/edgetypes'
c := authz.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.CreateEdgeType(ctx, uuid.Must(uuid.NewV4()), uuid.Must(uuid.FromString('f5bce640-f866-4464-af1a-9e7474c4a90c')), uuid.Must(uuid.FromString('1bf2b775-e521-41d3-8b7e-78e89427e6fe')), "invitee")

Creates a new edge (relationship) type.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the newly created edge type.
type_name string yes Application-provided human-readable name for the edge (relationship) type.
source_object_id UUIDv4 yes Object Type ID to enforce for the "source" / "from" object for edges of this edge type.
target_object_id UUIDv4 yes Object Type ID to enforce for the "target" / "to" object for edges of this edge type.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
  "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
  "created":"2022-03-28T21:43:36.099293Z",
  "updated":"2022-03-28T21:43:36.099293Z",
  "deleted":"0001-01-01T00:00:00Z",
  "type_name":"invitee",
  "source_object_type_id":"f5bce640-f866-4464-af1a-9e7474c4a90c",
  "target_object_type_id":"1bf2b775-e521-41d3-8b7e-78e89427e6fe"
}
Parameter Type Description
id UUIDv4 ID of the newly created edge type.
created datetime Timestamp of the object type's creation.
updated datetime Timestamp of the object type's most recent update.
deleted datetime Timestamp of the object type's deletion, or the "0" timestamp if alive.
type_name string Application-provided human-readable name for the edge type
source_object_id UUIDv4 Object Type ID to enforce for the "source" / "from" object for edges of this edge type.
target_object_id UUIDv4 Object Type ID to enforce for the "target" / "to" object for edges of this edge type.

Delete Edge Type

DELETE /authz/edgetypes/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'DELETE' \
  'https://sample.tenant.userclouds.com/edgetypes/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := authz.NewClient("https://sample.tenant.userclouds.com")
err := c.DeleteObjectType(ctx, uuid.FromStringOrNil("60b69666-4a8a-4eb3-94dd-621298fb365d"))

Delete a previously-registered edge type with a given ID.

Request

Parameter Type Required Description
/edgetypes/{id} UUIDv4 (in path) yes ID of the object type to delete.

Response

HTTP/1.1 204 No Content

204 No Content on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Object with ID not found
500 Internal error occurred processing the request

User Data Vault

Intro

Vault is a centralized data store for sensitive information such as PII combined together with a set of per-use accessor methods that describe the policies for accessing that data. Vault is meant to contain the only long lived copy of the data and other services/systems obtain data for it for a particular purpose and delete it once that purpose is complete. Vault is designed to improve privacy and security of data regardless of the stage of the compliance program. It helps the user both achieve more with minimal additional work today and provides continuous work savings through the lifetime of the technical systems. Vault can be gradually adopted for particular data types, or particular subsystems providing immediate benefits.

Instead of using a generic API/language for accessing data as is state of the art today, Vault encourages the user to define a per use custom accessor for each particular use of data. Most of the work to define the custom accessor is done by the system so that the developer doesn't have to do much more than they would to write a custom query against a generic API. Optionally additional work can be performed at definition time of the customer accessor depending on the company's security/privacy program such as associating it with a product/feature, referencing a document generated by an approval process, or attaching precise access policies. Regardless of optional work upfront each use of data can be audited, turned off, constrained without impacting other uses, or later labeled with additional documentation.

Vault includes a set of adapters to allow turn-key integrations with best in class third party services. These adapters (depending on the service being integrated) can remove, mask, tokenize, or make less precise the literal data flowing in the third party service without affecting operation of the service. Vault will help you get to a place where with a single click in the UI you can determine which data is used by product/feature for what purpose, which third party systems are involved in the operation of product/feature, and how the data involved is protected.

Configuration Concepts

The system is first configured by describing what columns are going to be in the user table and how they will be stored. Then the you describe how the data can be accessed and by who. You can add new accessor definitions as you need to use data for new purposes.

Three are three separate sets of APIs:

Management - the APIs for configuring and maintaining the user store and associated policies Operations - the APIs used for online, offline and adapter access to the user data Audit - the APIs used for compliance purposes to verify, confirm correctness and integrate with internal processes such as approval flows and documentation

User store management APIs can be thought as a set of configuration files:

The changes to configuration can be made through UserClouds console requiring no coding, through UserClouds API, or through bulk upload of the new configuration file. Regardless, each configuration change is subject to the same approval flow and is recorded for audit purposes. Not all configuration changes are reversible without data loss so testing configuration changes in your development environment prior to production deployment is best practice

From the client side the user store can be expressed in a SQL, GraphQL or another preferred data fetching language via one of our SDKs or a custom SDK for your use case. This allows the client code to be written in a way that is agnostic to the infrastructure being used for storing user data or for ease of migration of existing code to User Data Vault.

Column Configuration

Describe sample user store in GraphQL

type User {
 id: String! @ocolumn id
 name: String! @column name
 address: [Address!]! @column address
 phone: String! @column phone
 classes: [String!]! @column classes
}
enum AddressType {
 HOME
 OFFICE
 OTHER
}
type Address {
  type: AddressType! @column composite
  street: String! @column composite
  houseNumber: Int @column composite
  zip: Int @column composite
}
type Query {
 user(areaCode: String!): User
}

Describe sample user store in SQL

CREATE TABLE Users (
    id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    phone VARCHAR(255) NOT NULL,
    address JSON NOT NULL,
    classes JSON NOT NULL
)  ENGINE=USERCLOUDS;

Each column in the user data store has the following configuration fields:

The columns are limited in size and are not meant for storing bulk data. Instead you should store metadata, encryption keys and references to the bulk data in another store.

The columns can be defined via UserClouds console, CRUD API for columns or bulk updated via file upload. Column deletion doesn’t result in data deletion - instead the column is marked as deleted and can be removed via a separate operation.

There is a set of predefined columns that can’t be deleted:

Create Column

POST /userstore/config/columns HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "column_name":"FirstName",
 "primitive_type":"string",
 "logical_type":"Name-First",
 "purpose":"Product_Improvement, Integrity, Product_Operation",
 "global_access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
curl -X 'POST' \
 -H 'Content-Type: application/json' \
 -d '{"id":"8775116f-86cd-4f44-8023-e3108a901abd","column_name":"FirstName",  "primitive_type":"string",  "logical_type":"Name-First",
 "purpose":"Product_Improvement, Integrity, Product_Operation","global_access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"' \
 'https://sample.tenant.userclouds.com/userstore/config/columns'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.CreateColumn(ctx, uuid.Must(uuid.NewV4()), uuid.Must(uuid.FromString('f5bce640-f866-4464-af1a-9e7474c4a90c')), "FirstName", "string", "Name-First", "Product_Improvement, Integrity, Product_Operation")

Creates a new column in the datastore.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the newly created column type.
column_name string yes Application-provided human-readable name for the column.
primitive_type string yes Currently "string", "integer" and "uuid" are supported
logical_type string yes One of the UserClouds defined types or "custom"
purpose string yes A comma separated list of purposes
glo_access_policy_id UUIDv4 no ID of a policy to base access policy to the data.
geo_policy_id UUIDv4 no ID of a policy to describe which regions the data should stored in
enc_policy_id UUIDv4 no ID of a policy to describe encryption method for the data

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
 "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
 "created":"2022-03-28T21:43:36.099293Z",
 "updated":"2022-03-28T21:43:36.099293Z",
 "deleted":"0001-01-01T00:00:00Z",
 "column_name":"FirstName",
 "primitive_type":"string",
 "logical_type":"Name-First",
 "purpose":"Product_Improvement, Integrity, Product_Operation",
 "global_access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the newly created column.
created datetime Timestamp of the column's creation.
updated datetime Timestamp of the columns's most recent update.
deleted datetime Timestamp of the column's deletion, or the "0" timestamp if alive.
column_name string Application-provided human-readable name for the column.
primitive_type string Currently "string", "integer" and "uuid" are supported
logical_type string One of the UserClouds defined types or "custom"
purpose string A comma separated list of purposes
glo_access_policy_id UUIDv4 ID of a policy to base access policy to the data.
geo_policy_id UUIDv4 ID of a policy to describe which regions the data should stored in
enc_policy_id UUIDv4 ID of a policy to describe encryption method for the data

Get Column

GET /userstore/config/columns/8775116f-86cd-4f44-8023-e3108a901abd HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
 'https://sample.tenant.userclouds.com/userstore/config/columns/8775116f-86cd-4f44-8023-e3108a901abd'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.GetColumn(ctx, uuid.FromStringOrNil("8775116f-86cd-4f44-8023-e3108a901abd))

Gets an existing column's configuration by its id.

Request

Parameter Type Required Description
/columns/{id} UUIDv4 (in path) yes ID of the column to get.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "created":"2022-03-28T21:43:36.099293Z",
 "updated":"2022-03-28T21:43:36.099293Z",
 "deleted":"0001-01-01T00:00:00Z",
 "column_name":"FirstName",
 "primitive_type":"string",
 "logical_type":"Name-First",
 "purpose":"Product_Improvement, Integrity, Product_Operation",
 "global_access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the newly created column.
created datetime Timestamp of the column's creation.
updated datetime Timestamp of the columns's most recent update.
deleted datetime Timestamp of the column's deletion, or the "0" timestamp if alive.
column_name string Application-provided human-readable name for the column.
primitive_type string Currently "string", "integer" and "uuid" are supported
logical_type string One of the UserClouds defined types or "custom"
purpose string A comma separated list of purposes
glo_access_policy_id UUIDv4 ID of a policy to base access policy to the data.
geo_policy_id UUIDv4 ID of a policy to describe which regions the data should stored in
enc_policy_id UUIDv4 ID of a policy to describe encryption method for the data

Update Column

POST /userstore/config/columns/8775116f-86cd-4f44-8023-e3108a901abd HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "update":"purpose: Product_Improvement, Product_Operation",
}
curl -X 'POST' \
 -H 'Content-Type: application/json' \
 -d '{"id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "purpose":"Product_Improvement, Product_Operation"' \
 'https://sample.tenant.userclouds.com/userstore/config/columns/8775116f-86cd-4f44-8023-e3108a901abd'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.UpdateColumn(ctx, uuid.Must(uuid.FromString('8775116f-86cd-4f44-8023-e3108a901abd')), "Purpose: Product_Improvement, Product_Operation")

Update a column with a given ID. Certain fields cannot be changed in an Update operation, once the column contains data. A column update may invalidate the accessors defined for it.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the existing column.
update string yes Fields to be updated

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "created":"2022-03-28T21:43:36.099293Z",
 "updated":"2022-03-28T21:43:36.099293Z",
 "deleted":"0001-01-01T00:00:00Z",
 "column_name":"FirstName",
 "primitive_type":"string",
 "logical_type":"Name-First",
 "purpose":"Product_Improvement, Integrity, Product_Operation",
 "global_access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the updated created column.
created datetime Timestamp of the column's creation.
updated datetime Timestamp of the columns's most recent update.
deleted datetime Timestamp of the column's deletion, or the "0" timestamp if alive.
column_name string Application-provided human-readable name for the column.
primitive_type string Currently "string", "integer" and "uuid" are supported
logical_type string One of the UserClouds defined types or "custom"
purpose string A comma separated list of purposes
glo_access_policy_id UUIDv4 ID of a policy to base access policy to the data.
geo_policy_id UUIDv4 ID of a policy to describe which regions the data should stored in
enc_policy_id UUIDv4 ID of a policy to describe encryption method for the data

Delete Column

DELETE /userstore/config/columns/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'DELETE' \
 'https://sample.tenant.userclouds.com/userstore/config/columns/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
err := c.DeleteColumn(ctx, uuid.FromStringOrNil("60b69666-4a8a-4eb3-94dd-621298fb365d"))

Delete a column with given id. Note that deleting the column doesn't result in data deletion, but in the data being immediately unavailable. To delete the data stored in the column, you need to trigger the garbage collection process on the column which will remove the data after a configurable retention period. Note that the minimum retention period is 72 hours for primary copy and 30 days for backups. This three stage process and delay is designed to protect your user data from mistakes or in case of account takeover.

Request

Parameter Type Required Description
/columns/{id} UUIDv4 (in path) yes ID of the column to delete.

Response

HTTP/1.1 204 No Content

204 No Content on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 Column with ID not found
500 Internal error occurred processing the request

CRUD Configuration

Describe the userstore in GraphQL

type User {
 id: String! @ocolumn id
 name: String! @column name
 address: [Address!]! @column address
 phone: String! @column phone
 classes: [String!]! @column classes
}
enum AddressType {
 HOME
 OFFICE
 OTHER
}
type Address {
  type: AddressType! @column composite
  street: String! @column composite
  houseNumber: Int @column composite
  zip: Int @column composite
}

Define the query method which maps to the accessor getusersforareacode

query GetUsersForAreaCode($ac: String!) @method getusersforareacode{
  user(areaCode: $ac) {
    name
    address
  }
}
GetUsersForAreaCode(“650”)

Describe the userstore in SQL

CREATE TABLE Users (
    id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    phone VARCHAR(255) NOT NULL,
    address JSON NOT NULL,
    classes JSON NOT NULL
)  ENGINE=USERCLOUDS;

Define the stored procedure which maps to the accessor getusersforareacode

CREATE PROCEDURE GetUsersForAreaCode(
    IN areaCode VARCHAR(255)
)
BEGIN
    SELECT name, address
    FROM User
    WHERE phone LIKE areaCode
END

CALL GetUsersForAreaCode(650)

Each individual CRUD API has the following properties:

Describe the userstore in GraphQL

type User {
 name: String! @column name
 address: [Address!]! @column address
 phone: String! @column phone
 classes: [String!]! @column classes
}
enum AddressType {
 HOME
 OFFICE
 OTHER
}
type Address {
  type: AddressType! @column composite
  street: String! @column composite
  houseNumber: Int @column composite
  zip: Int @column composite
}

Define the query method which maps to the accessor getusersforareacode

type Query {
 user(areaCode: String!): User
}

query GetUsersForAreaCode($ac: String!) @method getusersforareacode{
  user(areaCode: $ac) {
    name
    address
  }
}
GetUsersForAreaCode(“650”)

Each CRUD API can be expressed as a SQL or GraphQL query or another preferred data fetching language - see examples on the right. This allows the client code to be written in a way that is agnostic to the infrastructure being used for storing user data or for ease of migration of existing code to User Data Vault.

Create Accessor

POST /userstore/config/api HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "name":"GetUsersForAreaCode",
 "operation":"READ",
 "columns":["id", "name", "address"],
 "selectors":["phone.contains"],
 "access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
curl -X 'POST' \
 -H 'Content-Type: application/json' \
 -d '{"id":"8775116f-86cd-4f44-8023-e3108a901abd","name":"GetUsersForAreaCode",  "operation":"READ",  "columns":["id", "name", "address"], "selectors":["phone.contains"],
 "access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"' \
 'https://sample.tenant.userclouds.com/userstore/config/api'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.CreateAPI(ctx, uuid.Must(uuid.NewV4()),  "GetUsersForAreaCode", "READ",
                                ["id", "name", "address"], "selectors":["phone.contains"],uuid.Must(uuid.FromString('f5bce640-f866-4464-af1a-9e7474c4a90c')))

Creates a new api to perform an operation on the datastore.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the newly created api.
name string yes Application-provided human-readable name for the api.
columns string yes A comma separated list of column names
selectors string no A comma separated list of selectors names
operation enum yes Operation type CREATE/READ/UPDATE/DELETE
access_policy_id UUIDv4 yes ID of a policy to access policy to execute the operation.
data_transform_id UUIDv4 no ID of a transform to modify the return value(s).
data_validator_id UUIDv4 no ID of a transform to validate the input value(s).
approval_policy_id UUIDv4 no ID of a policy describing manual approval triggers
product_path string no A comma separate list of product paths
doc_ref_id UUIDv4 no ID of a document from privacy program

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
 "id":"60b2f286-f051-444f-9b08-4b67129dcb7b",
 "created":"2022-03-28T21:43:36.099293Z",
 "updated":"2022-03-28T21:43:36.099293Z",
 "deleted":"0001-01-01T00:00:00Z",
 "name":"GetUsersForAreaCode",
 "operation":"READ",
 "columns":"["id", "name", "address"]",
 "selectors":["phone.contains"],
 "access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the newly created api.
created datetime Timestamp of the api's creation.
updated datetime Timestamp of the api's most recent update.
deleted datetime Timestamp of the api's deletion, or the "0" timestamp if alive.
name string Application-provided human-readable name for the api.
columns string A comma separated list of column names
selectors string A comma separated list of selectors names
operation enum Operation type CREATE/READ/UPDATE/DELETE
access_policy_id UUIDv4 ID of a policy to access policy to execute the operation.
data_transform_id UUIDv4 ID of a transform to modify the return value(s).
data_validator_id UUIDv4 ID of a transform to validate the input value(s).
approval_policy_id UUIDv4 ID of a policy describing manual approval triggers
product_path string A comma separate list of product paths
doc_ref_id UUIDv4 ID of a document from privacy program

Get Accessor

GET /userstore/config/api/8775116f-86cd-4f44-8023-e3108a901abd HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'GET' \
 'https://sample.tenant.userclouds.com/userstore/config/api/8775116f-86cd-4f44-8023-e3108a901abd'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.GetAPI(ctx, uuid.FromStringOrNil("8775116f-86cd-4f44-8023-e3108a901abd))

Gets an existing accessor's configuration by its id.

Request

Parameter Type Required Description
/api/{id} UUIDv4 (in path) yes ID of the accessor to get.

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "created":"2022-03-28T21:43:36.099293Z",
 "updated":"2022-03-28T21:43:36.099293Z",
 "deleted":"0001-01-01T00:00:00Z",
 "name":"GetUsersForAreaCode",
 "operation":"READ",
 "columns":"["id", "name", "address"]",
 "selectors":["phone.contains"],
 "access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the newly created api.
created datetime Timestamp of the api's creation.
updated datetime Timestamp of the api's most recent update.
deleted datetime Timestamp of the api's deletion, or the "0" timestamp if alive.
name string Application-provided human-readable name for the api.
columns string A comma separated list of column names
selectors string A comma separated list of selectors names
operation enum Operation type CREATE/READ/UPDATE/DELETE
access_policy_id UUIDv4 ID of a policy to access policy to execute the operation.
data_transform_id UUIDv4 ID of a transform to modify the return value(s).
data_validator_id UUIDv4 ID of a transform to validate the input value(s).
approval_policy_id UUIDv4 ID of a policy describing manual approval triggers
product_path string A comma separate list of product paths
doc_ref_id UUIDv4 ID of a document from privacy program

Update Accessor

POST /userstore/config/api/8775116f-86cd-4f44-8023-e3108a901abd HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "update" : "columns:[id, name, phone, address]",
}
curl -X 'POST' \
 -H 'Content-Type: application/json' \
 -d '{"id":"8775116f-86cd-4f44-8023-e3108a901abd", "update": "columns:[id, name, address]", ' \
 'https://sample.tenant.userclouds.com/userstore/config/api'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.UpdateAPI(ctx, uuid.Must(uuid.FromString('8775116f-86cd-4f44-8023-e3108a901abd')),
                                "columns: [id, name, address]")

Update an accessor with a given ID. Name and ID are immutable.

Request

Parameter Type Required Description
id UUIDv4 yes ID of the existing accessor.
update string yes Fields to be updated

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
 "id":"8775116f-86cd-4f44-8023-e3108a901abd",
 "created":"2022-03-28T21:43:36.099293Z",
 "updated":"2022-03-28T21:43:36.099293Z",
 "deleted":"0001-01-01T00:00:00Z",
 "name":"GetUsersForAreaCode",
 "operation":"READ",
 "columns":"["id", "name", "address"]",
 "selectors":["phone.contains"],
 "access_policy":"f5bce640-f866-4464-af1a-9e7474c4a90c"
}
Parameter Type Description
id UUIDv4 ID of the updated api.
created datetime Timestamp of the api's creation.
updated datetime Timestamp of the api's most recent update.
deleted datetime Timestamp of the api's deletion, or the "0" timestamp if alive.
name string Application-provided human-readable name for the api.
columns string A comma separated list of column names
selectors string A comma separated list of selectors names
operation enum Operation type CREATE/READ/UPDATE/DELETE
access_policy_id UUIDv4 ID of a policy to access policy to execute the operation.
data_transform_id UUIDv4 ID of a transform to modify the return value(s).
data_validator_id UUIDv4 ID of a transform to validate the input value(s).
approval_policy_id UUIDv4 ID of a policy describing manual approval triggers
product_path string A comma separate list of product paths
doc_ref_id UUIDv4 ID of a document from privacy program

Delete Accessor

DELETE /userstore/config/api/60b2f286-f051-444f-9b08-4b67129dcb7b HTTP/1.1
Host: sample.tenant.userclouds.com
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc
curl -X 'DELETE' \
 'https://sample.tenant.userclouds.com/userstore/config/api/60b2f286-f051-444f-9b08-4b67129dcb7b'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
err := c.DeleteAPI(ctx, uuid.FromStringOrNil("60b69666-4a8a-4eb3-94dd-621298fb365d"))

Delete a api with given id, which makes it immediately unavailable. Note that the api configuration is retained for 72 hours in case you need to restore it and for 30 days in backups. This two stage process and delay is designed to protect your api configuration from mistakes or in case of account takeover.

Request

Parameter Type Required Description
/api/{id} UUIDv4 (in path) yes ID of the accessor to delete.

Response

HTTP/1.1 204 No Content

204 No Content on success, or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 API with ID not found
500 Internal error occurred processing the request

Execute Accessor

POST /userstore/api/8775116f-86cd-4f44-8023-e3108a901abd HTTP/1.1
Host: sample.tenant.userclouds.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...6PzZx3Y3FBuGc

{
 "selectors":["650"],
 "context:"{ "purpose":"Product Operation"}"
}
curl -X 'POST' \
 -H 'Content-Type: application/json' \
 -d '{"selectors":["650"], "context":"{ "purpose":"Product Operation"},' \
 'https://sample.tenant.userclouds.com/userstore/api/8775116f-86cd-4f44-8023-e3108a901abd'
c := userstore.NewClient("https://sample.tenant.userclouds.com")
edgeType, err := c.CallAPI( "GetUsersForAreaCode", "650", '{ "purpose":"Product Operation"}')

Executes the accessor, performs the defined operation and returns any output if defined.

Request

Parameter Type Required Description
selectors string no A comma separated list of selectors inputs
context string yes Context for evaluating the access/approval policy
access_policy_id UUIDv4 yes ID of a policy to access policy to execute the operation.
product_path string no Product path

Response

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json

{
 "output":"[ { name : name1, address: address1 }, {name: name2, address: address2}",
 "state":"COMPLETE",
}
Parameter Type Description
output JSON Output of the operation if any
state enum State of the execution - COMPLETE

Or one of the following errors:

Code Reason
401 No credentials or invalid credentials provided
404 API with ID not found
500 Internal error occurred processing the request

Policy Configuration

See Access Policy

Tokenizer

Tokenizer is available natively from inside the User Store, but also as a standalone API that can be called for singleton pieces of data, or in bulk.

Tokens are used to replace PII when the data needs to be transferred to secondary systems, but you want to retain control of what the data can be used for (and when) in a central policy store. Just before "sharing" the records, you tokenize important PII (using the Create Token API, or Lookup Token API if you want to reuse an already-created token for this value), and share that token instead. The Generation Policy controls how the token is generated (how much information to obscure or retain, formatting, etc).

When the time comes to use the data (eg. send an email), the user calls the Resolve Token API and the Access Policy controls whether or not the token can be resolved.

Generation Policies

type GenerationPolicy struct {
  ID         uuid.UUID
  Function   string
  Parameters interface{}
}

Generation Policies control how a token is generated ... they range from the simplest built-in UUID policy that naively replaces any given data with a unique identifier, to custom-written Javascript that runs in a carefully-controlled sandbox.

In practice, a generation policy may be passed in-line to CreateToken(), or it may be referenced by ID (IDs may be included in in-line policies to "name" them, otherwise they will be automatically assigned); if only an ID is passed, the policy will be looked up by ID. A CreateGenerationPolicy API is also available for "offline" management.

A generation policy consists of a tuple of (ID, function, parameters)

id - as described above

function - a generator function with the signature func(data JSONValue, parameters JSONValue) (Token | error)

parameters - a static JSON object (not containing PII) that is available at runtime, allowing you to parameterize and reuse functions like "obfuscate all but the first X letters of these emails"

Access Policies

type AccessPolicy struct {
  ID         uuid.UUID
  Function   string
  Parameters interface{}
}

Access Policies control token resolution down the line. They can be as simple as "allow any resolution with purpose 'security'" to complex Javascript evaluations including locations, credentials, etc.

Like generation policies, access policies can be passed in-line to CreateToken(), or they may be referenced by ID.

An access policy consists of a tuple of (ID, function, parameters)

id - as described above

function - a function with the signature func(token Token, parameters JSONValue, context JSONValue), where context is passed in from the ResolveToken() call.

parameters - a static JSON object (not containing PII) that is available at runtime, allowing you to parameterize and reuse functions like "allow access only from IP range X-Y"

Create Token API

func CreateToken(
  data interface{},
  attributes interface{},
  gp GenerationPolicy,
  ap AccessPolicy
  ) (*Token, error)

CreateToken creates a new token for a data NB: CreateToken will always generate a unique token for this data. If you want to reuse a token that was already generated, use LookupToken()

data: a JSON-serializable object that is being tokenized (the PII)

attributes: a JSON-serializable object that is stored alongside the data, but does not contain PII. This is used for things like the InspectToken() API, as well as bulk DeleteToken() operations (eg. delete all tokens associated with a given user_id)

gp: a Generation Policy that controls how the token is generated

ap: an Access Policy that controls under what conditions a token can be resolved

Lookup Token API

go LookupToken( data interface{}, attributes interface{}, gp GenerationPolicy, ap AccessPolicy, ) (*Token, error)

LookupToken is just like CreateToken, except that it only returns existing tokens that match across the full set of parameters; if no token matches, an error is returned.

Resolve Token API

func ResolveToken(
  token *Token,
  context interface{},
) (interface{}, error)

ResolveToken takes a token and a resolution context (eg. the purpose for which the token is being resolved, by whom it is being resolved, etc), and either resolves the token or raises an error.

Inspect Token API

func InspectToken(
  token *Token,
) (GenerationPolicy, AccessPolicy, Attributes, error)

InspectToken is primarily a debugging API that lets you query (but not resolve) a token.

Delete Token API

func DeleteToken(token *Token) error
func DeleteFromData(data interface{}) error
func DeleteByAttributes(attributes interface{}) error

DeleteToken is actually a small collection of APIs that lets you delete tokens (break the link between PII and downstream data) in various ways.

Batch APIs

Batch APIs are available for CreateToken, LookupToken and ResolveToken.

Fundamentally a batch consists of an optional list of Generation Policies and Access Policies that can be referenced in the list of objects (for CreateToken and LookupToken), followed by an ordered list of objects (either data, attribute pairs, or tokens). Each object in the list may optionally be assigned an ID, which will be preserved in the response.

The response object consists of an order-preserved list of response objects, which include the ID (if used in the request), a response object (Token or data), and/or an error for that particular object's operation.

Batch sizes are currently allowed up to 100 items but we expect we'll expand this much farther as we do more ETL integrations.

We currently don't support batches for InspectToken (primarily for debugging) or DeleteToken (because attributes allows bulk deletion), but contact us if you need these.

Create Generation Policy API

func CreateGenerationPolicy(
  gp GenerationPolicy,
) (uuid.UUID, error)

CreateGenerationPolicy is a convenience wrapper around just inlining a generation policy on the first CreateToken call.

Create Access Policy API

func CreateAccessPolicy(
  ap AccessPolicy,
) (uuid.UUID, error)

CreateAccessPolicy is a convenience wrapper around just inlining a access policy on the first CreateToken call.