GDPR: Protect and secure user data

As per article 32 of GDPR, you must implement appropriate security measures in order to ensure a level of security appropriate to the risk, including (but not limited to):

  • Τhe encryption of personal data
  • Τhe ability to ensure the ongoing confidentiality, integrity, availability and resilience of processing systems and services
  • Τhe ability to restore the availability and access to personal data in a timely manner in the event of a physical or technical incident

There are several Auth0 features than can help you achieve that, like user profile encryption, brute-force protection, breached password detection, step-up authentication, and more.

The contents of this document are not intended to be legal advice, nor should they be considered a substitute for legal assistance. The final responsibility for understanding and complying with GDPR resides with you, though Auth0 will assist you in meeting GDPR requirements where possible.

Encrypt user profile information

You can encrypt user information before you save it in the user profile. You can use any encryption mechanism you like prior to storing data in the metadata fields. When a user sets sensitive information, call the Update a user endpoint.

For example, to save the encrypted passportNumber in the user's profile, send this request:


curl --request PATCH \
  --url 'https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id' \
  --header 'authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{"user_metadata": {"passportNumber": "B9MuhaDoreVr69MDqx3p8A=="}}'
var client = new RestClient("https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id");
var request = new RestRequest(Method.PATCH);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Bearer YOUR_ACCESS_TOKEN");
request.AddParameter("application/json", "{\"user_metadata\": {\"passportNumber\": \"B9MuhaDoreVr69MDqx3p8A==\"}}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id"

	payload := strings.NewReader("{\"user_metadata\": {\"passportNumber\": \"B9MuhaDoreVr69MDqx3p8A==\"}}")

	req, _ := http.NewRequest("PATCH", url, payload)

	req.Header.Add("authorization", "Bearer YOUR_ACCESS_TOKEN")
	req.Header.Add("content-type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.patch("https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id")
  .header("authorization", "Bearer YOUR_ACCESS_TOKEN")
  .header("content-type", "application/json")
  .body("{\"user_metadata\": {\"passportNumber\": \"B9MuhaDoreVr69MDqx3p8A==\"}}")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id",
  "method": "PATCH",
  "headers": {
    "authorization": "Bearer YOUR_ACCESS_TOKEN",
    "content-type": "application/json"
  },
  "processData": false,
  "data": "{\"user_metadata\": {\"passportNumber\": \"B9MuhaDoreVr69MDqx3p8A==\"}}"
}

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id',
  headers: 
   { 'content-type': 'application/json',
     authorization: 'Bearer YOUR_ACCESS_TOKEN' },
  body: 
   { user_metadata: { passportNumber: 'B9MuhaDoreVr69MDqx3p8A==' } },
  json: true };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer YOUR_ACCESS_TOKEN",
                           @"content-type": @"application/json" };
NSDictionary *parameters = @{ @"user_metadata": @{ @"passportNumber": @"B9MuhaDoreVr69MDqx3p8A==" } };

NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"PATCH"];
[request setAllHTTPHeaderFields:headers];
[request setHTTPBody:postData];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "PATCH",
  CURLOPT_POSTFIELDS => "{\"user_metadata\": {\"passportNumber\": \"B9MuhaDoreVr69MDqx3p8A==\"}}",
  CURLOPT_HTTPHEADER => array(
    "authorization: Bearer YOUR_ACCESS_TOKEN",
    "content-type: application/json"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import http.client

conn = http.client.HTTPSConnection("")

payload = "{\"user_metadata\": {\"passportNumber\": \"B9MuhaDoreVr69MDqx3p8A==\"}}"

headers = {
    'authorization': "Bearer YOUR_ACCESS_TOKEN",
    'content-type': "application/json"
    }

conn.request("PATCH", "/YOUR_AUTH0_DOMAIN/api/v2/users/user_id", payload, headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))
require 'uri'
require 'net/http'

