Collect and reveal data with Skyflow Elements

Skyflow Elements provides a secure way to collect and reveal sensitive data, such as personally identifiable information (PII) and credit card information (PCI). It offers several benefits, including complete programmatic isolation from your frontend applications, end-to-end encryption, tokenization, and the ability to customize the look and feel of the data collection form.

You can integrate Skyflow Elements into existing applications and workflows by installing server-side and client-side Skyflow SDKs, initializing the SDKs with your Skyflow credentials, and using the client-side SDK to create and customize the data collection form.

How it works

When your users interact with Skyflow Elements, various components work together to collect and reveal sensitive data. Here’s how it works:

  • When your user enters sensitive data into collect elements, the client-side SDK sends the data to your vault and receives tokens that represent the data.
  • When you need to reveal the data to a user, the client-side SDK sends the tokens to your vault, receives the data, and displays the data in reveal elements.

Prerequisites

  • Sign in to your Skyflow account. If you don’t have an account, sign up for a free trial.

  • Basic knowledge of JavaScript and Node.js

  • Basic knowledge of HTML and CSS

  • A device with the following tools installed:

  • A vault and its details: 1. In Studio, click the vault menu icon > View vault details. 2. Note your Vault URL, and Vault ID values.

    The following content uses the Quickstart vault template. Adapt your commands accordingly.

Identify data to collect

You may want to collect many kinds of sensitive data from your users. Here are some common examples:

  • Personally identifiable information (PII): full name, Social Security Number (SSN), date of birth (DOB), address, phone number, and email address.
  • Payment Card Industry (PCI) data: bank account numbers, credit card numbers, and financial transactions.
  • Personal health information (PHI): medical history, prescriptions, diagnoses, and health insurance information.

Make sure your vault has the appropriate tables and columns to store the data you want to collect.

This tutorial uses the Quickstart vault template and focuses on securely collecting the columns in the persons table:

  • name
  • email_address
  • ssn
  • date_of_birth
  • state

Create roles and service accounts

To use Skyflow Elements, you need to define a role to control what the SDKs can access and a service account to let the SDKs authenticate and access Skyflow according to their role.

Create a role

  1. In Studio, click Settings in the upper navigation.

  2. In the side navigation, click Vault, then choose your vault from the dropdown menu.

  3. Under IAM, click Roles, then Add New Role.

  4. For Name, enter “Collect PII”.

  5. For Description, enter a value. For example, “Restrictive vault access”.

  6. Click Create.

  7. Click Attach Policies, and replace the placeholder content with the following policies:

    1ALLOW CREATE ON persons.*
    2ALLOW TOKENIZATION ON persons.*

    These policies let you gather data from your client, insert it into your vault, and return tokens to your client.

    If you have a requirement to display data, add the following policies:

    1ALLOW DETOKENIZATION ON persons.name WITH REDACTION = MASKED
    2ALLOW DETOKENIZATION ON persons.email_address WITH REDACTION = MASKED
    3ALLOW DETOKENIZATION ON persons.ssn WITH REDACTION = MASKED
    4ALLOW DETOKENIZATION ON persons.date_of_birth WITH REDACTION = MASKED
    5ALLOW DETOKENIZATION ON persons.state WITH REDACTION = MASKED

    Caution: Revealing data in your interfaces exposes that data to your users. Only use reveal elements when necessary, and make sure you have adequate access policies in place when you do.

  8. Click Create, enter “Collect PII” for the policy name, then click Save.

  9. Click Enable, then close the dialog.

Create a service account

  1. Under IAM, click Service Accounts, then click New Service Account.
  2. For Name, enter “Client-side SDK”.
  3. For Roles, select Collect PII.
  4. Click Create.

Your browser downloads a credentials.json file. Store this file in a secure location. You’ll need it to generate bearer tokens.

Integrate with a server-side SDK (Node.js)

