Generate a JSON Web Token for Okta Access Gateway APIs
Last Updated:
Overview
Okta Access Gateway (OAG) Application Programming Interfaces (APIs) require a JSON Web Token (JWT) in requests. Generate a JWT using bash or Python scripts to authenticate API requests. Developers can use Java or other programming languages to generate a JWT using these examples.
Applies To
- Okta Identity Engine (OIE)
- Okta Classic Engine
- Okta Access Gateway (OAG) Application Programming Interface (API)
Solution
Review the prerequisites for generating a JSON Web Token.
Meet the following prerequisites before generating a JSON Web Token (JWT):
- Generate the client ID and store the private key in a file using Privacy Enhanced Mail (PEM) format.
- Obtain the details of all scopes linked to the client ID.
- Obtain the OAG domain (Hostname) from the Admin UI by navigating to Settings and locating the Access Gateway section.
How is a JSON Web Token generated using a bash script?
Run the following bash script locally to generate a JWT. Add the client ID to CLIENT_ID, https://<oag_hostname> to AUD, the path of the PEM file to PRIVATE_KEY_PATH, and all the scopes of the client ID to SCOPES using a space as a delimiter. When adding the private key to the file, include the header and footer, and remove <Paste api private key here>.
-----BEGIN PRIVATE KEY-----
<Paste api private key here>
-----END PRIVATE KEY-----
Execute the following bash script to generate the token.
#!/bin/bash
# Set variables
CLIENT_ID=""
AUD=""
PRIVATE_KEY_PATH=""
SCOPES=""
TOKEN_LIFETIME=300
NOW=$(date +%s)
EXP=$((NOW + TOKEN_LIFETIME))
HEADER='{"alg":"RS256","typ":"JWT"}'
PAYLOAD="{\"iss\":\"$CLIENT_ID\",\"iat\":$NOW,\"exp\":$EXP,\"scope\":\"$SCOPES\",\"aud\":\"$AUD\",\"sub\":\"$CLIENT_ID\"}"
b64url() {
openssl base64 -e -A | tr '+/' '-_' | tr -d '='
}
HEADER_B64=$(echo -n "$HEADER" | b64url)
PAYLOAD_B64=$(echo -n "$PAYLOAD" | b64url)
SIGN_INPUT="${HEADER_B64}.${PAYLOAD_B64}"
SIGNATURE=$(echo -n "$SIGN_INPUT" | openssl dgst -sha256 -sign "$PRIVATE_KEY_PATH" | b64url)
JWT="${SIGN_INPUT}.${SIGNATURE}"
echo "$JWT"
Execute a Python Script to Generate a JSON Web Token
Execute the example Python script on an OAG instance to get the JWT and call the application endpoint. Install the required packages before running the script by executing the following commands.
sudo pip3 install PyJWT
sudo pip3 install requests
Input the private key, client ID, Access Gateway hostname, and all the scopes of the client ID with a space as a delimiter in the following script before executing it.
import jwt
import time
import requests
PRIVATE_KEY = """-----BEGIN PRIVATE KEY-----
<YOUR_PRIVATE_KEY_HERE>
-----END PRIVATE KEY-----"""
CLIENT_ID = "<YOUR_CLIENT_ID_HERE>"
TOKEN_LIFETIME = 300
def generate_jwt(scopes=None):
if scopes is None:
scopes = ["<scopes>"]
now = int(time.time())
payload = {
"iss": CLIENT_ID,
"iat": now,
"exp": now + TOKEN_LIFETIME,
"scope": " ".join(scopes),
"aud": "https://<YOUR_OAG_HOSTNAME_HERE>",
"sub": CLIENT_ID
}
token = jwt.encode(payload, PRIVATE_KEY, algorithm="RS256")
return token
def main():
scopes = [
"okta.oag.app.manage",
]
token = generate_jwt(scopes)
data = {
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"grant_type": "client_credentials",
"client_assertion": token,
"scope": " ".join(scopes)
}
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
}
# fetch oauth token
url = "http://admin.service.spgw:8091/api/v2/oauth/token"
response = requests.post(url, data=data, headers=headers)
print("Token response body:", response.text)
token_data = response.json()
access_token = token_data.get("access_token")
if not access_token:
print("failed to obtain access_token")
return
# call /apps with Bearer token
auth_headers = {
"Authorization": f"Bearer {access_token}",
"X-Request-Domain": "https://<YOUR_OAG_HOSTNAME_HERE>",
}
apps_url = "http://admin.service.spgw:8091/api/v2/apps"
apps_resp = requests.get(apps_url, headers=auth_headers)
print("Apps Request Status Code:", apps_resp.status_code)
print("Apps Response Body:", apps_resp.text)
if __name__ == "__main__":
main()