Reputation: 5856
I'm trying to get an access token from FHIR EPIC using JWT. My code is below. I keep getting this error
Request error: 400
Client Error: Bad Request for url: https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token
I've tried looking at similar questions like Fhir Epic Sandbox : Using a JWT to Obtain an Access Token for a Backend Service. And I havent been able to get anywhere.
The apps that I created on vendor site are more than 3 weeks old.
I checked my JWT token on JWT.io and it seems to be rendering correctly. My expiration time should be around 3 minutes. I generate a new jti every time I run the script.
I tried to follow the OAuth2 documentation the best that I can. I'm hoping someone can lead me to the right direction.
def get_epoch_time():
current_epoch_seconds = int(time.time())
future_epoch_seconds = current_epoch_seconds + 180
return future_epoch_seconds
# function to read key certificate files
def get_key(path):
# open and read the file
with open(path,'rb') as file:
key_content = file.read()
#function to create kid (key identification)
#Key ID and is an identifier for the key used to sign a JWT.
def get_x509_fingerprint(cert_path):
"""
Calculates the SHA1 fingerprint of an X.509 certificate in colon-separated hex format.
"""
with open("../publickey509.pem", 'rb') as f:
cert_data = f.read()
cert_hash = hashlib.sha1(cert_data).digest()
return ':'.join(f'{byte:02x}' for byte in cert_hash)
cert_path = "../publickey509.pem" # Replace with the path to your certificate
fingerprint = get_x509_fingerprint(cert_path)
jti = str(uuid.uuid4())
print(jti, "my jti")
header = {
"alg": "RS384",
"typ": "JWT",
"kid" : fingerprint
}
payload = {
"iss": "${non_production_clientID}",
"sub": "${non_production_clientID}",
"aud": "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token",
"jti": jti,
"exp": get_epoch_time()
}
private_key = get_key("../privatekey.pem")
# create a signature for jwt token
private_signature = jwt.encode(header,payload,private_key)
print(private_signature)
post_body_data = {
"grant-type": "client_credentials",
"client_assertion_type" : "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion" : private_signature
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
try:
auth_response = requests.post(base_auth_url,headers=headers, data = post_body_data)
auth_response.raise_for_status()
data = auth_response.json()
except requests.exceptions.RequestException as e:
print(f"Request error: {e}")
except json.decoder.JSONDecodeError as e:
print(f"JSON decoding error: {e}")
print(f"Response text: {auth_response.text}")
Upvotes: 0
Views: 111