DomainTools API Guide: Authentication
Most requests sent to the DomainTools API require authentication. We support two authentication schemes with different levels of security. Choose the one that best fits your implementation.
It is vitally important that you protect your API credentials. Your account will be charged for all queries authenticated with your key even if you later determine the requests were fraudulent.
Open Key Authentication
This is the easiest authentication scheme to implement, but also the most insecure. You should take precautions in the design of your application to ensure your key is not compromised.
http://api.domaintools.com/v1/domaintools.com?api_username=example&api_key=xxxxxx
Signed Authentication
HMAC, or hashed message authentication code, is our preferred authentication scheme. It follows the principles outlined in RFC2104 and provides a straightforward but secure method of protecting your API key. It involves passing a hash composed of your api username, the current date and time, and the request URI. This hash is then signed with your authentication key. The result is a request that expires after a brief period of time and, most importantly, does not contain your authentication key.
2011-02-01T14:37:59-0800
2011-02-01T22:37:59Z
2011-02-02T10:37:59+1200
To create the signature, build a string with your api username, a timestamp in ISO 8601 format, and the URI you are requesting. That string is then signed with your api key using an HMAC function to give the signature.
Follow these guidelines when build your signature:
- 1) The URI is the part of the URL after api.domaintools.com of your request e.g. /v1/yourdomain.com/whois
- 2) Timestamps should be in ISO 8601 format and contain the timezone offset
- 3) The timestamp value for the hash and timestamp parameter passed to the API need to be identical
- 4) Make sure your server time is accurate and that you always use a fresh timestamp
- 5) Use only MD5, SHA1, or SHA256 for the hashing algorithm
You'll likely find built-in support for HMAC authentication in your preferred programming language. We support several hashing algorithms and we closely follow the HMAC standard to ensure the widest support possible.
NOTE: The following code samples are provided for educational purposes only.
PHP
class DTSigner {
private $api_username;
private $api_key;
public function __construct($api_username, $api_key) {
$this->api_username = $api_username;
$this->api_key = $api_key;
}
public function timestamp() {
return gmdate("Y-m-d\TH:i:s\Z");
}
public function sign($timestamp, $uri) {
return hash_hmac('md5', $this->api_username . $timestamp .
$uri, $this->api_key);
}
}
//example of using DTSigner
$api_username = 'your_username';
$api_key = 'xxxxx-xxxxx-xxxxx-xxxxx-xxxxx';
$uri = '/v1/yourdomain.com/whois';
$host = 'api.domaintools.com';
$signer = new DTSigner($api_username, $api_key);
$timestamp = $signer->timestamp();
$signature = $signer->sign($timestamp, $uri);
echo 'http://' . $host . $uri . '?api_username=' . $api_username . '&signature=' .
$signature . '×tamp=' . $timestamp;
Python
#!/usr/bin/env python
import hmac
import hashlib
from datetime import datetime
class DTSigner(object):
def __init__(self, api_username, api_key):
self.api_username = api_username
self.api_key = api_key
def timestamp(self):
return datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
def sign(self, timestamp, uri):
params = ''.join([self.api_username, timestamp, uri])
return hmac.new(self.api_key, params, digestmod=hashlib.sha1).hexdigest()
if __name__ == "__main__":
api_username = 'your_username'
api_key = 'xxxxx-xxxxx-xxxxx-xxxxx-xxxxx';
uri = '/v1/yourdomain.com/whois'
host = 'api.domaintools.com'
signer = DTSigner(api_username, api_key)
timestamp = signer.timestamp()
signature = signer.sign(timestamp, uri)
print 'http://{0}{1}?api_username={2}&signature={3}×tamp={4}'.format(
host, uri, api_username, signature, timestamp)
Ruby
class DomainToolsSigner
def self.get(username, key, uri)
timestamp = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
data = username+timestamp+uri
digester = OpenSSL::Digest::Digest.new("md5") # can be sha1 | sha256
signature = OpenSSL::HMAC.hexdigest(digester, key, data)
"api_username=#{username}&signature=#{signature}×tamp=#{timestamp}"
end
end
api_username = 'your_username';
api_key = 'xxxxx-xxxxx-xxxxx-xxxxx-xxxxx';
uri = '/v1/yourdomain.com/whois';
host = 'api.domaintools.com';
authentication = DomainToolsSigner.get(api_username,api_key, uri)
puts "http://#{host}#{uri}?#{authentication}"
Java
import javax.crypto.Mac;
import java.security.SignatureException;
import javax.crypto.spec.SecretKeySpec;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DTSigner {
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
private String api_username;
private String api_key;
private SimpleDateFormat timeFormatter;
public DTSigner(String api_username, String api_key) {
this.api_username = api_username;
this.api_key = api_key;
this.timeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
}
public String timestamp() {
Date now = new Date();
return this.timeFormatter.format(now);
}
public String getHexString(byte[] b) {
String result = "";
for (int i=0; i < b.length; i++) {
result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring(1);
}
return result;
}
public String sign(String timestamp, String uri)
throws java.security.SignatureException {
String Result;
try {
String data = new String(this.api_username + timestamp + uri);
SecretKeySpec signingKey = new SecretKeySpec(this.api_key.getBytes(),
HMAC_SHA1_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
byte[] rawSignature = mac.doFinal(data.getBytes());
Result = this.getHexString(rawSignature);
} catch(Exception e) {
throw new java.security.SignatureException("Failed to generate HMAC : "
+ e.getMessage());
}
return Result;
}
public static void main(String args[]) {
String api_username = "your_username";
String api_key = "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx";
String uri = "/v1/yourdomain.com/whois";
String host = "api.domaintools.com";
try {
DTSigner signer = new DTSigner(api_username, api_key);
String timestamp = signer.timestamp();
String signature = signer.sign(timestamp, uri);
System.out.println("http://" + host + uri + "?api_username=" +
api_username + "&signature=" + signature + "×tamp="
+ timestamp);
} catch(Exception e) {
System.out.println("Error trying to sign query");
}
}
}
C#
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace DTSigner
{
class Program
{
public static String timestamp()
{
return DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
}
public static String sign(String api_username, String key, String timestamp, String uri)
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] data = encoder.GetBytes(api_username + timestamp + uri);
HMACSHA1 hmac = new HMACSHA1(encoder.GetBytes(key));
CryptoStream cs = new CryptoStream(Stream.Null, hmac, CryptoStreamMode.Write);
cs.Write(data, 0, data.Length);
cs.Close();
String hex = BitConverter.ToString(hmac.Hash);
return hex.Replace("-","").ToLower();
}
public static void Main(string[] args)
{
String api_username = "your_username";
String key = "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx";
String uri = "/v1/yourdomain.com/whois";
String host = "api.domaintools.com";
String timestamp = Program.timestamp();
String signature = Program.sign(api_username, key, timestamp, uri);
Console.WriteLine("http://" + host + uri + "?api_username=" + api_username +
"&signature=" + signature + "×tamp=" + timestamp);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}