protection
Data protection by tokenization.
Data protection by tokenization. Sensitive values such as card numbers, national identifiers, email addresses, phone
numbers and free text are replaced by tokens that are safe to store and pass around. The values are encrypted under a
tenant KMS key, and turning a token back into its value is decided by policy per profile and stated purpose. Every
call is audited with counts, never with values or tokens. The repository guide is docs/data-protection.md.
Profiles and policies
A profile handles one kind of value: its dataType (card, ssn, email, phone, generic), its token format
(format-preserving or random), whether tokens are deterministic, its display mask and its retention. Policies
name a profile as iam/protection/{name} and can use resource.profile, resource.dataType, resource.format and
resource.deterministic. detokenize adds resource.purpose, and mask adds resource.style (the style used, the
profile's default included). Tokenizing, detokenizing, masking and erasing are separate permissions, so the services
that collect data can be allowed to tokenize without ever reading anything back. Tokenizing into a deterministic
profile can test guesses against known tokens: grant it as narrowly as detokenizing.
A profile bound to a customer key (keyId) leaves the key's owner in charge: every call also needs the caller's
iam:kms:generate-data-key (tokenize) or iam:kms:decrypt (detokenize, mask) on the key. A key the profile created
is managed by it (KEY_MANAGED for direct KMS use) and is scheduled for deletion with the profile.
| Method | What it does | Access |
|---|---|---|
createProfile | Creates a tokenization profile, with an existing tenant AES key the caller may use (keyId) or a new one. | Credential |
deleteProfile | Deletes a profile that holds no tokens. A key the profile created is scheduled for deletion after 7 days. | Credential |
deleteTokens | Deletes tokens and their values for good, named by tokens or by values. Erasing by value finds every token issued for it, even in profiles that are not deterministic. | Credential |
detokenize | Turns up to 100 tokens of the profile back into their values, in order, with null for tokens the profile does not hold. purpose is required: a short lowercase name such as payment-processing. | Credential |
getProfile | One profile, with the number of tokens it holds. | Credential |
listProfiles | The tenant's profiles the caller may read, by name. | Credential |
mask | The masked form of up to 100 tokens' values (************4242, j***@example.com), with the profile's mask or a style its data type allows (last4, first6last4 for cards, email for email addresses, full). A mask never shows more than half of a value, except the first six and last four digits of a card number of 15 digits or more. | Credential |
tokenize | Replaces up to 100 values by tokens, in order. Values are validated and normalized for the data type (text to Unicode NFC; a card number must pass the Luhn check). A deterministic profile returns the token it already issued for a value. The response does not say which values were stored already; the audit event does. | Credential |
updateProfile | Changes the description, the mask, or the retention (retentionDays: null keeps tokens until they are deleted). The data type, format and key never change. | Credential |
createProfile
Creates a tokenization profile, with an existing tenant AES key the caller may use (keyId) or a new one.
Used inData protection
- Permission:
iam:protection:manageoniam/protection/{name}; withkeyId, alsoiam:kms:generate-data-keyandiam:kms:decrypton the key. - Audited as:
iam:protection:manage(metadata:profile,dataType,format,deterministic,keyId). - Errors:
INVALID_INPUTfor an unknown data type or format, a mask the data type does not allow, a non-deterministic format-preservingssnorphoneprofile, or a key that is notaes-256-gcm;KEY_MANAGEDfor a key another profile or module manages;CONFLICTfor a name in use;LIMIT_EXCEEDEDpast 100 profiles.
await iam.api.protection.createProfile(admin, {
tenantId,
name: 'cards',
dataType: 'card',
deterministic: true,
retentionDays: 365,
});A ProfileCreateInput object:
Prop
Type
A ProfileSummary object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/createProfile" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"name": "<name>",
"dataType": "email"
}'iam.api.protection.createProfile(
credential: CredentialInput,
input: ProfileCreateInput,
): Promise<ProfileSummary>deleteProfile
Deletes a profile that holds no tokens. A key the profile created is scheduled for deletion after 7 days.
- Permission:
iam:protection:manage, with recent authentication. - Audited as:
iam:protection:manage(metadata:profile,keyDeletionDate). - Errors:
RESOURCE_IN_USEwhile tokens remain.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/deleteProfile" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"profile": "<profile>"
}'iam.api.protection.deleteProfile(
credential: CredentialInput,
input: { tenantId: string; profile: string },
): Promise<{ success: true }>deleteTokens
Deletes tokens and their values for good, named by tokens or by values. Erasing by value finds every token issued for it, even in profiles that are not deterministic.
Used inData protection
- Permission:
iam:protection:delete. - Audited as:
iam:protection:delete(metadata:profile,deleted,by).
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/deleteTokens" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"profile": "<profile>"
}'iam.api.protection.deleteTokens(
credential: CredentialInput,
input: { tenantId: string; profile: string; tokens?: string[]; values?: string[] },
): Promise<{ deleted: number }>detokenize
Turns up to 100 tokens of the profile back into their values, in order, with null for tokens the profile does not hold. purpose is required: a short lowercase name such as payment-processing.
Used inData protection
- Permission:
iam:protection:detokenize, withresource.purpose(andiam:kms:decrypton a customer key). - Audited as:
iam:protection:detokenize(metadata:profile,purpose,count,found). - Errors:
INVALID_INPUTfor a malformed purpose;KEY_STATE_INVALID.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/detokenize" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"profile": "<profile>",
"tokens": [
"<token>"
],
"purpose": "<purpose>"
}'iam.api.protection.detokenize(
credential: CredentialInput,
input: { tenantId: string; profile: string; tokens: string[]; purpose: string },
): Promise<{ values: Array<string | null> }>getProfile
One profile, with the number of tokens it holds.
- Permission:
iam:protection:read.
Prop
Type
A ProfileSummary object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/getProfile" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"profile": "<profile>"
}'iam.api.protection.getProfile(
credential: CredentialInput,
input: { tenantId: string; profile: string },
): Promise<ProfileSummary>listProfiles
The tenant's profiles the caller may read, by name.
- Permission:
iam:protection:read, evaluated for each profile.
Prop
Type
An array of ProfileSummary.
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/listProfiles" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.protection.listProfiles(
credential: CredentialInput,
input: { tenantId: string },
): Promise<ProfileSummary[]>mask
The masked form of up to 100 tokens' values (************4242, j***@example.com), with the profile's mask or a style its data type allows (last4, first6last4 for cards, email for email addresses, full). A mask never shows more than half of a value, except the first six and last four digits of a card number of 15 digits or more.
Used inData protection
- Permission:
iam:protection:mask, withresource.style(andiam:kms:decrypton a customer key). - Audited as:
iam:protection:mask(metadata:profile,style,count,found).
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/mask" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"profile": "<profile>",
"tokens": [
"<token>"
]
}'iam.api.protection.mask(
credential: CredentialInput,
input: { tenantId: string; profile: string; tokens: string[]; style?: MaskStyle },
): Promise<{ values: Array<string | null> }>tokenize
Replaces up to 100 values by tokens, in order. Values are validated and normalized for the data type (text to Unicode NFC; a card number must pass the Luhn check). A deterministic profile returns the token it already issued for a value. The response does not say which values were stored already; the audit event does.
Used inData protection
- Permission:
iam:protection:tokenize(andiam:kms:generate-data-keyon a customer key). - Audited as:
iam:protection:tokenize(metadata:profile,count,created). - Errors:
INVALID_INPUTfor a value the data type does not accept;KEY_STATE_INVALIDwhen the profile's key is disabled.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/tokenize" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"profile": "<profile>",
"values": [
"<value>"
]
}'iam.api.protection.tokenize(
credential: CredentialInput,
input: { tenantId: string; profile: string; values: string[] },
): Promise<{ tokens: string[] }>updateProfile
Changes the description, the mask, or the retention (retentionDays: null keeps tokens until they are deleted). The data type, format and key never change.
- Permission:
iam:protection:manage; setting or shorteningretentionDaysdeletes tokens, so it also needsiam:protection:deleteand recent authentication.
Prop
Type
A ProfileSummary object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/protection/updateProfile" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"profile": "<profile>"
}'iam.api.protection.updateProfile(
credential: CredentialInput,
input: {
tenantId: string;
profile: string;
description?: string | null;
mask?: MaskStyle;
retentionDays?: number | null;
},
): Promise<ProfileSummary>Better IAM is created by Sean Filimon
Last updated
privacy
Privacy and consent management for GDPR, UK GDPR, CCPA/CPRA, LGPD and PIPEDA: the purposes a tenant processes personal data for, each person's consent with a s…
quotas
API usage plans: throttles (a token bucket of ratePerSecond holding at most burst) and period limits (per minute, hour, day, week or month) on a meter you name…