Authentication
The REST-API and GraphQL API require authentication for requests. remote.it authentication uses HTTP Request Signature. The advantages of this method are:
    Keys do not expire
    Keys can be disabled and revoked (deleted) by the user at any time
    Keys are not dependent on password
    Keys are more secure (the secret is never transmitted because the request is signed)

Key Management

You can generate, enable, disable and delete keys in the Account section of the web portal here https://app.remote.it. Screen shot is provided below.
Please note: Generation of keys is crypto-random and the secret is only available immediately after creation by clicking the “Show secret access key” link or downloading the key as a CSV file (containing the Access Key ID and Secret Access Key)
You are limited to 2 active access keys. The account page will also show when the key was created and last used for authentication. If you suspect your key has been compromised, generate a new one, replace it in your code and disable. If desired you can delete the compromised key after disabling it.
In addition, if you will be using the REST-API you will also need to retrieve your Developer API Key. This can also be found in the Account section of the web portal.

Create a remote.it Credentials File

You will need to follow the steps above with Key Management to generate your access key and secret before proceeding
Create the following file to save all your remote.it credentials. The file must located be in ~/.remoteit/credentials (in your home directory). For windows, the directory is C:\Users<name>.remoteit\credentials with no extension.
The file is in the standard ini file format:
1
[default]
2
R3_ACCESS_KEY_ID=Z5QCS6ZO7PXXXMVDNXXX
3
R3_SECRET_ACCESS_KEY=XXXWC14Qsktnq/nbF+iXxXq2yc4sVPkQn3J0m5i
4
R3_DEVELOPER_API_KEY=XXXXXXX
Copied!
You can save more than one key pair under different profiles (sections) in the remote.it credentials file. Profile names are case-insensitive, cannot contain a period (.) and default is the default profile name.

API Request Signing

To authenticate an API request, the client must generate a signature using the previously created key and secret. The REST-API example you will also need your Developer API Key which you can get from your account page https://app.remote.it/#account

Examples

