【问题标题】:Fhir Epic Sandbox : Using a JWT to Obtain an Access Token for a Backend ServiceFhir Epic Sandbox:使用 JWT 获取后端服务的访问令牌
【发布时间】:2023-03-30 09:20:01
【问题描述】:

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

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

  • 我已经注册了一个新应用,
  • 创建了一个 JWT(使用 SSL 密钥)
  • https://jwt.io/ 上测试了 JWT:工作正常!

但我无法将 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
}

网址是否正确?如何获得访问令牌来玩沙盒?

【问题讨论】:

    标签: python python-requests jwt hl7-fhir smart-on-fhir


    【解决方案1】:
    'exp': get_int_from_datetime(datetime.now(timezone.utc) + timedelta(hours=1)),
    

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

    几条建议,除此之外:

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

    【讨论】:

    • 我已经使用了来自 jwt.io 的库和调试器。问题确实是exp 中定义的时间!谢谢
    • 我们还要求每个请求都有一个唯一的 JTI。如果您在上面的代码中使用硬编码的 JTI,第一个请求可能会起作用,但具有相同 JTI 的后续请求将失败。您可以每次生成一个新的 GUID 并将其设置为 JTI。
    • @Cooper 确实,我现在每次调用我的函数时都会生成一个随机 ID
    • @ExceptionAl,我遇到了与原始发帖人相同的问题。我验证了我的令牌,一切似乎都井井有条(包括“exp”时间戳)。查看我的应用程序,它说它处于“草稿”状态。要完成这项工作,还需要做些什么吗?
    • @ChrisJ.Karr 很难说没有看到一些代码/示例,但是处于草稿状态的应用程序应该不是问题,只要您将其标记为准备好沙盒。我见过的关键事情让人们失望:“exp”太远了,JWT 没有用私钥正确签名,“jti”不是唯一的(在“exp”的窗口内)。
    猜你喜欢
    • 2019-12-21
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 2022-10-15
    • 2020-08-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多