To test API endpoints that sit behind Auth0 authorisation you can use your Auth0 "Test Application" to generate auth tokens. This will enable you to run integration tests on your endpoints without having to make use of Auth0's /authorize
endpoint (which responds with a 302 redirect, making it tricky to test with).
To get started, you first need to ensure that you have the appropriate permissions and grant types setup for your API. You can do this by navigating to your "Test Application" in the Auth0 dashboard. Auth0 automatically creates a "Test Application" for regular Auth0 API applications. Once the appropriate test application is selected, click on the "API" tab, make sure the correct application is switched on. Next to that switch is a dropdown arrow, when clicking on it, you can then select the appropriate permissions needed. Save your changes.
Once that is done, on the "Settings" tab, click on the "Show Advanced Settings" at the bottom of the page, click on "Grant Types" and then select "Client Credentials" (You can leave the others unselected). Save your changes.
In order to make API calls from Python, I use the requests library.
Install as a dependency via: pip install requests
or update your requirements.txt
file and install as needed.
Keep in mind that with the "client credentials" auth flow, you make use of your Auth0 client secret. This value must not be made public. As such, you should be passing this value in from environment variables into your app config so that they are not exposed at any point.
The Auth0 domain, client ID and audience are values that are made visible using Auth0's front-end authentication flows, so these are not critical to keep secret. However, in the example below, I have kept those in environment variables too for consistency. Also keep in mind that the client id for your "Test Application" will be different from the Client ID for your "parent application".
You can setup your request in Pytest as follows:
import json
import os
import requests
def get_auth0_access_token():
domain = os.environ.get("AUTH0_DOMAIN")
payload = {
"client_id": os.environ.get("AUTH0_CLIENT_TEST_ID"),
"client_secret": os.environ.get("AUTH0_SECRET"),
"audience": os.environ.get("AUTH0_AUDIENCE"),
"grant_type": "client_credentials",
}
headers = {"content-type": "application/json"}
res = requests.post(
f"https://{domain}/oauth/token", data=json.dumps(payload), headers=headers
)
access_token = res.json()["access_token"]
return access_token
You now have a function that will get you an access_token when needed in your tests. For example:
def test_sanity_check_success(test_app):
access_token = get_auth0_access_token()
client = test_app.test_client()
res = client.get(
"/sanity",
headers={"Authorization": f"Bearer {access_token}"},
content_type="application/json",
)
data = json.loads(res.data.decode())
assert res.status_code == 200
assert res.content_type == "application/json"
assert "world!" in data["hello"]
Please Note: It is imperative that you keep your Auth0 Client Secret secret. As such, the above flow is not suitable for front-end only, SPA auth flows!
Primarily, the "client credential" flow is for machine-to-machine authorisation - which unit/integration testing is. As such, do not use this in your SPA, or add this API call into your Postman collection with client secret populated.