These are examples of query requests only for the purposes of how to do the request signing. Please refer to the schema and usage documentation for requests which are supported.
bash/cURL
Node
Python
Other Languages
The examples reads the ~/.remoteit/credentials file for the variables of your access key, secret, and developer key.
GraphQL
1
#!/bin/bash
2
source ~/.remoteit/credentials
3
4
SECRET=`echo ${R3_SECRET_ACCESS_KEY} | base64 --decode`
5
6
HOST="api.remote.it"
7
URL_PATH="graphql/v1"
8
URL="https://{$HOST}/{$URL_PATH}"
9
10
VERB="POST"
11
12
CONTENT_TYPE="application/json"
13
14
LC_VERB=`echo "${VERB}" | tr '[:upper:]' '[:lower:]'`
15
16
DATE=$(LANG=en_US date "+%a, %d %b %Y %H:%M:%S %Z")
17
18
DATA='{ "query": "{ login { email devices (size: 1000, from: 0) { items { id name services { id name} } } } }" }'
19
20
CONTENT_LENGTH=${#DATA}
21
22
SIGNING_STRING="(request-target): ${LC_VERB} /${URL_PATH}
23
host: ${HOST}
24
date: ${DATE}
25
content-type: ${CONTENT_TYPE}
26
content-length: ${CONTENT_LENGTH}"
27
28
echo ${SIGNING_STRING}
29
30
SIGNATURE=`echo -n "${SIGNING_STRING}" | openssl dgst -binary -sha256 -hmac "${SECRET}" | base64`
31
32
SIGNATURE_HEADER="Signature keyId=\"${R3_ACCESS_KEY_ID}\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date content-type content-length\",signature=\"${SIGNATURE}\""
33
34
curl --write-out -v -X ${VERB} -H "Authorization:${SIGNATURE_HEADER}" -H "Date:${DATE}" -H "Content-Type:${CONTENT_TYPE}" ${URL} -d "${DATA}" --insecure
Copied!
REST-API
Please note, that you need the DEVELOPER API KEY in addition to the access key and access key secret. This example is for the purposes of demonstrating the REST-API request signing. For the device list, please use the graphQL API example above.
1
#!/bin/bash
2
source ~/.remoteit/credentials
3
4
SECRET=`echo ${R3_SECRET_ACCESS_KEY} | base64 --decode`
5
6
HOST="api.remote.it"
7
URL_PATH="apv/v27/device/list/all"
8
URL="https://{$HOST}/{$URL_PATH}"
9
10
VERB="GET"
11
12
CONTENT_TYPE="application/json"
13
14
LC_VERB=`echo "${VERB}" | tr '[:upper:]' '[:lower:]'`
15
16
DATE=$(LANG=en_US date "+%a, %d %b %Y %H:%M:%S %Z")
17
DATA=''
18
CONTENT_LENGTH=${#DATA}
19
20
SIGNING_STRING="(request-target): ${LC_VERB} /${URL_PATH}
21
host: ${HOST}
22
date: ${DATE}
23
content-type: ${CONTENT_TYPE}
24
content-length: ${CONTENT_LENGTH}"
25
26
echo ${SIGNING_STRING}
27
28
SIGNATURE=`echo -n "${SIGNING_STRING}" | openssl dgst -binary -sha256 -hmac "${SECRET}" | base64`
29
30
SIGNATURE_HEADER="Signature keyId=\"${R3_ACCESS_KEY_ID}\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date content-type content-length\",signature=\"${SIGNATURE}\""
31
32
curl --write-out -v -X ${VERB} -H "Authorization:${SIGNATURE_HEADER}" -H "DeveloperKey:${R3_DEVELOPER_API_KEY}" -H "Date:${DATE}" -H "Content-Type:${CONTENT_TYPE}" ${URL} --insecure
Copied!
GraphQL
1
const fs = require("fs");
2
const ini = require("ini");
3
const os = require("os");
4
const path = require("path");
5
const httpSignature = require("http-signature");
6
const https = require("https");
7
8
const R3_ACCESS_KEY_ID = "R3_ACCESS_KEY_ID";
9
const R3_SECRET_ACCESS_KEY = "R3_SECRET_ACCESS_KEY";
10
11
const CREDENTIALS_FILE = ".remoteit/credentials";
12
const DEFAULT_PROFILE = "default";
13
14
const SIGNATURE_ALGORITHM = "hmac-sha256";
15
const SIGNED_HEADERS = "(request-target) host date content-type content-length";
16
17
const query = {
18
query: `{ login { email devices (size: 1000, from: 0) { items { id name services { id name} } } } }`,
19
};
20
const data = JSON.stringify(query);
21
22
const options = {
23
hostname: "api.remote.it",
24
port: 443,
25
path: "graphql/v1",
26
method: "POST",
27
headers: {
28
"Content-Type": "application/json",
29
"Content-Length": data.length,
30
},
31
};
32
33
const file = path.resolve(os.homedir(), CREDENTIALS_FILE);
34
35
if (!fs.existsSync(file))
36
return `remote.it credentials file not found: ${file}`;
37
38
let credentials;
39
40
try {
41
credentials = ini.parse(fs.readFileSync(file, "utf-8"));
42
} catch (error) {
43
return `remote.it credentials file error: ${error.message}`;
44
}
45
46
if (profile) {
47
credentials = getSection(credentials, profile);
48
49
if (!credentials) return `remote.it profile not found: ${profile}`;
50
} else {
51
credentials = getSection(credentials, DEFAULT_PROFILE) || credentials;
52
}
53
54
const key = credentials[R3_ACCESS_KEY_ID];
55
56
if (!key) return `remote.it credentials missing: ${R3_ACCESS_KEY_ID}`;
57
58
const secret = credentials[R3_SECRET_ACCESS_KEY];
59
60
if (!secret) return `remote.it credentials missing: ${R3_SECRET_ACCESS_KEY}`;
61
62
await Promise.all([
63
context.store.setItem(R3_ACCESS_KEY_ID, key),
64
context.store.setItem(R3_SECRET_ACCESS_KEY, secret),
65
]);
66
67
const [key, secret] = await Promise.all([
68
context.store.getItem(R3_ACCESS_KEY_ID),
69
context.store.getItem(R3_SECRET_ACCESS_KEY),
70
]);
71
72
httpSignature.sign(new RequestWrapper(context.request), {
73
keyId: key,
74
key: Buffer.from(secret, "base64"),
75
algorithm: SIGNATURE_ALGORITHM,
76
headers: SIGNED_HEADERS.split(/\s+/),
77
});
78
79
const req = https.request(options, (res) => {
80
console.log(`statusCode: ${res.statusCode}`);
81
82
res.on("data", (data) => {
83
process.stdout.write(data);
84
});
85
});
86
87
req.on("error", (error) => {
88
console.error(error);
89
});
90
91
req.write(data);
92
req.end();
Copied!
This example is using a helper library requests_http_signature for python which will sign the request before submitting it to the server. This demonstrates how to safely reference the key and secret from environmental variables rather than including it in the code. You will need to set the environmental variables before executing.
GraphQL
1
import os
2
import requests
3
import json
4
from requests_http_signature import HTTPSignatureAuth
5
from base64 import b64decode
6
7
key_id = os.environ.get('R3_ACCESS_KEY_ID')
8
key_secret_id = os.environ.get('R3_SECRET_ACCESS_KEY')
9
10
body = {"query": "query { login { id email devices { items { id name }}}}"}
11
host = 'api.remote.it'
12
url_path = '/graphql/v1'
13
content_type_header = 'application/json'
14
content_length_header = str(len(body))
15
16
headers = {
17
'host': host,
18
'path': url_path,
19
'content-type': content_type_header,
20
'content-length': content_length_header,
21
}
22
23
response = requests.post('https://' + host + url_path,
24
json=body,
25
auth=HTTPSignatureAuth(algorithm="hmac-sha256",
26
key=b64decode(key_secret_id),
27
key_id=key_id,
28
headers=[
29
'(request-target)', 'host',
30
'date', 'content-type',
31
'content-length'
32
]),
33
headers=headers)
34
35
if response.status_code == 200:
36
print(response.text)
37
else:
38
print(response.status_code)
Copied!
REST-API
Please note, that you need the DEVELOPER API KEY in addition to the access key and access key secret. This example is for the purposes of demonstrating the REST-API request signing. For the device list, please use the graphQL API example above.
1
import requests
2
from requests_http_signature import HTTPSignatureAuth
3
from base64 import b64decode
4
5
# For more on authentication see https://docs.remote.it/api-reference/authentication
6
key_id = os.environ.get('R3_ACCESS_KEY_ID')
7
key_secret_id = os.environ.get('R3_SECRET_ACCESS_KEY')
8
api_key = os.environ.get('R3_DEVELOPER_API_KEY')
9
10
body = '' #update this with your data if posting with a body
11
host = 'api.remote.it'
12
url_path = '/apv/v27/device/list/all'
13
content_type_header = 'application/json'
14
content_length_header = str(len(body))
15
headers = {
16
'host': host,
17
'content-type': content_type_header,
18
'content-length': content_length_header,
19
'DeveloperKey': api_key
20
}
21
response = requests.get('https://' + host + url_path,
22
auth=HTTPSignatureAuth(algorithm="hmac-sha256",
23
key=b64decode(key_secret_id),
24
key_id=key_id,
25
headers=[
26
'(request-target)', 'host',
27
'date', 'content-type',
28
'content-length'
29
]),
30
headers=headers)
31
32
if response.status_code == 200:
33
print(response.text)
34
else:
35
print(response.status_code)
36
print(response.text)
Copied!
You can reference different standard implementations of the signature in different languages from w3c-ccg https://github.com/w3c-ccg/http-signatures/issues/1
Last modified 13d ago