Now that you’ve created your vault and defined your role and service account, it’s time to integrate with the server-side SDK.

  1. In a terminal, run the following commands:

    $mkdir skyflow-server
    >cd skyflow-server
    >npm init
    >npm install express skyflow-node
  2. Move your credentials.json file to the root directory of your project.

  3. Create server.js in the root directory of the project with the following code:

    1// Load the express module.
    2const express = require("express");
    3const app = express();
    4const port = 3000;
    5
    6// Load the skyflow-node module.
    7const { generateBearerToken, isExpired } = require("skyflow-node");
    8
    9// Load the credentials.json file.
    10let filepath = "./credentials.json";
    11let bearerToken = "";
    12
    13// Generate a bearer token. If the cached token is expired, generate a new one.
    14async function getSkyflowBearerToken() {
    15 try {
    16 if (!isExpired(bearerToken)) {
    17 return bearerToken;
    18 } else {
    19 let response = await generateBearerToken(filepath);
    20 bearerToken = response.accessToken;
    21 return bearerToken;
    22 }
    23 } catch (e) {
    24 console.error(e);
    25 }
    26}
    27
    28// Create a route to serve the elements.html file.
    29app.get("/", (req, res) => {
    30 res.sendFile(__dirname + "/elements.html");
    31});
    32
    33// Create a route to fetch a bearer token.
    34app.get("/getToken", async (req, res) => {
    35 let token = await getSkyflowBearerToken();
    36 res.send({ token });
    37});
    38
    39// Start the server.
    40app.listen(port, () => {
    41 console.log(`Example app listening at http://localhost:${port}`);
    42});
  4. Run the server:

    $node server.js
  5. In a new terminal, check to make sure you can fetch a bearer token from your server:

    $curl http://localhost:3000/getToken

    You should see a bearer token in the response. If you don’t, check your first terminal for errors.

Integrate with client-side SDK (JavaScript)

