Data Deletion Request Callback, Ruby on Rails

Moiz Ali
3 min readFeb 10, 2021

Introduction:

In order to provide users with more control over data and to protect data privacy norms, Facebook gives the option to remove all data consumed by the apps and integrations. A common use case scenario is When a user authenticates with Facebook to use the application’s services, his profile details are stored by the app. User can send a request to your app to delete his Facebook consumed data afterwards.

https://developers.facebook.com/docs/development/create-an-app/app-dashboard/data-deletion-callback/

In this post, we’ll implement this feature in a Rails way

Why is it necessary?

As a developer, we need to implement a Data Deletion Request callback URL to get our app passed for Facebook compliance when a user request to delete his/her data. This is mandatory as per new data privacy policy, GDPR. Also, we can’t submit our app for Review and switch to Live mode without implementing it.

Implement the Callback URL:

We have to make a POST web API endpoint on our server, where we’ll receive requests from Facebook. Our endpoint must be HTTPS enabled and preserve the functionality to parse signed request token sent by Facebook and take further actions to delete user’s data.

Actual Code in Rails:

def facebook_user_deletion
signed_request = params['signed_request']
data = parse_fb_signed_request(signed_request)
# Do data deletion stuff then
user = User.find_by(uid: data['user_id'])
user.destroy
# Return tracking url and code to Facebook
data = { url: "#{ENV['APP_HOST_URL']}/deletion_status?id=del_# {user.id}", confirmation_code: "del_#{user.id}" }
respond_to do |format|
format.json { render :json => data }
end
end
def parse_fb_signed_request(signed_request)
encoded_sig, payload = signed_request.split('.', 2)
secret = ENV['FACEBOOK_SECRET_ID']

# Decode the data
decoded_sig = Base64.urlsafe_decode64(encoded_sig)
data = JSON.load(Base64.urlsafe_decode64(payload))

# Create the HMAC signature
expected_sig = OpenSSL::HMAC.digest("SHA256", secret, payload)

if decoded_sig != expected_sig
puts 'Bad Signed JSON signature!'
return nil
end
data
end
end

Explanation:

Our facebook_user_deletion method is the endpoint where the request is received. Firstly we are getting signed_request token from the params hash and passing it to our parse_fb_signed_request method as a parameter which will parse it and return the user's data JSON object like this:

{
"algorithm": "HMAC-SHA256",
"expires": 1291840400,
"issued_at": 1291836800,
"user_id": "218471"
}

In this object user_id is our relevant field which we are using to find the user and destroy it.

After that, we are returning a JSON response object to Facebook, which has url and confirmation code key-value pairs. Basically, this URL exists on our server in the form of a webpage where the user can check status of his request by using his own confirmation code.

I am using some interpolation inside values to dynamically inject user ids. Also ENV[‘APP_HOST_URL’] is an environment variable which holds my app’s default host url.

In parse_fb_signed_request method we split the token into two parts with reference to dot(.) to obtain encoded signature and payload.
Then we get the app's Facebook secret id which will be used to construct the expected signature

You can learn more about Base64 and JSON.load methods here:

Base64
JSON.load

After that, we are creating an HMAC signature using SHA256 algorithm, app’s secret and payload object. Finally, an If conditional block confirms the signature by comparing the decoded and newly created signature, thus returning nil object when block fails otherwise it returns data

Add API endpoint as Callback in Facebook Project App:

Go to App Dashboard > Products > Facebook Login > Settings > Data Deletion Requests

Always Love Coding !!

--

--

Moiz Ali

I am a Software Engineer who loves to transform ideas into reality, devise solutions, write code and articles.