PSaaS Appliance: Rate Limiting

Beginning with PSaaS Appliance build 6576, rate limits for API endpoints can be enabled and configured in the Dashboard. Rate limiting in the PSaaS Appliance is done using limitd.

Enable and Configure Rate Limiting

In the PSaaS Appliance Dashboard, go to Rate Limiting.

Click the checkbox next to Enable to enable rate limiting.

By default, Configuration of buckets is empty, which means that limitd's default configuration will be used. Your Customer Success Engineer may advise you to adjust this value if appropriate.

Click Save and wait for the updates to the configuration to complete.

Test Rate Limiting Functionality

When you've enabled rate limiting, the HTTP response includes the following headers:

  • X-RateLimit-Limit: Request limit
  • X-RateLimit-Remaining: Requests available for the current time frame
  • X-RateLimit-Reset: Time until the rate limit resets (in UTC epoch seconds)

To verify that rate limiting is working, you can send a call to any rate-limited API endpoint, such as the Get All Connections endpoint:


curl --request GET \
  --url 'https://YOUR_AUTH0_DOMAIN/api/v2/connections' \
  --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN'
var client = new RestClient("https://YOUR_AUTH0_DOMAIN/api/v2/connections");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer MGMT_API_ACCESS_TOKEN");
IRestResponse response = client.Execute(request);
package main

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

func main() {

	url := "https://YOUR_AUTH0_DOMAIN/api/v2/connections"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("authorization", "Bearer MGMT_API_ACCESS_TOKEN")

	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.get("https://YOUR_AUTH0_DOMAIN/api/v2/connections")
  .header("authorization", "Bearer MGMT_API_ACCESS_TOKEN")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://YOUR_AUTH0_DOMAIN/api/v2/connections",
  "method": "GET",
  "headers": {
    "authorization": "Bearer MGMT_API_ACCESS_TOKEN"
  }
}

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

var options = { method: 'GET',
  url: 'https://YOUR_AUTH0_DOMAIN/api/v2/connections',
  headers: { authorization: 'Bearer MGMT_API_ACCESS_TOKEN' } };

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

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

NSDictionary *headers = @{ @"authorization": @"Bearer MGMT_API_ACCESS_TOKEN" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_AUTH0_DOMAIN/api/v2/connections"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];
[request setAllHTTPHeaderFields:headers];

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/connections",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => array(
    "authorization: Bearer MGMT_API_ACCESS_TOKEN"
  ),
));

$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("")

headers = { 'authorization': "Bearer MGMT_API_ACCESS_TOKEN" }

conn.request("GET", "/YOUR_AUTH0_DOMAIN/api/v2/connections", headers=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/connections")

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

request = Net::HTTP::Get.new(url)
request["authorization"] = 'Bearer MGMT_API_ACCESS_TOKEN'

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

let headers = ["authorization": "Bearer MGMT_API_ACCESS_TOKEN"]

var request = NSMutableURLRequest(URL: NSURL(string: "https://YOUR_AUTH0_DOMAIN/api/v2/connections")!,
                                        cachePolicy: .UseProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.HTTPMethod = "GET"
request.allHTTPHeaderFields = headers

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()

Your expected response looks something like this:

HTTP/1.1 200 OK
Date: Wed, 01 Nov 2017 19:52:28 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 366
Connection: keep-alive
Keep-Alive: timeout=100
x-ratelimit-limit: 50
x-ratelimit-remaining: 49
x-ratelimit-reset: 1509565949
vary: origin,accept-encoding
cache-control: no-cache
accept-ranges: bytes
Strict-Transport-Security: max-age=15724800
X-Robots-Tag: noindex, nofollow, nosnippet, noarchive

[{"id":"con_sw...O","options":{"mfa":{"active":true,"return_enroll_settings":true},"disable_signup":true,"brute_force_protection":true,"strategy_version":2},"strategy":"auth0","name":"Initial-Connection","enabled_clients":["aCb...C","ef7...Z"],"is_domain_connection":false,"realms":["Initial-Connection"]}]