Now that you’ve integrated with the server-side SDK, it’s time to integrate with the client-side SDK.

  1. Create elements.html in the root directory of the project with the following code. Update VAULT_ID and VAULT_URL with your vault’s values.

    1<!DOCTYPE html>
    2<html>
    3 <head>
    4 <title>Skyflow Collect and Reveal Example</title>
    5 {script src="https://js.skyflow.com/v1/index.js"}{/script}
    6 </head>
    7 <body>
    8 <h1>Skyflow Collect and Reveal Example</h1>
    9
    10 <!-- Collect container/elements -->
    11 <h2>Collect</h2>
    12 <div id="collectNameElement"></div>
    13 <div id="collectSsnElement"></div>
    14 <div id="collectDobElement"></div>
    15 <div id="collectEmailElement"></div>
    16 <div id="collectStateElement"></div>
    17 <button id="submit">Submit</button>
    18 <br /><br />
    19
    20 <!-- Reveal elements -->
    21 <h2>Reveal</h2>
    22 <div id="revealNameElement"></div>
    23 <div id="revealSsnElement"></div>
    24 <div id="revealDobElement"></div>
    25 <div id="revealEmailElement"></div>
    26 <div id="revealStateElement"></div>
    27 <button id="reveal">Reveal</button>
    28
    29 <!-- JavaScript -->
    30 {script} // Initialize Skyflow const VAULT_ID = "" // Replace with your
    31 vault ID const VAULT_URL = "" // Replace with your vault URL const
    32 skyflow = Skyflow.init({ vaultID: VAULT_ID, vaultURL: VAULT_URL,
    33 options: { // logLevel: Skyflow.LogLevel.DEBUG, // Uncomment to enable
    34 debug logs // env: Skyflow.Env.DEV, // Uncomment to use the development
    35 environment }, // Get bearer token from your server getBearerToken: ()
    36 => { return new Promise((resolve, reject) => { const Http = new
    37 XMLHttpRequest(); Http.onreadystatechange = () => { if (Http.readyState
    38 === 4) { if (Http.status === 200) { const response =
    39 JSON.parse(Http.responseText); resolve(response.token); } else {
    40 reject("Error occured"); } } }; Http.onerror = (error) => {
    41 reject("Error occured"); }; // Replace with your server URL const url =
    42 "http://localhost:3000/getToken"; Http.open("GET", url); Http.send();
    43 }); }, }); // Set up collect container const collectContainer =
    44 skyflow.container(Skyflow.ContainerType.COLLECT); // Set up collect
    45 elements const collectNameElement = collectContainer.create( { table:
    46 "persons", column: "name", label: "Name", type:
    47 Skyflow.ElementType.INPUT_FIELD, }, collectContainer ); const
    48 collectSsnElement = collectContainer.create( { table: "persons", column:
    49 "ssn", label: "SSN", type: Skyflow.ElementType.INPUT_FIELD, },
    50 collectContainer ); const collectDobElement = collectContainer.create( {
    51 table: "persons", column: "date_of_birth", label: "Date of birth", type:
    52 Skyflow.ElementType.INPUT_FIELD, }, collectContainer ); const
    53 collectEmailElement = collectContainer.create( { table: "persons",
    54 column: "email_address", label: "Email", type:
    55 Skyflow.ElementType.INPUT_FIELD, }, collectContainer ); const
    56 collectStateElement = collectContainer.create( { table: "persons",
    57 column: "state", label: "State", type: Skyflow.ElementType.INPUT_FIELD,
    58 }, collectContainer ); // Mount collect elements
    59 collectNameElement.mount("#collectNameElement");
    60 collectSsnElement.mount("#collectSsnElement");
    61 collectDobElement.mount("#collectDobElement");
    62 collectEmailElement.mount("#collectEmailElement");
    63 collectStateElement.mount("#collectStateElement"); // Set up reveal
    64 container const revealContainer =
    65 skyflow.container(Skyflow.ContainerType.REVEAL); // Set up reveal
    66 elements const revealNameElement = revealContainer.create({ label:
    67 "Name", }); const revealSsnElement = revealContainer.create({ label:
    68 "SSN", }); const revealDobElement = revealContainer.create({ label:
    69 "Date of birth", }); const revealEmailElement = revealContainer.create({
    70 label: "Email", }); const revealStateElement = revealContainer.create({
    71 label: "State", }); // Mount reveal elements
    72 revealNameElement.mount("#revealNameElement");
    73 revealSsnElement.mount("#revealSsnElement");
    74 revealDobElement.mount("#revealDobElement");
    75 revealEmailElement.mount("#revealEmailElement");
    76 revealStateElement.mount("#revealStateElement"); // Set up reveal button
    77 const revealButton = document.getElementById("reveal");
    78 revealButton.addEventListener("click", async () => { const
    79 revealResponse = await revealContainer.reveal();
    80 console.log(revealResponse); }); // Set up submit button const
    81 submitButton = document.getElementById("submit");
    82 submitButton.addEventListener("click", async () => { // Collect data
    83 const collectResponse = await collectContainer.collect(); // TODO: Store
    84 tokens from the collect response in your data store
    85 console.log(collectResponse); // Update reveal elements with tokens
    86 const fieldsTokenData = collectResponse.records[0].fields;
    87 revealNameElement.setToken(fieldsTokenData.name);
    88 revealSsnElement.setToken(fieldsTokenData.ssn);
    89 revealDobElement.setToken(fieldsTokenData.date_of_birth);
    90 revealEmailElement.setToken(fieldsTokenData.email_address);
    91 revealStateElement.setToken(fieldsTokenData.state); }); {/script}
    92 </body>
    93</html>

    This code does the following:

    • Defines HTML elements to mount elements onto.
    • Initializes the SDK with your vault’s values, including fetching a bearer token from the server-side SDK.
    • Defines a collect container and the elements it contains.
    • Mounts the collect container onto the HTML element.
    • Defines the reveal elements.
    • Mounts the reveal elements onto the HTML element.
    • Configures the Submit button to collect data from the collect container and update the reveal element with the token.
    • Configures the Reveal button to reveal the data in the reveal element.
  2. In a browser, open http://localhost:3000.

    You should see a form with input fields. When you enter a value and click Submit, the SDK sends the value to your vault and returns a token for the value. Store tokens in your data store instead of the actual values.

    When you click the Reveal button, if you added the DETOKENIZATION policy, the SDK uses the token to retrieve the value from your vault and display it on the page. If you didn’t add the DETOKENIZATION policy, the SDK returns an error.

Next steps

You now have a functional, if minimal, integration with Skyflow Elements. There are a few ways you can improve the current integration:

  • Customize the types of elements you use.
  • Configure upsert to update existing records and insert new records.
  • Style the elements to match your application’s look and feel.
  • Set labels for the elements.
  • Set placeholder text for the elements.
  • Set alt text for the elements.
  • Add input validation to display errors when users enter invalid data.
  • Add input formatting to format the data users enter.

For information on these topics, see the Skyflow JavaScript SDK.