SymetryML REST API Security
SymetryML REST Request Authentication
The SymetryML REST API allows you to authenticate your requests. The API’s authentication is based on a "message-authentication code" signature created using specific parts of the REST API HTTP request.
Message authentication code (MAC) provides a way to verify the integrity of information sent in a REST request based on a secret key known only to the request sender and receiver. Because only two parties know the secret key, validating the MAC signature also authenticates the corresponding REST request. For this reason, each SymetryML API account has a secret key associated with its SymetryML key ID that is used to create a MAC signature for each REST request. The SymetryML server uses this secret key to verify signatures and authenticate all requests.
Authentication Header
The SymetryML REST API uses the HTTP Authorization header to pass authentication information to the server. The signature is an HMAC-SHA256 (HMAC-SHA2, RFC 4868) of a string built from the request.
Changed in SymetryML 7.0. The secret key is no longer part of the string to sign; it is only the HMAC key. HMAC-SHA1 is no longer accepted, and every request must send sym-version with major version 7. Clients written for 6.x get 401 Invalid Signature or 400 until they are upgraded. See Protocol Version Header.
| Header | Description |
|---|---|
| Authorization | Signature |
| Signature | Base64( HMAC-SHA256( Base64Decode(SecretKey), UTF-8-Encoding-Of( StringToSign ) ) ) |
| StringToSign | HTTP-Verb + "\n" + Content-MD5 + "\n" + Sym-Date + "\n" + SymetryML-customer-Id + "\n" + RequestBody + "\n" + CanonicalizedResource + "\n" + URLQueryParameters + "\n" |
| SecretKey | The customer's SymetryML secret key, a Base64-encoded 128-bit key. The decoded bytes are the HMAC key. The secret key never appears in the string to sign. |
| Content-MD5 | Base64 of the MD5 digest of the UTF-8 request body. An empty string when there is no body; the newline that follows it is still added. |
| Sym-Date format | See the section covering Date Header. |
| CanonicalizedResource | <HTTP-Request-URI, from the protocol name up to the query string> |
| URLQueryParameters | Any URL query parameters used in the REST request. If no query parameters are present, do not add null or a new line "\n". |
| RequestBody | JSON request body. If there is no request body, omit this along with the newline ("\n") that follows it. |
| sym-version | Protocol version of the client. Required; must be 7.x. Not part of the string to sign. See Protocol Version Header. |
| sym-client | This parameter is not mandatory and not used in computing the string to sign, but is used when compiling logging statistics about the data source and streaming API. For more details please consult the DS Log section. |
Protocol Version Header
Every request must carry a sym-version header whose major version is 7, for example:
sym-version: 7.0Any minor version is accepted. A request with no sym-version header, or with a major version other than 7, is refused with 400 BAD REQUEST before the signature is checked. The message names the version the server requires. WebSocket messages carry the same version in their header; see WebSocket API.
SymetryML 7.0 has no backward compatibility with 6.x clients: the signature and the encrypted body format both changed. Upgrade pymetry, the web UI, the Java client and any custom client together with the server.
Encrypted Request and Response Bodies
Some request bodies and response values carry credentials (data source definitions, federation information, fusion cell information) and are encrypted with the customer's secret key, so they are never sent in the clear even without HTTPS. The SymetryML 7.0 format is:
v2:Base64( nonce[12] || AES-GCM-128(key, nonce, UTF-8 plaintext) || tag[16] )| Part | Description |
|---|---|
v2: | Format prefix. Required. A receiver reads everything up to the first : and refuses any other prefix. |
| nonce | 12 random bytes, drawn fresh for every encryption. Never reuse a nonce with the same key. |
| key | The Base64-decoded secret key (16 bytes). |
| tag | The 128-bit GCM authentication tag, appended to the cipher text. A modified payload or a wrong key fails decryption. |
No additional authenticated data is used. Federation invitations are encrypted with a password instead of the secret key: the password (at most 16 characters) is zero-padded to a 16-byte key, and the output has the same v2: format.
The pre-7.0 format (bare Base64, AES/CBC/PKCS5Padding with a fixed initialization vector) is no longer accepted. A body in that format is refused with 400 BAD REQUEST.
SymetryML Date Header
Each SymetryML REST request must contain a SymetryML Date header. The content of this header is a date and time based on the Universal Coordinated Time/Greenwich Mean Time (UTC/GMT) time zone. This header is called sym-date.
The SymetryML Date header must:
- Follow this syntax:
yyyy-MM-dd HH:mm:ss;nanosecondsFor example:
2014-07-31 08:01:07;1245- Not be 5 minutes or more behind the server time
- Not be more than 1 minute ahead of the server time.
Authentication Errors
If the signature does not verify, the server returns a 401 (UNAUTHORIZED) response with the status string Invalid Signature.
When the server runs with debug logging, the response also contains a stringToSign entity: the string the server signed when it checked the request. Compare it with the string your client signed to find the difference. In normal operation the entity is not sent.
The following shows an example of an unauthorized response from a server with debug logging on.
{
"statusCode":"UNAUTHORIZED",
"statusString":"Invalid Signature",
"values":{
"stringToSign":"DELETE\\n\\n2013-05-22 18:13:38\\nc1\\nhttp://192.168.0.19:8080/symetry/rest/c1/projects/r1\\n"
}
}Authentication Error Codes
To help you identify and resolve authentication issues quickly, the SymetryML REST API supports a variety of error codes. The following table describes the supported error codes.
| API Error Codes | ||
|---|---|---|
| Error Code | HTTP Code | Description |
| Md5 do not match | 400 | MD5 of the request body is invalid. |
| Invalid User | 401 | Server does not know this user. |
| Invalid Signature | 401 | Authentication header signature is invalid. |
| Invalid Signature: too many authentication error, disabling user credential | 401 | Too many failed signatures for this user; the user's credential is disabled. |
| Unlicensed Software | 401 | The server license is missing or expired. |
| Too many users | 401 | The server has more users than its license allows. |
| Authorization header is null | 400 | Authorization header is missing from the request. |
| sym-date header is null | 400 | SymetryML date header is missing from the request. |
| Missing sym-version header; … / Client protocol version […] is not supported; … | 400 | The sym-version header is missing or its major version is not 7. See Protocol Version Header. |
| Please update your server time, it is likely out of sync with UTC | 400 | Date in the request is more than 5 minutes before the server time or more than 1 minute after it. Check the time configuration on your client. |
| Invalid Date format: … | 400 | Format of the SymetryML date header is invalid. See the section SymetryML Date Header for information about the appropriate format to use. |
| Duplicate request. | 403 | A request with the same signature was already received. Every request needs its own sym-date, and so its own signature. |
| Redis store is not in SymetryML 7.0 format … | 503 | The server was upgraded from 6.x but its stored credentials were not migrated. Every request is refused until the migration is done; see the Installation Guide. |
Cross-Origin Resource Sharing (CORS)
By default the REST API sends no CORS headers, so a browser page served from a different origin cannot call it directly. CORS is opt-in: start the SymetryML JVM with
-Dsml.rest.cors=trueSee SymetryML REST Configuration for where to set this in a Docker deployment.
When the flag is on, every REST response carries the following headers:
| Header | Value |
|---|---|
Access-Control-Allow-Origin | * |
Access-Control-Allow-Methods | GET, POST, PUT, DELETE, OPTIONS |
Access-Control-Allow-Headers | Content-MD5, Sym-date, Customer-ID, Authorization, sym-version, Content-Type |
Access-Control-Max-Age | 86400 |
The browser's preflight OPTIONS request is answered automatically and passes through the same filter, so preflight needs no additional configuration.
Note: Access-Control-Allow-Credentials is deliberately not sent. The API is request-signed with HMAC-SHA2 and uses no cookies or sessions, so a browser has no ambient credential to attach — a page can only call the API if it holds the customer's secret key. Bear in mind that a secret key placed in browser-side code is visible to anyone who loads that page.
APIs at-a-Glance
Please note that Every REST request that is made starts with the following canonical URL:
HTTPVERB /symetry/rest/{cid}where:
{cid}is the customer ID.- HTTP VERB is a valid HTTP verb such as
GET,PUT,POST, orDELETE.