# Generating SAS Tokens

## Prerequisites

To use Shared Access Signature tokens as authorization method, create a new HTTP device connector and select the device authentication **Shared Access Signature.**

<figure><img src="https://2165942204-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MMKXTFIN5ZlLOjBlfC4%2Fuploads%2FjmO2vnZt7Kw4RQYVjsik%2Fimage.png?alt=media&#x26;token=c48aa8f4-810f-46dc-b674-06fe506c904f" alt=""><figcaption></figcaption></figure>

Setup a new device with the data flow and copy the deviceId, the primary signing key and use it in the following code example to generate a token.

## Generating tokens

{% tabs %}
{% tab title="JavaScript" %}

```javascript
import crypto from "crypto";
import axios from "axios";

const generateSasToken = (
  signingKey,
  resourceUri,
  expiryInSeconds,
  deviceConnectorIdAudience,
  deviceIdAudience
) => {
  let query = `deviceConnectorIdAudience=${deviceConnectorIdAudience}\n`;
  if (deviceIdAudience !== null) {
    query += `deviceIdAudience=${deviceIdAudience}\n`;
  }
  query += `expiry=${expiryInSeconds}`;
  const encodedQuery = encodeURIComponent(query);

  let hmac = crypto.createHmac("sha256", Buffer.from(signingKey, "base64url"));
  hmac.update(encodedQuery);

  let signature = encodeURIComponent(hmac.digest("base64"));
  let token = `sig=${signature}&exp=${expiryInSeconds}&aud=${encodeURIComponent(
    resourceUri
  )}`;
  return Buffer.from(token).toString("base64");
};

// generate the token
const baseUrl = "https://data-gateway.akenza.io"
const expiry = Math.ceil(Date.now() / 1000 + 60 * 60 * 24); // 1d
const signingKey = "<primaryOrSecondarySigningKey>";
const deviceConnectorId = "<yourDeviceConnectorId>";
const deviceId = "<yourPhysicalDEviceId>";
const resourceUri = `https://akenza.io/device-connectors/${deviceConnectorId}/devices/${deviceId}`;
const token = generateSasToken(
    signingKey,
    resourceUri,
    expiry,
    deviceConnectorId,
    deviceId
  );
  
// send the uplink
const url = `${baseUrl}/v3/capture?deviceId=${deviceId}&topic=default`;
const options = {
    headers: {
      "Content-Type": "application/json",
      "x-access-signature": token,
    },
  };
const body = { param1: "value" };
const response = await axios.post(url, body, options);
```

{% endtab %}

{% tab title="Python" %}

```python
from base64 import b64encode, urlsafe_b64decode
from hashlib import sha256
from time import time
from urllib import parse
from hmac import HMAC
import os
import requests


def generate_sas_token(signing_key, resource_uri, expiry_in_seconds, device_connector_id, device_id):
    query = f"deviceConnectorIdAudience={device_connector_id}\n"
    if device_id:
        query += f"deviceIdAudience={device_id}\n"
    query += f"expiry={expiry_in_seconds}"
    query = parse.quote_plus(query).encode('utf-8')

    padded_signing_key = signing_key
    missing_padding = len(signing_key) % 4
    if missing_padding:
        padded_signing_key += '=' * (4 - missing_padding)
    padded_signing_key = urlsafe_b64decode(padded_signing_key)

    signature = b64encode(HMAC(padded_signing_key, query, sha256).digest()).decode("utf-8")
    encoded_signature = parse.quote_plus(signature.encode('utf-8'))
    token = f"sig={encoded_signature}&exp={expiry_in_seconds}&aud={parse.quote_plus(resource_uri)}"

    return b64encode(token.encode('utf-8')).decode("utf-8")


if __name__ == "__main__":
    base_url = "https://data-gateway.akenza.io"
    signing_key = "<primaryOrSecondarySigningKey>"
    device_id = "<yourPhysicalDEviceId>"
    device_connector_id = "<yourDeviceConnectorId>"
    expiry = round(time() + 60 * 60 * 24)
    resource_uri = f"https://akenza.io/device-connectors/{device_connector_id}/devices/{device_id}"
    token = generate_sas_token(signing_key, resource_uri, expiry, device_connector_id, device_id)

    headers = {
        'Content-Type': 'application/json',
        "x-access-signature": token
    }

    body = {
        "param1": "value"
    }

    response = requests.request("POST", f"{base_url}/v3/capture", headers=headers, json=body, timeout=10)
    response.raise_for_status()

    print("uplink sent")
```

{% endtab %}

{% tab title="Java" %}

```java
/**
 * Generates a SAS signature
 *
 * @param query the query to hash
 * @param key   the recommended key length is 32 bytes (256 bits)
 * @return the shared access signature
 */
public static String generateSignature(String query, String key) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
    String stringToSign = URLEncoder.encode(query, StandardCharsets.UTF_8);

    byte[] decodedKey = Base64.getUrlDecoder().decode(key);

    Mac sha256HMAC = Mac.getInstance("HmacSHA256");
    SecretKeySpec secretKey = new SecretKeySpec(decodedKey, "HmacSHA256");
    sha256HMAC.init(secretKey);
    Base64.Encoder encoder = Base64.getEncoder();

    String signature = new String(encoder.encode(
        sha256HMAC.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8))), StandardCharsets.UTF_8);

    return URLEncoder.encode(signature, StandardCharsets.UTF_8);
}
```

{% endtab %}
{% endtabs %}
