Use a Server API Token With an Integration
- Applies to:
- All MindTouch Versions
- Role required:
- Admin
Prerequisites
What You will Need
You should have recorded the following when generating your Server API Token:
- Key
- Secret
How to Use Your Server API Token
To gain access to the Expert API, you first need to provide a Server API Token signature to Expert. Your token signature will be in the following format:
tkn_{key}_{epoch}_{user}_{hash}
Server API Token Signature Breakdown
key |
Provided with your Server API Token |
epoch |
The current time in Unix timestamp (for example Current time: 02/03/2015 @ 5:10am (UTC); Unix timestamp: 1422940200) |
user |
An Expert user id or username prefixed with `=` (for example =admin). The API request will be handled in the context of this user identity. This must be encoded. |
hash |
Expert requires HMAC SHA256 hashing of server API tokens. The benefit of HMAC SHA256 over plain SHA256 is it provides Expert the ability to detect if the token signature has been tampered with since being generated by your server |
The signature is included in an API request by setting it as the X-Deki-Token
HTTP header value. Upon receipt, Expert calculates the same signature and matches it to the signature received. Once validated, your integration can access the Expert API.
Your authentication signature is time-sensitive (5 minutes), and as a common best practice, it's advisable to generate a new token for each API call. If a request is processed too long after the timestamp is created, it may be denied.
Examples
The following are code snippets for PHP, C#, Node.js, and Python to get you started:
Java Example
// Server API Token key and secret are available from API token management dashboard when Server API Token is generated String key = "REPLACE_KEY"; String secret = "REPLACE_SECRET"; // include username prefixed with '=' String user = '=foo'; // ...or include userid String user = '123'; // hash time, key, user with secret String epoch = Long.toString(new Date().getTime() / 1000L); try { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); sha256_HMAC.init(secret_key); String message = key + "_" + epoch + "_" + user; // this example uses Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) to ensure bytes are converted to a HTTP header compatible hex string hash = Hex.encodeHexString(sha256_HMAC.doFinal(message.getBytes())); } catch (NoSuchAlgorithmException | InvalidKeyException e) { // handle signing exceptions } String token = String.join("_", "tkn", key, epoch, user, hash); // send signature as X-Deki-Token HTTP header to MindTouch API URL url = new URL("https://success.example.com/@api/deki/pages/home/info"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("X-Deki-Token", token);
PHP Example
<?php // Server API Token key and secret are available from API token management dashboard when Server API Token is generated $key = 'REPLACE_KEY'; $secret = 'REPLACE_SECRET'; // include username prefixed with '=' $user = '=foo'; // ...or include userid $user = '123'; // hash time, key, user with secret $epoch = time(); $hash = hash_hmac('sha256', ("{$key}_{$epoch}_{$user}"), $secret, false); $token = "tkn_{$key}_{$epoch}_{$user}_{$hash}"; // send signature as X-Deki-Token HTTP header to MindTouch API (a fictional HTTP client is used in this example) $client = new HttpClient('https://success.example.com/@api/deki/pages/home/info'); $client = $client->withHeader('X-Deki-Token', $token); $response = $client->get();
C# Example
using System; using System.IO; using System.Security.Cryptography; using System.Net.Http; // Server API Token key and secret are available from API token management dashboard when Server API Token is generated var key = "REPLACE_KEY"; var secret = "REPLACE_SECRET"; // include username prefixed with '=' var user = "=admin"; // ...or include userid user = "1"; // hash time, key, user with secret var hash = ""; var epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; using (var hmac = new HMACSHA256(Encoding.ASCII.GetBytes(secret))) { var bytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(string.Format("{0}_{1}_{2}", key, epoch, user))); hash = BitConverter.ToString(bytes).Replace("-", ""); } var signature = string.Format("tkn_{0}_{1}_{2}_{3}", key, epoch, user, hash); // send signature as X-Deki-Token HTTP header to MindTouch API (WebRequest is used in this example) var client = new HttpClient(); client.DefaultRequestHeaders.Add("X-Deki-Token", signature); var response = await client.GetAsync("https://authtalk.mindtouch.es/@api/deki/users/current?dream.out.format=json"); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body); // Exchange signature token for a user's authtoken for immediate access via a link. // https://{authtalk.mindtouch.es}/@api/deki/users/authenticate?x-deki-token={signature} Console.WriteLine($"https://authtalk.mindtouch.es/@api/deki/users/authenticate?x-deki-token={signature}"); Console.WriteLine($"https://authtalk.mindtouch.es/@api/deki/users/authenticate?x-deki-token={signature}&redirect=https%3A%2F%2Fauthtalk.mindtouch.es%2F");
Node.js Example
// Server API Token key and secret are available from API token management dashboard when Server API Token is generated const key = 'REPLACE_KEY'; const secret = 'REPLACE_SECRET'; // include username prefixed with '=' let user = '=foo'; // ...or include userid let user = '123'; // hash time, key, user with secret const crypto = require('crypto'); const hmac = crypto.createHmac('sha256', secret); const epoch = Math.floor(Date.now() / 1000); hmac.update(`${key}_${epoch}_${user}`); const hash = hmac.digest('hex'); const token = `tkn_${key}_${epoch}_${user}_${hash}`; // send signature as X-Deki-Token HTTP header to MindTouch API (https://github.com/request/request is used in this example) const request = require('request'); request({ url: 'https://success.example.com/@api/deki/pages/home/info', headers: { 'X-Deki-Token': token } }, (error, response, body) => { // ... });
Python 3 Example
import hashlib import time import requests import hmac # Server API Token key and secret are available from API token management dashboard when Server API Token is generated key = 'REPLACE_KEY' secret = 'REPLACE_SECRET' # include username prefixed with '=' user = '=foo'; # ...or include userid user = '123'; # hash time, key, user with secret epoch = str(int(time.time())) message_bytes = f'{key}_{epoch}_{user}'.encode('utf-8') secret_bytes = secret.encode('utf-8') hash = hmac.new(secret_bytes, message_bytes, digestmod=hashlib.sha256).hexdigest().lower() token = f'tkn_{key}_{epoch}_{user}_{hash}' # send signature as X-Deki-Token HTTP header to MindTouch API (Python Requests is used in this example) headers = { 'X-Deki-Token': token, } response = requests.get('https://success.example.com/@api/deki/pages/home/info', headers=headers, verify=False) # Handling the response if response.status_code == 200: # Success print(response.text) else: # Error print(f"Error: {response.status_code} - {response.text}")
Postman Example
In pre-request script:
// Server API Token key and secret are available from API token management dashboard when Server API Token is generated const key = 'REPLACE_KEY'; const secret = 'REPLACE_SECRET'; // include username prefixed with '=' let user = '=admin'; // ...or include userid let user = '123'; const epoch = Math.floor(Date.now() / 1000); var hash = CryptoJS.HmacSHA256(`${key}_${epoch}_${user}`, secret); const token = `tkn_${key}_${epoch}_${user}_${hash}`; pm.request.headers.add({ key: 'x-deki-token', value: token });
Authenticate With a Server API Token
This authentication method should only be used to implement Single Sign-On if it is not possible to leverage Expert's supported enterprise-grade OpenID Connect or SAML SSO solutions.
A Server API Token signature can be traded for an Auth Token session cookie, which will sign in a user. Using this method, you can construct a URI that logs the user in and redirects to any page in Expert. To tell the API to issue an Auth Token session cookie, use the following format to create a URI for the user to follow:
GET https://{hostname}/@api/deki/users/authenticate?x-deki-token={signature}&redirect={redirect}
{hostname}
is the hostname of the Expert site{signature}
is the server API token signature{redirect}
is a URI for the user to be redirected to (for example redirect=https://example.com/foo). This URI must be URI encoded
Since this URI is valid for only a few minutes, it should not be generated as a URI on one of your pages directly. Instead, it should be a redirect response of a request to your server that authenticates the user in your system. The system should build the URI at the time of request. After the user follows the URI, if the authentication is successful they receive HTTP response headers similar to the following:
HTTP/1.1 302 FOUND Date: Thu, 28 Feb 2013 19:58:59 GMT Server: Dream-HTTPAPI/2.4.0.393 X-Deki-Site: id="{site}" X-Deki-Session: {session} Content-Type: text/plain; charset=us-ascii Content-Length: 20 Location: {redirect} Set-Cookie: authtoken="{authtoken}"; Domain=.{hostname}; Set-Cookie: dekisession="{session}"; Domain=.{hostname};
This results in a sign in workflow like this:
- A user logged into your authentication system clicks a URI to go to the Expert site. Note: the URL actually points to an endpoint on your site.
- Your endpoint validates the user's credentials.
- Your endpoint constructs the Server API Token signature and the redirect URI above.
- Your endpoint responds with a
302 Found
response and the constructed URI as itsLocation
Header. - The user's browser redirects to the Expert API.
- The Expert API creates the user as a Community Member if they do not exist on Expert site, and issues a
302 Found
response including the Auth Token session cookie and theLocation
Header for{redirect}
.