url = URI("https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Patch.new(url)
request["authorization"] = 'Bearer YOUR_ACCESS_TOKEN'
request["content-type"] = 'application/json'
request.body = "{\"user_metadata\": {\"passportNumber\": \"B9MuhaDoreVr69MDqx3p8A==\"}}"

response = http.request(request)
puts response.read_body
import Foundation

let headers = [
  "authorization": "Bearer YOUR_ACCESS_TOKEN",
  "content-type": "application/json"
]
let parameters = ["user_metadata": ["passportNumber": "B9MuhaDoreVr69MDqx3p8A=="]]

let postData = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: nil)

var request = NSMutableURLRequest(URL: NSURL(string: "https://YOUR_AUTH0_DOMAIN/api/v2/users/user_id")!,
                                        cachePolicy: .UseProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.HTTPMethod = "PATCH"
request.allHTTPHeaderFields = headers
request.HTTPBody = postData

let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    println(error)
  } else {
    let httpResponse = response as? NSHTTPURLResponse
    println(httpResponse)
  }
})

dataTask.resume()

Replace the YOUR_ACCESS_TOKEN placeholder with a token that will allow you to access this endpoint. This should be a Management API Token, with the scopes update:users and update:users_app_metadata.

Enable brute-force protection

You can enable the brute-force protection shield in order to stop malicious attempts to access your application.

Every time Auth0 detects 10 failed login attempts into a single account from the same IP, we will:

  • Send a notification email to the user
  • Block the suspicious IP address

You can enable brute-force protection, configure which actions you want to take, and customize the blocked account email using the Dashboard.

For more information and configuration steps, see Brute Force Protection.

Enable breached password detection

The breached password detection shield helps you identity user credentials that might have been compromised in a public data breech.

Auth0 tracks large security breaches that are happening on major third party sites. If one of your users' credentials were included in a public security breech, you can take action and:

  • Send an email to the affected user
  • Send an email to dashboard owners immediately, and/or have a daily/weekly/monthly summary
  • Block login attempts for suspected user accounts using that username and password combination. This block remains in place until the user changes their password

You can enable breached password detection and configure which actions you want to take using the Dashboard.

For more information and steps to follow, see Breached Password Detection.

Harden your security with multi-factor authentication

With multi-factor authentication (MFA), you can add an additional layer of security to your applications. It is a method of verifying a user's identity by asking them to present more than one piece of identifying information.

We support MFA using push notifications, SMS, one-time password authentication services, and custom providers. You can enable MFA for specific users or specific actions (for example, access screens with sensitive data). You can also define the conditions that will trigger additional authentication challenges, such as changes in geographic location or logins from unrecognized devices.

To review all available options and their features, and get implementation details for the one that suits your needs, see Multi-factor Authentication in Auth0.

Help your users choose better passwords

You can customize the level of password complexity for new sign ups. For example, you can ask for a password that has at least 10 characters and includes at least one upper-case letter, a number, and a special character.

You can also forbid the use of previous passwords using our Password History feature and stop users from choosing common passwords using our Password Dictionary.

All three features are configurable from the Dashboard.

For information on how to use them see Password Strength and Password Options.

Step-up authentication

With step-up authentication, applications can ask users to authenticate with a stronger authentication mechanism to access sensitive resources. For example, you may have a banking application which does not require Multi-factor Authentication (MFA) to view the accounts basic information, but when users try to transfer money between accounts then they must authenticate with one more factor (for example, a code sent via SMS).

You can check if a user has logged in with MFA by reviewing the contents of their ID Token or Access Token. You can then configure your application to deny access to sensitive resources if the token indicates that the user did not log in with MFA.

For details see Step-up Authentication.

Availability and resilience

Auth0 is designed and built as a scalable, highly available, multi-tenant cloud service. We are highly resilient to the failure of any of our components, because we implement redundant components at all levels. We also detect failures rapidly and our failover is very quick.

We support four deployment models:

  • A multi-tenant cloud service running on Auth0's cloud
  • A dedicated cloud service running on Auth0's cloud
  • A dedicated cloud service running on Customer's cloud infrastructure
  • An on-premises virtual Private SaaS (PSaaS) Appliance running on Customer's private environment (for the cases where a public cloud-based solution is not acceptable).

You decide which deployment model works best for you based on your business and security requirements.

For more information on Auth0 architecture, see Availability & Trust.

For more information on the available deployment models of Auth0, see Auth0 Deployment Models.