Skip to main content

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.

Metadata

Release files for OktaJWT 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for OktaJWT 0.4.0
File Size Uploaded Provenance
OktaJWT-0.4.0.tar.gz 22.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for OktaJWT 0.4.0
File Interpreter ABI Platform
OktaJWT-0.4.0-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 47.6 kB

Release files / OktaJWT-0.4.0.tar.gz

Download URL OktaJWT-0.4.0.tar.gz
Size 22.8 kB
Tags Source
SHA-256 checksum
How to use checksums
e0b1508ed98b107bc3407ad0276588f343092e49d9c5bc1f23c09ad683c24065
BLAKE2b-256 checksum
How to use checksums
da9b2e31ad4980a7d8689d7a22ccfbe081255429b3ae4f6642403a9f3a6b48d5
Upload date
Uploaded using Trusted Publishing?
What is 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

Release files / OktaJWT-0.4.0-py2.py3-none-any.whl

Download URL OktaJWT-0.4.0-py2.py3-none-any.whl
Size 24.8 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
93dd00809fc937aac8b5b827ccb8e448bdb5dfef3780820e55e187c99c04ec9d
BLAKE2b-256 checksum
How to use checksums
a761cab66e60cc834a4c964453f7eabdf832973b7d1b3e678ad611693c87d270
Upload date
Uploaded using Trusted Publishing?
What is 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

Security for OktaJWT 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page