As part of a learning exercise, I am writing an API server app implemented in Python, Flask, et al, along with automated tests using the Python unittest module.

After knocking out some initial functionality, my partner Ryan (who is writing a frontend as a native Android app) and I decided to add authorization of users to control access to the API. We chose the Auth0 service for this.

Testing implies that you are simulating a client. That means you must have a valid and unexpired authorization token issued by Auth0.

At the beginning of developing this I tested manually by using Postman, which is a great tool for constructing and sending requests to APIs. To acquire an Auth0 token I used the curl command to send a request to an Auth0 endpoint that is specific to our account.

However, getting the token requires providing secret Auth0 credentials that are unique to our Auth0 account. You don’t want to include these in code that is committed to a public repo.

As with other kinds of credentials, e.g. database login, I decided to put the Auth0 ones into environment variables, a mechanism which I had already put in place using the Python python-dotenv module. That module uses a .env file placed at the top of the app directory, that contains variable definitions. The file is never committed to a public repo and is only kept in the intended environment.

# Put these definitions into the .env file.
# You get the values from your Auth0 dashboard.
AUTHO_CLIENT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
AUTHO_CLIENT_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"


Following are the contents of get_auth0.token.py, where the first several lines fetch the secret Auth0 values.

Functionget_auth0_access_token() then uses those to construct a request to send to the Auth0 endpoint, extracts the access token from the response, and returns the token. The body of the function is largely copied from Auth0 documentation (which is extensive and very well-written).

# get_auth0_token.py

import http.client
import json
import os
from dotenv import load_dotenv, find_dotenv

# Get the AUTHO_CLIENT_ID and AUTHO_CLIENT_SECRET credentials.
ENV_FILE = find_dotenv()
if ENV_FILE:
    load_dotenv(ENV_FILE)

AUTHO_CLIENT_ID = os.environ['AUTHO_CLIENT_ID']
AUTHO_CLIENT_SECRET = os.environ['AUTHO_CLIENT_SECRET']


def get_auth0_access_token():
    """Retrieves an access token using the Auth0 Client Credentials Flow
    which is documented at https://auth0.com/docs/flows/client-credentials-flow
    and at https://auth0.com/docs/api/authentication#client-credentials-flow
    """
    conn = http.client.HTTPSConnection("espresso-dev.us.auth0.com")

    request_items = { "client_id": AUTHO_CLIENT_ID, \
                      "client_secret": AUTHO_CLIENT_SECRET, \
                      "audience": "api.espresso.routinew.com", \
                      "grant_type": "client_credentials"
                    }

    payload = json.dumps(request_items)
    headers = {'content-type': "application/json"}

    conn.request("POST", "/oauth/token", payload, headers)

    res = conn.getresponse()
    data_json = res.read()
    data_dict = json.loads(data_json)
    access_token = data_dict.get('access_token', None)

    return access_token


if __name__ == '__main__':
    access_token = get_auth0_access_token()
    print(access_token)


Finally, the test code calls the above function. Test cases use the returned token to authorize themselves as part of their calls to the API server. For example,

import unittest
import get_auth0_token

# Get the Auth0 access token just once to avoid repeated hits to the Auth0 API
access_token = get_auth0_token.get_auth0_access_token()
auth_header = {'authorization': 'Bearer ' + access_token}


class RestaurantsTestCases(unittest.TestCase):

    def test_get_restaurants(self):
        resp = self.test_client.get('/api/v1/restaurants', headers=auth_header)
        self.assertEqual(resp.status_code, 200)


Full code on GitHub at https://github.com/tz-earl/Espresso