A JSON Web Token (JWT) will be required in requests to OAG APIs. This article provides examples to generate the same using bash and Python. Java or other languages can be used to generate the JWT using the following examples.
- Okta Access Gateway API
Prerequisites
- Ensure that the client ID is generated and the private key is stored in a file using PEM format.
- Ensure the details of all scopes linked to the client ID are available.
- Ensure the details of the OAG domain(Hostname). It can be found on the Admin UI > Settings page under the Access Gateway section.
Bash
Below is a bash script that can be run locally to generate a JWT. Add details for CLIENT_ID with client ID, AUD with https://<oag_hostname>, PRIVATE_KEY_PATH with the path of the PEM file and SCOPES with all the scopes of the client ID, with a space as a delimiter. When adding the private key to the file, add the following header and footer. Remove <Paste api private key here>.
-----BEGIN PRIVATE KEY-----
<Paste api private key here>
-----END PRIVATE KEY-----
#!/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"
Python
The example Python script can be executed on an OAG instance to get the JWT. It also includes an example call to the app's endpoint. The following packages must be installed before running the script.
sudo pip3 install PyJWT
sudo pip3 install requests
Helper Script
Input the private key, client ID, Access Gateway hostname, and all the scopes of client ID with a space as a delimiter in the script below before executing:
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()