Fhir Epic 沙箱:使用 JWT 获取后端服务的访问令牌

Fhir Epic Sandbox : Using a JWT to Obtain an Access Token for a Backend Service

我正在尝试将 https://fhir.epic.com/ 中的沙箱用于后端服务。

我正在学习本教程:https://fhir.epic.com/Documentation?docId=oauth2&section=BackendOAuth2Guide

但我无法 POST 到端点的 JWT 来获取访问令牌。我应该向这个 URL 发送一个 POST 请求:https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token.

我正在使用 python,这是我目前的代码:

import json
import requests
from datetime import datetime, timedelta, timezone
from requests.structures import CaseInsensitiveDict
from jwt import (
    JWT,
    jwk_from_dict,
    jwk_from_pem,
)
from jwt.utils import get_int_from_datetime


def main():
    instance = JWT()
    message = {
        # Client ID for non-production
        'iss': '990573e-13e3-143b-8b03-4fbb577b660',
        'sub': '990573e-13e3-143b-8b03-4fbb577b660',
        'aud': 'https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token',
        'jti': 'f9eaafba-2e49-11ea-8880-5ce0c5aee679',
        'iat': get_int_from_datetime(datetime.now(timezone.utc)),
        'exp': get_int_from_datetime(datetime.now(timezone.utc) + timedelta(hours=1)),
    }

    # Load a RSA key from a PEM file.
    with open('/home/user/ssl/privatekey.pem', 'rb') as fh:
        signing_key = jwk_from_pem(fh.read())

    compact_jws = instance.encode(message, signing_key, alg='RS384')
    print(compact_jws)

    headers = CaseInsensitiveDict()
    headers['Content-Type'] = 'application/x-www-form-urlencoded'

    data = {
      'grant_type': 'client_credentials',
      'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
      'client_assertion': compact_jws
    }
    
    x = requests.post('https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token', headers=headers, data=data)
    print(x.text)

但我总是收到 400 错误:

{
  "error": "invalid_client",
  "error_description": null
}

URL 正确吗?我怎样才能获得访问令牌来玩沙盒?

'exp': get_int_from_datetime(datetime.now(timezone.utc) + timedelta(hours=1)),

乍一看,这似乎是您的问题。 Epic要求exp未来不超过5分钟。

除此之外还有几条建议:

  1. 使用 jwt.io
  2. 提供的库
  3. Jwt.io 还有一个调试器,您可以在其中粘贴 JWT 以验证它是否有效