Skip to main content

Set up a JWKS Signing Key

eCW requires that you have a JWKS server in order to sign and authenticate your requests. Below is an example of how this can be achieved.

PREREQUISITE: Generate an RSA384 PEM format public/private key pair

Any method can be used to generate the public/private key pair, below is an example using OpenSSL

Generate the private key:

openssl genpkey \   
-algorithm RSA \
-pkeyopt rsa_keygen_bits:3072 \
-out rsa384-private.pem

Generate the public key from the private key:

openssl pkey -in rsa384-private.pem -pubout -out rsa384-public.pem   

STEP 1: Create a JWKS key using your public key

There are a few methods to generate a JWKS key from the private key. The method below uses pre built Python libraries to generate the JWKS:

import json   
import base64
import sys
import hashlib
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

def generate_kid(pem_key: str) -> str:
"""Generate a 16-character key ID (kid) from SHA-256 hash of the PEM key."""
return hashlib.sha256(pem_key.encode()).hexdigest()[:16]

def b64url_encode(data: bytes) -> str:
"""Base64url encode without padding."""
return base64.urlsafe_b64encode(data).decode('utf-8').rstrip("=")

def generate_jwk_from_pem(pem_key: str, alg: str = "RS384") -> dict:
"""Generate a JWK dict from a PEM-encoded RSA public key."""
public_key = serialization.load_pem_public_key(pem_key.encode())

if not isinstance(public_key, rsa.RSAPublicKey):
raise ValueError("Provided key is not an RSA public key")

numbers = public_key.public_numbers()

# Do NOT add leading 0x00 - jwt.io can't handle it
n_bytes = numbers.n.to_bytes((numbers.n.bit_length() + 7) // 8, byteorder='big')
e_bytes = numbers.e.to_bytes((numbers.e.bit_length() + 7) // 8, byteorder='big')

jwk = {
"kty": "RSA",
"alg": alg,
"n": b64url_encode(n_bytes),
"e": b64url_encode(e_bytes),
"key_ops": ["verify"],
"ext": True,
"kid": generate_kid(pem_key)
}

return jwk

if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python generate_jwk.py <public_key.pem>")
sys.exit(1)

# Load PEM public key
with open(sys.argv[1], "r") as f:
pem_key = f.read()

# Generate JWK and wrap in a JWKS object if needed
jwk = generate_jwk_from_pem(pem_key)
print(json.dumps(jwk, indent=4))

STEP 2: Host the JWKS key on an HTTPS endpoint

Step 2 is to host the JWKS key on an HTTPS endpoint that responds with the JWKS key.

IMPORTANT: The endpoint URL must not be in the form of IP:PORT

Below is an example of what the response should look like when a request is made to the endpoint:

STEP 3: Contact eCW support to whitelist the JWKS endpoint.

After inputting your endpoint information into your eCW app, you must contact eCW to request that the endpoint is added to the whitelist.