Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth2 access token is not passed to client.client_credentials.get_token #151

Open
aumi9292 opened this issue Nov 7, 2022 · 0 comments
Open

Comments

@aumi9292
Copy link

aumi9292 commented Nov 7, 2022

I'm creating a backend systems application on Epic's App Marketplace. I checked the box "Use Oauth 2.0," am using R4 FHIR version, and I uploaded a public key to Epic's app marketplace. I'm using 'https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4' as the BASE_URL when instantiating a FHIR::Client instance. Per Epic's documentation for a Backend Systems app, a POST request needs to be made to the token endpoint to obtain an access token. This POST request needs to look like this example shown in Epic's documentation

POST <TOKEN_URL> HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkNDUwNDljMy0zNDQxLTQwZWYtYWI0ZC1iOWNkODZhMTcyMjUiLCJzdWIiOiJkNDUwNDljMy0zNDQxLTQwZWYtYWI0ZC1iOWNkODZhMTcyMjUiLCJhdWQiOiJodHRwczovL2FwcG1hcmtldC5lcGljLmNvbS9pbnRlcmNvbm5lY3QtYW1jdXJwcmQtb2F1dGgvb2F1dGgyL3Rva2VuIiwianRpIjoiZjllYWFmYmEtMmU0OS0xMWVhLTg4ODAtNWNlMGM1YWVlNjc5IiwiZXhwIjoxNTgzNTI0NDAyLCJuYmYiOjE1ODM1MjQxMDIsImlhdCI6MTU4MzUyNDEwMn0.cM3o-9LzamiNP0luN1slylY3W0mo8YwYx4Bqj2uLPf_IhEUvt8Y3BiYBGlfnU_RgWaMkij9TCuhCRk7A8N6kVVxpBknd0JscKyTKeIrFqPbYk0gkWbpOjsxtkWnuKS0bdkjlRPXsaLMJ4uNfSAcViuuZ-wbLxnWX4AEZzzGXj8lt3uNKfOx7i3f-3wXZ-Mwe0qQq3pUjex7LpQA7qPBoQ2dJFXn491DBTW43QXsAebeKzWpKY94q5p2CU8qAJRBVrigbXc_C9Bsy_rknI-SGjH8X7BsIzMLLNFL5B1wIHhrkVFaZ83iLnJQQxaiFtsJUgtyaR02eSKhWdH3t40liMQ

This POST request needs to have a body that includes grant_type, client_credentials, client_assertion_type, and client_assertion. Here, client_assertion needs to be an encoded JWT token that looks like

      def payload
        {
          'iss': NON_PROD_CLIENT_ID,
          'sub': NON_PROD_CLIENT_ID,
          'aud': AUD,
          'iat': Time.zone.now.to_i,
          'exp': Time.zone.now.to_i + 4 * 60,
          'jti': SecureRandom.hex(6),
          'kid': PUBLIC_KEY_FINGERPRINT
        }
      end

      def assertion
        @token ||= JWT.encode payload, rsa_private, 'RS384', {typ: 'JWT', alg: 'RS384', kid: PUBLIC_KEY_FINGERPRINT}
      end

In FHIR::Client#set_oauth2_auth, OAuth2::Client#get_token is called with no arguments.

@client = client.client_credentials.get_token

OAuth2::Client#get_token accepts params as the first argument. In the method, it uses params to make the body of the POST request. If no params are passed, this request to get the access token will not be successful.

def get_token(params, access_token_opts = {}, access_token_class = AccessToken) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
      params = Authenticator.new(id, secret, options[:auth_scheme]).apply(params)
      opts = {:raise_errors => options[:raise_errors], :parse => params.delete(:parse)}
      headers = params.delete(:headers) || {}
      if options[:token_method] == :post
        opts[:body] = params
        opts[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
      else
...

Can FHIR::Client#set_oauth2_auth be re-worked to accept a params argument so that I can pass the necessary parameters to the make the initial POST request to get the needed access token? Please let me know if you could use more information from me or if I'm misunderstanding the implementation.

In case it's useful, this is the terminal output when I try to run the example oauth2 code from GH

I, [2022-11-07T15:25:21.450261 #45018]  INFO -- : Initializing client with https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4
I, [2022-11-07T15:25:21.450680 #45018]  INFO -- : Configuring the client to use no authentication.
I, [2022-11-07T15:25:21.451568 #45018]  INFO -- : GETTING: https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4/metadata
D, [2022-11-07T15:25:21.864158 #45018] DEBUG -- : GET - Request: {"method":"get","headers":{"User-Agent":"Ruby FHIR Client","Accept-Charset":"utf-8","Accept":"application/fhir+json"},"url":"https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4/metadata","password":null,"user":null,"uri":"https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4/metadata","cookie_jar":[],"payload":null,"block_response":null,"raw_response":false,"stream_log_percent":10,"ssl_opts":{"verify_ssl":1,"cert_store":{"verify_callback":null,"error":null,"error_string":null,"chain":null,"time":null}},"log":null,"max_redirects":10,"processed_headers":{"Accept":"application/fhir+json","User-Agent":"Ruby FHIR Client","Accept-Charset":"utf-8"},"processed_headers_lowercase":{"accept":"application/fhir+json","user-agent":"Ruby FHIR Client","accept-charset":"utf-8"},"args":{"method":"get","url":"https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4/metadata","headers":{"User-Agent":"Ruby FHIR Client","Accept-Charset":"utf-8","Accept":"application/fhir+json"}},"before_execution_proc":null}, Response: [too large]
D, [2022-11-07T15:25:21.865255 #45018] DEBUG -- : Parsing response with {klass: FHIR::CapabilityStatement, format: application/fhir+json, code: 200}.
I, [2022-11-07T15:25:21.890849 #45018]  INFO -- : Configuring the client to use OpenID Connect OAuth2 authentication.
OAuth2::Error: invalid_client: 
{
  "error": "invalid_client",
  "error_description": null
}
from /Users/austinmiller/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/oauth2-1.4.4/lib/oauth2/client.rb:120:in `request'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant