A subset of RFC 7519 for working with JWTs minted by Okta API Access Management.
Project description
oktajwt
This is a simple JWT package built to work specifically with Okta's API Access Management product (API AM). It was inspried in part by jpadilla's PyJWT package. This is not meant to be a full implementation of RFC 7519, but rather a subset of JWT operations specific to working with Okta.
Requirements
- Python >= 3.7
Installing
Install with pip:
pip install oktajwt
Usage
This package is very simple, there is a single function: verify()
.
from oktajwt import *
issuer = "your OAuth issuer"
audience = "expected audience"
jwt = "your base64 encoded JWT, pulled out of the HTTP Authorization header bearer token"
jwtVerifier = JwtVerifier(issuer, audience)
# validate the token and get claims as a JSON dict
claims = jwtVerifier.verify(jwt)
print("iss {0}".format(claims["iss"]))
print("aud {0}".format(claims["aud"]))
print("sub {0}".format(claims["sub"]))
print("exp {0}".format(claims["exp"]))
This module also has a basic command line interface just as an example:
usage:
Decodes and verifies JWTs from an Okta authorization server.
oktajwt [options] <JWT>
positional arguments:
JWT The base64 encoded JWT to decode and verify
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
--verbosity {0,1,2} increase output verbosity
-i ISSUER, --issuer ISSUER
The expected issuer of the token
-a AUDIENCE, --audience AUDIENCE
The expected audience of the token
--cache CACHE The JWKS caching method to use: file or S3
-b BUCKET, --bucket BUCKET
The S3 bucket to cache to. REQUIRED if --cache=S3
--claims Show verified claims in addition to validating the JWT
However, it's much more likely that this package will be used inside something like Flask API server, so the usage would look something more like this.
import json
import request
from oktajwt import *
def get_access_token():
access_token = None
authorization_header = request.headers.get("authorization")
print("Authorization header {0}".format(authorization_header))
if authorization_header == None:
abort(401)
else:
header = "Bearer"
bearer, access_token = authorization_header.split(" ")
if bearer != header:
# malformed header
abort(401)
return access_token
@app.route("/api/v1/token_test", methods=["GET"])
def token_test():
""" a simple route to show token validation """
logger.debug("token_test()")
access_token = get_access_token()
issuer = os.getenv("ISSUER")
audience = os.getenv("AUDIENCE")
cache_method = os.getenv("CACHE_METHOD")
# if using S3 caching
s3_bucket = os.getenv("S3_BUCKET")
try:
jwtVerifier = JwtVerifier(issuer, audience, cache=cache_method, bucket=s3_bucket)
claims = jwtVerifier.verify(access_token)
return jsonify(claims)
except (ExpiredTokenError, InvalidSignatureError, KeyNotFoundError,
InvalidKeyError, Exception) as e:
# something is wrong with the token
# expired, bad signature, etc.
logger.debug("Exception in token_test(): {0}".format(e))
abort(401)
If you're interested, I have a super basic Flask API server that fronts a subset of the Okta APIs (users, groups, factors) that uses this package as an example.
Okta Configuration
NOTE: this package will NOT work with the "stock" organization authorization server as access tokens minted by that server are opaque and no public key is published.
Okta Org You need to have an Okta org with API Access management available. You can get a free developer account at developer.okta.com. Developer tenants will have API Access Management available.
"How can I tell if I have API Access Management enabled or not?" It's actually quite easy. Copy this link and replace the subdomain with yours (a free developer tenant subdomain will look like dev-123456).
https://<YOUR_SUBDOMAIN>.okta.com/oauth2/default/.well-known/oauth-authorization-server
Paste the link with your subdomain in your browser and if you see this:
{
"errorCode": "E0000015",
"errorSummary": "You do not have permission to access the feature you are requesting",
"errorLink": "E0000015",
"errorId": "oaeNmCVqapuSJWf017UlTMjbg",
"errorCauses": []
}
You don't have API Access Management enabled in your org. Go get a free developer account. Developer tenants will have API Access Management available.
Create an OIDC Application Create a new OIDC application in Okta. This is where you'll get the client ID and client secret values. If you create an app that uses PKCE, a client secret value is not necessary and will not be generated.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file OktaJWT-0.4.0.tar.gz
.
File metadata
- Download URL: OktaJWT-0.4.0.tar.gz
- Upload date:
- Size: 22.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.3.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.7.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e0b1508ed98b107bc3407ad0276588f343092e49d9c5bc1f23c09ad683c24065 |
|
MD5 | 2a85446afab108e73d8e3b330bd628cd |
|
BLAKE2b-256 | da9b2e31ad4980a7d8689d7a22ccfbe081255429b3ae4f6642403a9f3a6b48d5 |
File details
Details for the file OktaJWT-0.4.0-py2.py3-none-any.whl
.
File metadata
- Download URL: OktaJWT-0.4.0-py2.py3-none-any.whl
- Upload date:
- Size: 24.8 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.3.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.7.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 93dd00809fc937aac8b5b827ccb8e448bdb5dfef3780820e55e187c99c04ec9d |
|
MD5 | 8149691ca44ae1efd8d7de68fe2a4d95 |
|
BLAKE2b-256 | a761cab66e60cc834a4c964453f7eabdf832973b7d1b3e678ad611693c87d270 |