The REST interface for BrightCloud Web Service (BCWS) uses the OAuth protocol to authenticate incoming requests. More specifically, it uses the 2-legged variation of OAuth protocol, as there are only 2 parties involved in a BCWS transaction - the end user ("consumer," in OAuth terms) and the server hosting BCWS ("provider," in OAuth terms).
The end user role in a BCWS transaction requires registration with the BCWS website in order to generate a key/secret pair. This is a one time activity. BCWS refers to these as your BCWS Secret Access Key and your BCWS Access Key ID. Using the key/secret pair, the end user generates a digital signature in accordance with OAuth protocol for the BCWS request; this request will include the generated signature in the request header (as part of Authorization header). This "signed" request is then sent to the BCWS server.
The BCWS server's role in the transaction is to extract the digital signature from the Authentication header in the request, authenticate it, and return the appropriate response if the user is authenticated and the request is valid. Alternatively, the BCWS server will send an error if the authentication fails or there is some other problem with the request.
One can visit BCWS website to register and generate a unique key/secret pair to be used for making requests to BCWS. For scenarios where a user may need BCWS integration with more than one application, a registered user can request more than one key/secret pair and name them appropriately for easy identification and use in their applications. The website also allows resetting an existing key/secret pair so that any subsequent requests signed using the original pair will no longer be fulfilled by BCWS. This may be useful in a situation where a user thinks that a particular key/value pair has been compromised.
NOTE: For those of you who refer to the specification or 3rd party code later the BCWS Access Key ID is called the Consumer Key and the BCWS Secret Access Key ID is called the Consumer Secret in OAuth parlance.
The rest of this document contains a lot of information on the mechanics of correctly creating the OAuth header to sign BCWS API calls. For the more productive and less hard-core of you, there are plenty of OAuth libraries already available in many languages. A good place to look first is the OAuth code page which has links to many OAuth libraries. One of the advantages of using a standards based approach to authentication is that there are also more and more example integrations being made available on the web using the library of your choice every day.
For every request to BCWS, the user needs to generate a digital signature in accordance with the 2-legged OAuth protocol and send it as part of the request headers. The signature should be generated using the HMAC-SHA1 algorithm (BCWS does not support the PLAINTEXT or RSA-SHA1 algorithms).
The 2-legged OAuth approach is slightly different from the more common 3-legged OAuth approach. Since only two parties are involved in the 2-legged OAuth scenario, one doesn't need to request a Request Token or exchange that Request Token for an Access Token. Therefore, a blank string should be used in place of the Access Token and the Access Token Secret, which are never required. In summary:
Next, we'll walk through the mechanics of a sample signing.
Let's assume that the user wants to retrieve classification information for a URL "www.whatismyclassification.com" from BCWS. We'll also assume that the user has previously registered with BCWS and obtained the BCWS Access Key ID (aka Consumer Key) dpf43f3p2l4k3l03 and BCWS Secret Access Key ID (aka Consumer Secret Key) kd94hf93k423kf44. To sign the request, the user will use the HMAC-SHA1 signature method, and generate an Nonce string kllo9940pd9333jh and Timestamp 1191242096.
The OAuth information such as Consumer Key is included in the request using special OAuth Parameters starting with the 'oauth_' prefix, most of which are mandatory. OAuth does not allow any other parameter to use the 'oauth_' prefix. These OAuth parameters are not only sent as part of HTTP request, they are also used to calculate an OAuth signature for the request which, in turn is included with the other OAuth parameters in the request.
Although OAuth specs allow for 3 different methods for calculating OAuth signature, BCWS currently supports only HMAC-SHA1 method. OAuth signature calculation for a BCWS request involves constructing a signature base string that serves as the HMAC-SHA1 text which will be "signed," constructing a key that serves as the HMAC-SHA1 algorithm key and then using the HMAC-SHA1 text and key in the HMAC-SHA1 algorithm to generate the signature.
There are three pieces to a signature base string:
These three strings are concatenated together, separated by an ampersand ('&'), to generate the signature base string.
For our sample request, the HTTP method to be used is GET. We start our signature base string with it
URLs are constructed from various elements, and take the general form of scheme://authority:port/path?query#fragment. The scheme and port are used to establish the desired connection, the authority is used in the 'Host' header and to connect to the Service Provider, and the path and query parts are used in the request itself (the fragment is used locally by the browser and is not transmitted with the request).
The request URL is normalized as scheme://authority:port/path. Please note that the query and the fragment are excluded from the normalized URL. The scheme and authority must be in lowercase, and the port must be present except for the default HTTP(S) ports which must be omitted ('80' is omitted when the scheme is 'http' and '443' is omitted when the scheme is 'https'). The path must retain its case as some web servers are case-sensitive.
For our sample request, the REST resource URL that the user needs to access is
which after normalization becomes -
The URL encoding of the normalized URL yields the following string
For our sample request, the following table contains our OAuth parameters
| Name | Value |
|---|---|
| oauth_version | 1.0 |
| oauth_consumer_key | dpf43f3p2l4k3l03 |
| oauth_token | |
| oauth_signature_method | HMAC-SHA1 |
| oauth_nonce | kllo9940pd9333jh |
| oauth_timestamp | 1191242096 |
These OAuth Parameters are collected together in their raw, pre-encoded form. All text parameters are UTF-8 encoded. After UTF-8 encoding, the parameters are URL-encoded. All the unreserved characters (letters, numbers, '-', '_', '.', '~') must not be encoded, while all other characters are encoded using the %XX format where XX is an uppercase representation of the character's hexadecimal value.
The parameters are then sorted first based on their encoded names, and if equal, based on their encoded values. Sort order is lexicographical byte value ordering, this is the default string sort method in most languages, and means comparing the byte value of each character and sorting in an ascending order resulting in a case sensitive sort.
The following table contains the OAuth parameters for our sample request after the required encoding and sorting
| Name | Value |
|---|---|
| oauth_consumer_key | dpf43f3p2l4k3l03 |
| oauth_nonce | kllo9940pd9333jh |
| oauth_signature_method | HMAC-SHA1 |
| oauth_timestamp | 1191242096 |
| oauth_token | |
| oauth_version | 1.0 |
Once encoded and sorted, the parameters are concatenated together into a single string. Each parameter's name is separated from the corresponding value by an equals sign (‘=’) character, even if the value is empty, and each name-value pair is separated by an ampersand (‘&’) character. The result is the normalized parameter string.
For our sample request, the normalized parameter string looks like this
The URL encoding of the normalized parameters yields the following string
To generate the signature base string, the three pieces generated above are concatenated together separated by an '&'. For our sample request, the resulting signature base string is
The HMAC-SHA1 signature method uses two secrets, the Consumer Secret and the Token Secret (which is blank in our case) as the HMAC-SHA1 algorithm key. To construct the algorithm key, each secret is UTF8-encoded, URL-encoded, and concatenated into a single string using an ampersand ('&') character as a separator even if either secret is empty. Libraries should not assume the secrets are in plain ASCII text and ensure proper UTF-8-encoding and URL-encoding prior to concatenation.
For our sample request, the UTF8-encoded, URL-encoded Consumer Secret is
The UTF8-encoded, URL-encoded Token Secret is
The resulting HMAC-SHA1 algorithm key is
(Note the empty string after the & because our Token Secret is empty).
Using the signature base string generated in Step 1 as the "HMAC-SHA1 text" and the key generated in Step 2 as the "HMAC-SHA1 algorithm key," the HMAC-SHA1 algorithm will generate an octet string which must be base64-encoded with equals ('=') padding. Here's the signature we calculated for our sample request
The calculated signature is added to the request using the 'oauth_signature' parameter. When the signature is included in the HTTP request, it must be properly encoded as required by the method used to transmit the parameters.
Please note that BCWS requires OAuth parameters to be sent strictly as part of HTTP Authorization header as depicted in the sample above. BCWS doesn't yet support OAuth parameters delivered to it in the URL query element or in a single-part 'application/x-www-form-urlencoded' POST body.
Here's how our sample request would look after including the signature
OAuth is a great standards based way of authenticating BCWS requests. As the community strengthens the libraries and implementations, every application developer benefits from those fixes and performance improvements. We strongly encourage you to download, use, and contribute where appropriate to the OAuth code base of your choosing.
If any part of this documentation is confusing or if you need additional help, please check out our forums or send us feedback. We created this for you to use, and want to make sure we're doing the best we can to provide you what you need to enable better applications!