AUTHENTICATION

Verifying User Identity

Authentication is a method of providing application and network security by permitting only users with validated identities (authenticated users) access to resources. Voodoo allows three types of authentication:

  1. Basic Authentication. Voodoo Robotics disables this option by default.  This method is completely insecure over HTTP, but some users prefer to use it over HTTPS. Voodoo Robotics will enable Basic Authorization on a customer’s Big Block Server by request only.
  2. Session-based Authentication. Secure and conveniently simple, this method requires the use of a session cookie and adds CSRF token and Referer fields to the header.
  3. OAuth2. An industry-standard protocol for authentication supported by libraries in many programming languages. Voodoo Robotics shows two examples of using OAuth2: with and without the oauthlib library in Python.

Basic Authentication

We discourage this method

By default, our servers do not allow Basic Authentication.

Using Basic Authentication over HTTP is completely insecure, nevertheless used extensively in industry.  Some of our customers feel that this method of authentication is perfectly fine as long as it is limited to HTTPS connections.  Since our servers generally use HTTPS, Voodoo can enable Basic Authentication on a customer’s Big Block server by request only.

The advantage of using this authentication method is that individual POST messages can be made without the need to maintain any state information between requests.  There is no login step required.

import requests

baseURL = "https://www.voodoodevices.com/" # or your Big Block server
apiURL = baseURL+"api/"
deviceEndpoint = apiURL+"device/"
deviceID = "CCCCCC:DDDDDD"
username = "yourusername"
password = "yourpassword"

session = requests.Session()

session.post(
    deviceEndpoint+deviceID+"/",
    auth=(username,password),
    json={
        'command':'flash',
        'line1':'Hello',
        'line2':'There1',
        'line3':'\\ictop',
        'line4':'\\qrmyspecialcode',
    }
)

Session-based Authentication

Adds CSRF Token and Referer to the header

Session-based Authentication is secure and conveniently simple.  When a client logs into a server, the client obtains both a session ID (in the cookie header) and a CSRF token.

The example shown here is somewhat deceptive because Python’s ‘requests’ library hides an important detail:  The ‘Session’ object in Python accepts, stores, and provides the session cookie in the header on subsequent requests automatically.

Note that the Big Block server also requires a ‘referer’ header in any POST request. (GET requests can be made without these header additions.)

import requests
import json

baseURL = "https://www.voodoodevices.com/" # or your Big Block server
apiURL = baseURL+"api/"
deviceEndpoint = apiURL+"device/"
deviceID = "CCCCCC:DDDDDD"
username = "yourusername"
password = "yourpassword"

session = requests.Session()

x = session.post(
    apiURL+"user/login/",
    json={
        'username': username,
        'password':password
    }
)

z = json.loads(x.text)

session.post(
    deviceEndpoint+deviceID+"/",
    headers = {
        'referer': baseURL,
        'x-csrf-token': z['token'],
    },
    json={
        'command':'flash',
        'line1':'Hello',
        'line2':'There1',
        'line3':'\\ictop',
        'line4':'\\qrmyspecialcode',
    }
)

OAUTH2 without importing ‘oauthlib’

Shows the details of the the authentication request.

This example shows exactly how a client can obtain a ‘Bearer Token’ from a Big Block server and then subsequently use that token for POST access.

Notice that the first POST request to obtain the token passes a dictionary in the data parameter.  Big Block expects these parameters to be encoded, not as JSON, but as an ‘x-www-form-urlencoded’ style encoded list.

The server responds to the first request with a result like:

{
    "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "expires_in": 36000, 
    "token_type": "Bearer", 
    "scope": "read write", 
    "refresh_token": "yyyyyyyyyyyyyyyyyyyyyyyy"
}

The access token can then be used for subsequent requests. The refresh_token can be used to update the access token after expiry.

import requests
import json

baseURL = "https://www.voodoodevices.com/" # or your Big Block server
apiURL = baseURL+"api/"
tokenURL = baseURL+"oauth2/token/"
deviceEndpoint = apiURL+"device/"
deviceID = "CCCCCC:DDDDDD"
username = "yourusername"
password = "yourpassword"
client_id = "xxxxget_this_client_id_from_usxxxxxxx"

session = requests.Session()

x = session.post(
    tokenURL,
    data = {  # note the use of the parameter name 'data' here
        'grant_type':'password',
        'username': username,
        'password':password,
        'client_id':client_id,
    }
)

z = json.loads(x.text)

session.post(
    deviceEndpoint+deviceID+"/",
    headers = {
        'Authorization': z['token_type'] + " " + z['access_token'],
    },
    json = { # note the use of the parameter name 'json' here
        'command':'flash',
        'line1':'Hello',
        'line2':'There1',
        'line3':'\\ictop',
        'line4':'\\qrmyspecialcode',
    }
)

OAUTH2 with automatic token refresh

‘oauthlib’ and ‘requests_oauthlib’ make your life easy.

Python offers two important libraries that can make a programmer’s life much simpler.  Consider this example that uses the ‘requests_oauthlib’ and ‘oauthlib’ libraries.

While some of the underlying details are hidden by the objects created, the utility is immediately obvious:  You never have to worry about token renewal/refresh!

This is definitely an authentication style worth considering if your client software is written in Python.

Other languages support OAUTH2 using similar plugin libraries.  Please check with us if you’d like recommendations for authentication options in your programming language of choice.

from oauthlib.oauth2 import LegacyApplicationClient
from requests_oauthlib import OAuth2Session

baseURL = "https://www.voodoodevices.com/" # or your Big Block server
apiURL = baseURL+"api/"
tokenURL = baseURL+"oauth2/token/"
deviceEndpoint = apiURL+"device/"
deviceID = "CCCCCC:DDDDDD"
username = "yourusername"
password = "yourpassword"
client_id = "xxxxget_this_client_id_from_usxxxxxxx"

session = OAuth2Session(
    client=LegacyApplicationClient(client_id=client_id),
    auto_refresh_url=tokenURL,
    auto_refresh_kwargs={
        "client_id": client_id,
        "username": username,
        "password": password,
    },
    token_updater=lambda t: t,
)
session.fetch_token(
    token_url=tokenURL,
    username=username,
    password=password,
    include_client_id=True,
)

session.post(
    deviceEndpoint+deviceID+"/",
    json={
        'command':'flash',
        'line1':'Hello',
        'line2':'There1',
        'line3':'\\ictop',
        'line4':'\\qrmyspecialcode',
    },
)

OAUTH2 using Postman

Here are some settings that might be useful:

© Copyright 2022 Voodoo Robotics. All Rights Reserved. Patents Pending. Voodoo Robotics, Voodoo Devices, Big Block Server, and Turbo names and logos are all trademarks of Voodoo Robotics.