How to build your own Adobe GDPR interface

If you have a steady stream of GDPR requests that need processing, using the Privacy UI can quickly become pretty time consuming. Fortunately Adobe’s Privacy Service is also available via APIs, which got me thinking about what could be done to speed up a fairly time consuming manual process.

The end result of that thinking time was a pretty simple UI but one that has reduced the processing time by more than 50%. This article will give you an overview of the different component parts and the process of joining them all together.

#1 Design Overview

The requirements for the UI are that the user can:
i) specify whether it is an “Access” or a “Delete” request
ii) add a Ticket ID for internal records
iii) add one or more declared IDs (used as the custom key for each request)
iv) remove rows if the form input is incorrect
v) receive confirmation when the requests are registered successfully
vi) receive a daily email update on the status of jobs

#2 Create an Adobe IO integration

By the end of this step you should end up with something that looks like this

#3 Create a json web token

However, we want to be able to handle the generation of the jwt as part of the process that is triggered when a user submits their IDs, without needing to rely on manually generating a token in the Adobe IO interface.

This means we’ll need to create our own token, which is a fairly straightforward process, but there are plenty of resources if you want to read up on jwt further:
i) look here for more general information on json web tokens
ii) there’s a very useful guide about jwt authentication for Adobe IO service accounts (i.e. like the GDPR service account integration created above) here
iii) finally, there is some sample code for several different languages here, which covers how to generate a jwt token

I’m using Node.js to take care of the heavy-lifting involved behind the scenes, so my code to generate the jwt looks like this:

#4 Exchange jwt for an access token

I’m making use of the Axios library for my API requests, so I end up with a token exchange request that looks like this:

Whilst the code above might look a bit odd in isolation, I’m using async/await syntax so that code further down the line (i.e. when I make the calls to the Privacy API) won’t start running until a response has been received from the token exchange request.

#5 Construct the API request

If you’re not familiar with the different parameters that are included in a Privacy API request then have a look at the help documentation here.

For POST requests, the Axios library accepts 3 arguments — url, config & body — so my next step is to define the url & config that I will be using:

No major stumbling blocks here, the url is available in the API reference I linked above and you can get your x-api-key (aka client id) & x-gw-ims-org-id (aka Adobe Org ID) from the Adobe IO integration created earlier. Finally, I need to define the body of my request, which includes the users array I constructed at the start of this section:

Again, there may be some parameters here that don’t look too familiar, in which case just head to the help section to get a better understanding of what is needed and why.

#6 AWS Lambda setup

I’m not going to go through how to get everything set up in AWS Lambda because there is plenty of documentation, which also includes some really useful examples, but I will point out one thing in relation to the callback in line 1 of the screenshot above. Whilst this might seem obvious, it took me a little while to realise that the Lambda function can only complete successfully if this callback is made.

Consequently, you need to trigger that callback with valid response data in all scenarios, whether that involves success or error. The response from my Lambda function contains the job ids that I need to inform the user of, so it’s fairly obvious if my function doesn’t complete successfully; however, even if you’re doing nothing with the response data, it’s still good practice to ensure there are no dead ends that will result in your function “failing” even though the API request is a success. Below is an example of the response data I’m including when I have a successful response from Privacy API request:

#7 UI Build

I set up an Amazon API Gateway that links to my Lambda function, so when a user clicks “submit” I make a request to that gateway endpoint, and include the user input in the request body. As mentioned in section #6, I want to inform the user of the job id associated with each request, so I also added some functionality that displays this information in a table once the processing is complete:

Anyone familiar with making the Privacy requests will know that it usually takes at least a couple of weeks for the processing to complete, so the final piece of the puzzle was to find an efficient way of checking the status of the submitted requests. Fortunately, the steps to achieve this ended up being much more simple than I had imagined:
i) I created a new Lambda function that retrieves the status of all jobs in the last 30 days (note: a 30 day window is the max)
ii) the function applies filters to the job information to ensure that only valid Ticket IDs are included
iii) it then sends an e-mail with all the relevant status information, using the Nodemailer library
iv) using AWS Cloudwatch I set up a schedule that triggers the function (and therefore the request and subsequent e-mail send) at 10:00 every day

Hopefully you found this post interesting and perhaps it’s given you some ideas about how you could apply similar technology to solve problems or make your own processes more efficient. It’s worth mentioning that I chose the AWS route primarily because I’d already been looking into what it was capable of; however, I’m keen to create a similar UI using Adobe’s IO Runtime environment to see how that compares.