The NXT FHIR API authorization implementation follows the requirements laid out by the SMART App Launch Framework v1.0.0 specifications. This document builds on top of the above specification to clarify the implementation details of the NXT framework.

Application registration

In order to be able to access protected resources in the NXT FHIR APi, a client application has to be registered with the system. In order to do that you need to provide us with a few pieces of information:

  • Application name
  • Application type: confidential (an application that can protect a secret), public (example a browser based SPA), native, system (a server-to-server type application)
  • redirect uri - used to redirect the browser to your application after the authorization workflow as well as confirm your identity
  • JWKS uri - for system applications this is the URL where your public signing key information can be retrieved

After registration we will generate a client_id and a shared secret that will be sent securely to you.

Authorization URLs

Each deployed NXT FHIR service advertises its authorization specific URLs using the smart-configuration endpoint. In order to retrieve the conformance document you should perform a GET request on the endpoint smart-configuration url:

Example

Request

GET https://r4cert.medicasoft.us/api/fhir/.well-known/smart-configuration

Response

{
  "authorization_endpoint": "https://r4cert.medicasoft.us/api/security/smart/authorize",
  "token_endpoint": "https://r4cert.medicasoft.us/api/security/smart/token",
  "token_endpoint_auth_methods_supported": [
    "client_secret_basic"
  ],
  "registration_endpoint": "https://dev-53834000.okta.com/oauth2/aus4iqk1j2177jl9N5d7/v1/clients",
  "scopes_supported": [
    "openid",
    "profile",
    "launch",
    "launch/patient",
    "patient/*.read",
    "user/*.read",
    "offline_access",
    "system/*.read"
  ],
  "response_types_supported": [
    "code",
    "code id_token",
    "id_token",
    "refresh_token"
  ],
  "introspection_endpoint": "https://dev-53834000.okta.com/oauth2/aus4iqk1j2177jl9N5d7/v1/introspect",
  "revocation_endpoint": "https://dev-53834000.okta.com/oauth2/aus4iqk1j2177jl9N5d7/v1/revoke",
  "capabilities": [
    "launch-ehr",
    "client-public",
    "client-confidential-symmetric",
    "context-ehr-patient",
    "sso-openid-connect",
    "launch-standalone",
    "context-standalone-patient",
    "permission-offline",
    "permission-patient",
    "context-banner",
    "context-style",
    "permission-user"
  ],
  "code_challenge_methods_supported": [
    "S256"
  ]
}

Supported Scopes

The NXT FHIR APi supports the following scopes:

launch/patient, openid, fhirUser, offline_access, patient/Medication.read, patient/AllergyIntolerance.read, patient/CarePlan.read, patient/CareTeam.read, patient/Condition.read, patient/Device.read, patient/DiagnosticReport.read, patient/DocumentReference.read, patient/Encounter.read, patient/Goal.read, patient/Immunization.read, patient/Location.read, patient/MedicationRequest.read, patient/Observation.read, patient/Organization.read, patient/Patient.read, patient/Practitioner.read, patient/Procedure.read, patient/Provenance.read, patient/PractitionerRole.read, user/Medication.read, user/AllergyIntolerance.read, user/CarePlan.read, user/CareTeam.read, user/Condition.read, user/Device.read, user/DiagnosticReport.read, user/DocumentReference.read, user/Encounter.read, user/Goal.read, user/Immunization.read, user/Location.read, user/MedicationRequest.read, user/Observation.read, user/Organization.read, user/Patient.read, user/Practitioner.read, user/Procedure.read, user/Provenance.read, user/PractitionerRole.read, system/*.read

Launch sequences

The NXT FHIR API implements the following SMART launch sequences

EHR Launch

Your application is launched from the HealthCenter PHR user interface.

  1. The HealthCenter user interface will open your application URL in a new browser page, along with an iss and a launch parameter. iss is the FHIR API url that you can use to discover the API endpoint launch is an opaque token that will be exchanged for an access token later on. It is also used to provide the application launch context (e.g. patient selected in HealthCenter at the time of launch).

    Example

    GET https://inferno.healthit.gov/suites/custom/smart/launch?iss=https://r4cert.medicasoft.us/api/fhir&launch=12345678
    
  2. Your application retrieves the SMART configuration from the smart-configuration endpoint

    Example

    GET https://r4cert.medicasoft.us/api/fhir/.well-known/smart-configuration
    
  3. Your application then follows the standalone launch sequence as described below except that it should also pass the received launch parameter to the authorize endpoint

    Example

    GET https://r4cert.medicasoft.us/api/security/smart/authorize?response_type=code&redirect_uri=[redirect_uri]&client_id=[client_id]&state=    [client_application_state]&scope=[requested_scopes]&aud=https%3A%2F%2Fr4cert.medicasoft.us%2Fapi%2Ffhir&launch=[received_launch_parameter]
    

Standalone launch

In the standalone launch, you application initiates the aouthorization flow in order to connect to the FHIR API endpoint.

  1. Your application requests an authorization code

    Your application will snd a GET request to the authorization endpoint with the following query parameters:

    • response_type - always code
    • client_id - the application client id received from MedicaSoft during the Application Registration process
    • redirect_uri - your application redirect URL
    • scope - requested application scopes (see). For a patient facing client application you should send some or all of the patient access scopes, for a practitioner facing application you should send the user scopes.
    • state - this is an opaque identifier generated by your application that identifies this session
    • aud - FHIR API endpoint URL

    Example

    GET https://r4cert.medicasoft.us/api/security/smart/authorize?response_type=code&redirect_uri=[redirect_uri]&client_id=[client_id]&state=    [client_application_state]&scope=[requested_scopes]&aud=https%3A%2F%2Fr4cert.medicasoft.us%2Fapi%2Ffhir
    
  2. The authorization server authenticates and authorizes the user

    If the authentication is successful, the authorization server redirects the user to the consent page, otherwise it return a 401 error. The user authorizes some or all of the requested scopes. The authorization server redirects the browser to the redirect URL you supplied during the [Application Registration] (#application-registration) and appends the following parameters:

    • code - the authorization code is a token generated by the authorization server that will be exchanged for an access token
    • state - your application state parameter as sent in step 1

    Example

    GET https://inferno.healthit.gov/suites/custom/smart/redirect?code=FzPDQkGRy0yHttCLo4pFwyCTr-3_aMAjJ8ctngFzoFM&state=42042f18-a66c-4a55-86ca-bf1d72d25798
    
  3. Your application exchanges the authorization token for an access token

    Your application will send a POST request to the token endpoint with a url-encoded form payload (Content-Type: application/x-www-form-urlencoded). The parameters sent depend on whether your application was issued a client secret or not:

    • grant_type - always authorization_code
    • redirect_uri - your application redirect URL
    • code - the authorization code received during the previous step

    If the application does not own a client secret the the client_id parameter is sent in the query string as well.

    If the application owns a client secret then the client_id value is passed to the token endpoint in the Authorization header following the Basic authentication scheme:

    Authorization: Basic base64Encode{<client_id>:<client_secret>}
    

    The token server responds with a JSON object that includes:

    • token_type - always Bearer
    • expires_in - token expiration time in seconds
    • access_token - the access token granted to your application
    • scope - the scopes consented by the user
    • refresh_token - returned only if the application owns a client secret. The refresh token can be used to rquest a new access token after the current access token has expired.
    • id_token - returned if the openid scope was requested
    • patient - the patient id for patient facing workflows

    Example

    Request

    POST https://r4cert.medicasoft.us/api/security/smart/token
    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic VGVzdENsaWVudElkOlRlc3RDbGllbnRTZWNyZXQK
        
    code=FzPDQkGRy0yHttCLo4pFwyCTr-3_aMAjJ8ctngFzoFM&grant_type=authorization_code&redirect_uri=https%3A%2F%2Finferno.healthit.    gov%2Fsuites%2Fcustom%2Fsmart%2Fredirect
    

    Response

    {
      "token_type": "Bearer",
      "expires_in": 86400,
      "access_token": "eyJraWQiOiJpLUs5RzVMdl9EOFpfcGZfYTVpeUtaeTVaSkpiM1l6TDJfOUhDOXZTMTdRIiwiYWxnIjoiUlMyNTYifQ.    eyJ2ZXIiOjEsImp0aSI6IkFULlg5Q1VsZkRYOUY1TXhsY0tuU0w3bGthMU1zbk5EakdRYVptQnNENC1fTlUub2FycDZ2b3lxOUFTc0llMHQ1ZDYiLCJpc3MiOiJodHRwczovL2Rldi01MzgzNDAwMC5va3RhLm    NvbS9vYXV0aDIvYXVzNGlxazFqMjE3N2psOU41ZDciLCJhdWQiOiJodHRwczovL3I0Y2VydC5tZWRpY2Fzb2Z0LnVzL2ZoaXIiLCJpYXQiOjE2NjU4MTY4OTksImV4cCI6MTY2NTkwMzI5OSwiY2lkIjoiMG9h    NGlxOXR5djhSYXFEZkc1ZDciLCJ1aWQiOiIwMHU2djFrMHJiSFlHR1F5djVkNyIsInNjcCI6WyJwYXRpZW50L0RvY3VtZW50UmVmZXJlbmNlLnJlYWQiLCJwYXRpZW50L1BhdGllbnQucmVhZCIsIm9wZW5pZC    IsInBhdGllbnQvUHJvY2VkdXJlLnJlYWQiLCJwYXRpZW50L09yZ2FuaXphdGlvbi5yZWFkIiwicGF0aWVudC9Mb2NhdGlvbi5yZWFkIiwicGF0aWVudC9NZWRpY2F0aW9uLnJlYWQiLCJwYXRpZW50L0NvbmRp    dGlvbi5yZWFkIiwicGF0aWVudC9PYnNlcnZhdGlvbi5yZWFkIiwicGF0aWVudC9EZXZpY2UucmVhZCIsInBhdGllbnQvQ2FyZVRlYW0ucmVhZCIsImZoaXJVc2VyIiwicGF0aWVudC9JbW11bml6YXRpb24ucm    VhZCIsImxhdW5jaC9wYXRpZW50IiwicGF0aWVudC9QcmFjdGl0aW9uZXIucmVhZCIsInBhdGllbnQvUHJvdmVuYW5jZS5yZWFkIiwicGF0aWVudC9Hb2FsLnJlYWQiLCJvZmZsaW5lX2FjY2VzcyIsInBhdGll    bnQvQ2FyZVBsYW4ucmVhZCIsInBhdGllbnQvRW5jb3VudGVyLnJlYWQiLCJwYXRpZW50L1ByYWN0aXRpb25lclJvbGUucmVhZCIsInBhdGllbnQvQWxsZXJneUludG9sZXJhbmNlLnJlYWQiLCJwYXRpZW50L0    1lZGljYXRpb25SZXF1ZXN0LnJlYWQiLCJwYXRpZW50L0RpYWdub3N0aWNSZXBvcnQucmVhZCJdLCJhdXRoX3RpbWUiOjE2NjU4MTY2NTMsInN1YiI6InBhdGllbnRAbWVkaWNhc29mdC51cyIsImxhdW5jaF9y    ZXNwb25zZV9wYXRpZW50IjoiYmNmYTgzZGYtZWU4Yy05NzIxLWNjMDctYmRjZmMyYjFlM2YyIiwidmFsaWRfY29uc2VudCI6InRydWUiLCJmaGlyVXNlciI6IlBhdGllbnQvYmNmYTgzZGYtZWU4Yy05NzIxLW    NjMDctYmRjZmMyYjFlM2YyIn0.    fqIM8d6UAAczhNlvHrglVkd2_F4eAIVVXAnkAYnITRCTTyo62jLy6gdG46DB5A29tPKHvEhScFCutsnYudMmj8qaCTMZN7OFGC8bSMyZY76xrgYr8Bfgorr-1cDcAbhwu6eACxTCHjJuAUrG2knLam5l7iviCL    y31Ua-d2kI0Wm7z1QKGFFGU_bNS229bS09dyHB4Rho1myFTEpninuf1D9Q1Op-J3GSWGGBO5g0XQg3bpyeFPPNNumyRYsfEr7oiPU7lyq17xYaweU_GQgLn3-JSfrmBJ16YPAdbOsw6nvsPxwTjvyVMqHC70tT    J_HU2SR_bsGHPf7JaNn_F0FzpQ",
      "scope": "patient/DocumentReference.read patient/Patient.read openid patient/Procedure.read patient/Organization.read patient/Location.read patient/    Medication.read patient/Condition.read patient/Observation.read patient/Device.read patient/CareTeam.read fhirUser patient/Immunization.read launch/patient     patient/Practitioner.read patient/Provenance.read patient/Goal.read offline_access patient/CarePlan.read patient/Encounter.read patient/PractitionerRole.read     patient/AllergyIntolerance.read patient/MedicationRequest.read patient/DiagnosticReport.read",
      "refresh_token": "IMUQELjly8LnHlKrZLgunvmiXu8nfNnmiTlFMOwGEZs",
      "id_token": "eyJraWQiOiJpLUs5RzVMdl9EOFpfcGZfYTVpeUtaeTVaSkpiM1l6TDJfOUhDOXZTMTdRIiwiYWxnIjoiUlMyNTYifQ.    eyJzdWIiOiIwMHU2djFrMHJiSFlHR1F5djVkNyIsInZlciI6MSwiaXNzIjoiaHR0cHM6Ly9kZXYtNTM4MzQwMDAub2t0YS5jb20vb2F1dGgyL2F1czRpcWsxajIxNzdqbDlONWQ3IiwiYXVkIjoiMG9hNGlxOX    R5djhSYXFEZkc1ZDciLCJpYXQiOjE2NjU4MTY4OTksImV4cCI6MTY2NTgyMDQ5OSwianRpIjoiSUQuS1hiYno4My1VNDZSRXV6ZWxGM1dpMUtnU2U1bVROcHpuTWlaa1JFOUpaTSIsImFtciI6WyJwd2QiXSwi    aWRwIjoiMDBvNGlwbmpteWI0OHU4TEc1ZDciLCJhdXRoX3RpbWUiOjE2NjU4MTY2NTMsImF0X2hhc2giOiJQN0RYUjlHY0c4TURpSmdFLUlvS3lRIiwiZmhpclVzZXIiOiJQYXRpZW50L2JjZmE4M2RmLWVlOG    MtOTcyMS1jYzA3LWJkY2ZjMmIxZTNmMiJ9.    B0jrd3L0L_7eTh9VvUKs2hoH6stopm0b0fT5Pu_DS3i08gRqH4nEk-usrVEOeq7MxrlzrohKIxqxdQY8M-FrIjVDYKbU2NWwmUacsaC7j7iywQm8yNLN6UsCaJvGOeYgH75SzXBd5pNRunViPZDhyMDnqLSvDL    yofXRY23V9yLF7zVlDG-xwRSWT5AvtR6MXw2gWi8owFGD-F_gDTBvtMF7ajStskT3uuCXIRRnktIENBOK7FpvIZ3NJGDRID_5PHmeFPqibI8TrSL98LMpKSJDb_gryyw8NK_KS_iZ_FII02BhvqaczxCw8hzn6    2HIf7MOZPv6lV3oe2H5Z9DHDDQ",
      "patient": "bcfa83df-ee8c-9721-cc07-bdcfc2b1e3f2"
    }
    
  4. Your application calls into the FHIR API

    The client application can issue FHIR API calls by setting the Authorization header with the Bearer scheme and the authorization token received in the previous step.

    Example

    GET https://r4cert.medicasoft.us/api/fhir/Patient?_id=bcfa83df-ee8c-9721-cc07-bdcfc2b1e3f2
    Authorization: Bearer eyJraWQiOiJpLUs5RzVMdl9EOFpfcGZfYTVpeUtaeTVaSkpiM1l6TDJfOUhDOXZTMTdRIiwiYWxnIjoiUlMyNTYifQ.    eyJ2ZXIiOjEsImp0aSI6IkFULnJQdFBqclpQeTFfbmFLd09yeEdNLUpidjNvUzZVYnVXSDk0N05OSHBnMG8ub2FycDV5ZjRzcmZlSWxVcnc1ZDYiLCJpc3MiOiJodHRwczovL2Rldi01MzgzNDAwMC5va3RhLmNv    bS9vYXV0aDIvYXVzNGlxazFqMjE3N2psOU41ZDciLCJhdWQiOiJodHRwczovL3I0Y2VydC5tZWRpY2Fzb2Z0LnVzL2ZoaXIiLCJpYXQiOjE2NjU3NzI1NTEsImV4cCI6MTY2NTg1ODk1MSwiY2lkIjoiMG9hNGlx    OXR5djhSYXFEZkc1ZDciLCJ1aWQiOiIwMHU0aXBuanRvRkJxTUhmbjVkNyIsInNjcCI6WyJwYXRpZW50L0RvY3VtZW50UmVmZXJlbmNlLnJlYWQiLCJwYXRpZW50L1BhdGllbnQucmVhZCIsInBhdGllbnQvUHJv    Y2VkdXJlLnJlYWQiLCJwYXRpZW50L09yZ2FuaXphdGlvbi5yZWFkIiwicGF0aWVudC9Mb2NhdGlvbi5yZWFkIiwicGF0aWVudC9NZWRpY2F0aW9uLnJlYWQiLCJwYXRpZW50L0NvbmRpdGlvbi5yZWFkIiwicGF0    aWVudC9PYnNlcnZhdGlvbi5yZWFkIiwicGF0aWVudC9EZXZpY2UucmVhZCIsInBhdGllbnQvQ2FyZVRlYW0ucmVhZCIsImZoaXJVc2VyIiwicGF0aWVudC9JbW11bml6YXRpb24ucmVhZCIsImxhdW5jaC9wYXRp    ZW50IiwicGF0aWVudC9QcmFjdGl0aW9uZXIucmVhZCIsInBhdGllbnQvUHJvdmVuYW5jZS5yZWFkIiwicGF0aWVudC9Hb2FsLnJlYWQiLCJvcGVuaWQiLCJvZmZsaW5lX2FjY2VzcyIsInBhdGllbnQvQ2FyZVBs    YW4ucmVhZCIsInBhdGllbnQvUHJhY3RpdGlvbmVyUm9sZS5yZWFkIiwicGF0aWVudC9FbmNvdW50ZXIucmVhZCIsInBhdGllbnQvQWxsZXJneUludG9sZXJhbmNlLnJlYWQiLCJwYXRpZW50L01lZGljYXRpb25S    ZXF1ZXN0LnJlYWQiLCJwYXRpZW50L0RpYWdub3N0aWNSZXBvcnQucmVhZCJdLCJhdXRoX3RpbWUiOjE2NjU3Njk4MTcsInN1YiI6ImNhdGFsaW4uYnJhbmVhQG1lZGljYXNvZnRsbGMuY29tIiwibGF1bmNoX3Jl    c3BvbnNlX3BhdGllbnQiOiJiY2ZhODNkZi1lZThjLTk3MjEtY2MwNy1iZGNmYzJiMWUzZjIiLCJ2YWxpZF9jb25zZW50IjoidHJ1ZSIsInBhdGllbnQiOiJiY2ZhODNkZi1lZThjLTk3MjEtY2MwNy1iZGNmYzJi    MWUzZjIiLCJmaGlyVXNlciI6IlBhdGllbnQvYmNmYTgzZGYtZWU4Yy05NzIxLWNjMDctYmRjZmMyYjFlM2YyIn0.    T9PEjb1c_zBqSAIlcPcAFLAdNdQKuNbOfB0yK28-5PqNJVuauY5q0COqMVqDcvKdsEpBMWcT5HFN5h0i-Lo7D262_KMuYAE2S9PJOcyumfZchYVgqJqErVz-5S8WvWxXPJKV2lEcJA6-8S14vPaxlj_NF9c1X9ZT    8wgjVaN-xvRwWZR_mCQRM6NkK3HlJGA_UEjMb__Oh3Y4U3zR2oTdYQHcbz8NTG-p9TQD5V0xtQChSX1PVTI4MxqOKveSHIJMfHk-JLM5AMw94GAcVs6dPRQivLnsyJ3Ohg2ezc89d6xobuiQ016zls_dRijdvfXr    A6y7810RLK__gXntPQsVBQ
    
  5. Your application uses a refresh token to request a new access token

    When the access token has expired the client application ca use the refresh token to request a new access token. To do that you have to issue a POST request to the token endpoint with a url-encoded form payload (Content-Type: application/x-www-form-urlencoded) having two parameters:

    • grant_type - always refresh_token
    • refresh_token - the refresh token received during step 3

    The Authorization header should be set with the Basic authentication scheme with the username set to the client_id and password set to the client_secret:

    Authorization: Basic base64Encode{<client_id>:<client_secret>}
    

    The authorization server will respond with a JSON object similar to the one returned in step 3:

    {
      "token_type": "Bearer",
      "expires_in": 86400,
      "access_token": "eyJraWQiOiJpLUs5RzVMdl9EOFpfcGZfYTVpeUtaeTVaSkpiM1l6TDJfOUhDOXZTMTdRIiwiYWxnIjoiUlMyNTYifQ.    eyJ2ZXIiOjEsImp0aSI6IkFULllraERma0d2TWpsbk1pdW5SSXB1LXZjOU5lVzZ0WTN6UmI3eHJEMzd1X0Uub2FycDZ2b3lxOUFTc0llMHQ1ZDYiLCJpc3MiOiJodHRwczovL2Rldi01MzgzNDAwMC5va3RhLm    NvbS9vYXV0aDIvYXVzNGlxazFqMjE3N2psOU41ZDciLCJhdWQiOiJodHRwczovL3I0Y2VydC5tZWRpY2Fzb2Z0LnVzL2ZoaXIiLCJpYXQiOjE2NjU4MTY5MDMsImV4cCI6MTY2NTkwMzMwMywiY2lkIjoiMG9h    NGlxOXR5djhSYXFEZkc1ZDciLCJ1aWQiOiIwMHU2djFrMHJiSFlHR1F5djVkNyIsInNjcCI6WyJwYXRpZW50L0RvY3VtZW50UmVmZXJlbmNlLnJlYWQiLCJwYXRpZW50L1BhdGllbnQucmVhZCIsIm9wZW5pZC    IsInBhdGllbnQvUHJvY2VkdXJlLnJlYWQiLCJwYXRpZW50L09yZ2FuaXphdGlvbi5yZWFkIiwicGF0aWVudC9Mb2NhdGlvbi5yZWFkIiwicGF0aWVudC9NZWRpY2F0aW9uLnJlYWQiLCJwYXRpZW50L0NvbmRp    dGlvbi5yZWFkIiwicGF0aWVudC9PYnNlcnZhdGlvbi5yZWFkIiwicGF0aWVudC9EZXZpY2UucmVhZCIsInBhdGllbnQvQ2FyZVRlYW0ucmVhZCIsImZoaXJVc2VyIiwicGF0aWVudC9JbW11bml6YXRpb24ucm    VhZCIsImxhdW5jaC9wYXRpZW50IiwicGF0aWVudC9QcmFjdGl0aW9uZXIucmVhZCIsInBhdGllbnQvUHJvdmVuYW5jZS5yZWFkIiwicGF0aWVudC9Hb2FsLnJlYWQiLCJvZmZsaW5lX2FjY2VzcyIsInBhdGll    bnQvQ2FyZVBsYW4ucmVhZCIsInBhdGllbnQvUHJhY3RpdGlvbmVyUm9sZS5yZWFkIiwicGF0aWVudC9FbmNvdW50ZXIucmVhZCIsInBhdGllbnQvQWxsZXJneUludG9sZXJhbmNlLnJlYWQiLCJwYXRpZW50L0    1lZGljYXRpb25SZXF1ZXN0LnJlYWQiLCJwYXRpZW50L0RpYWdub3N0aWNSZXBvcnQucmVhZCJdLCJhdXRoX3RpbWUiOjE2NjU4MTY2NTMsInN1YiI6InBhdGllbnRAbWVkaWNhc29mdC51cyIsImxhdW5jaF9y    ZXNwb25zZV9wYXRpZW50IjoiYmNmYTgzZGYtZWU4Yy05NzIxLWNjMDctYmRjZmMyYjFlM2YyIiwidmFsaWRfY29uc2VudCI6InRydWUiLCJwYXRpZW50IjoiYmNmYTgzZGYtZWU4Yy05NzIxLWNjMDctYmRjZm    MyYjFlM2YyIiwiZmhpclVzZXIiOiJQYXRpZW50L2JjZmE4M2RmLWVlOGMtOTcyMS1jYzA3LWJkY2ZjMmIxZTNmMiJ9.    kDeXOTCjQNA8JsySKv3zcBVPPXTsAKUUPFCt4CYtBVsQ3pYgF46n7QLOGUnePxsiBXKewY5iXhIAdcpml7i5edbXWqav-sQ-XG9jZnlPn4AHFlBrAT2CWA2ZiYLuExdB3Ck2vP5XUEb6vDeiDV1NXJdL4M_42X    Ywil8BiGdYhZP8stza8kiWJKCAS8h9Svk9phegGqLDY_wEjH8nAHzw0W2-ZJSq85-OpaQusTxn2y65nndTqaKls7ElCHldsnduSG0k_PK8HlPop3vJuJ830hMjR0t7Yro7n8iOToWiMzzsbSLG0RT6qbiE1SxE    qOdbmpvyILLWL7uWH8GuffgYkg",
      "scope": "patient/DocumentReference.read patient/Patient.read openid patient/Procedure.read patient/Organization.read patient/Location.read patient/    Medication.read patient/Condition.read patient/Observation.read patient/Device.read patient/CareTeam.read fhirUser patient/Immunization.read launch/patient     patient/Practitioner.read patient/Provenance.read patient/Goal.read offline_access patient/CarePlan.read patient/PractitionerRole.read patient/Encounter.read     patient/AllergyIntolerance.read patient/MedicationRequest.read patient/DiagnosticReport.read",
      "refresh_token": "IMUQELjly8LnHlKrZLgunvmiXu8nfNnmiTlFMOwGEZs",
      "id_token": "eyJraWQiOiJpLUs5RzVMdl9EOFpfcGZfYTVpeUtaeTVaSkpiM1l6TDJfOUhDOXZTMTdRIiwiYWxnIjoiUlMyNTYifQ.    eyJzdWIiOiIwMHU2djFrMHJiSFlHR1F5djVkNyIsInZlciI6MSwiaXNzIjoiaHR0cHM6Ly9kZXYtNTM4MzQwMDAub2t0YS5jb20vb2F1dGgyL2F1czRpcWsxajIxNzdqbDlONWQ3IiwiYXVkIjoiMG9hNGlxOX    R5djhSYXFEZkc1ZDciLCJpYXQiOjE2NjU4MTY5MDMsImV4cCI6MTY2NTgyMDUwMywianRpIjoiSUQuVmVFdURueF8ybjZrRXJuRlg5U21oMk1RVENPVmthZ092bllKUENGUDUtTSIsImFtciI6WyJwd2QiXSwi    aWRwIjoiMDBvNGlwbmpteWI0OHU4TEc1ZDciLCJhdXRoX3RpbWUiOjE2NjU4MTY2NTMsImF0X2hhc2giOiJGQ1FvRHpvMWtUemg2dDNobE5mckVnIiwiZmhpclVzZXIiOiJQYXRpZW50L2JjZmE4M2RmLWVlOG    MtOTcyMS1jYzA3LWJkY2ZjMmIxZTNmMiJ9.    ONFVTT19J_HHVd8aayoodzF3sqnG4rGXQJG8ZTqDffL7bTQv9FF3jjCdM7_xxoYQroU355cgxeqyoO8Aky67O4ZG_VANUX-fim1Z8Ie-9KyMvVylnNMZB9ehA5qXb-6bLZy3Sx8VV3DnwnwzLv83uZES0U9Hd1    9GdsfS074woZN65oqxOHjAgeaHi5Zz9bdz6Yie1_Fa-Wu4ce6zwUMGCu68hnGkQpKD6KcI1q4ml92zC2SQ0Sin1Q5hxW516FjVH3wQwM6SC7gZBgvusPc9hlWVh4JRGXuOp5QhyfwMB7Oa-NP8aY9oDOeOLbvY    kNeLrbSyjQK8wPO25XcRY4dXRA",
      "patient": "bcfa83df-ee8c-9721-cc07-bdcfc2b1e3f2"
    }
    

System Application authorization flow

A system application pre-authorises it’s users to access FHIR API endpoints. As such it does not need to follow the whole standalone application launch flow. A system application should register a public JWKS endpoint and use the private key authorization flow. To acces the FHIR API the application has to go through the following steps:

  1. Your application creates a JWT signed with your private key.

    The JWT should contain the following headers:

    • alg - should be either ES384 or RS384
    • typ - always JWT
    • kid - the kid value from your public JWKS

    The JWT should contain the following claims:

    • iss - this is your client_id
    • sub - this is your client_id
    • aud - the FHIR endpoint URL
    • exp - expiration time, should be no more than 5 minutes
    • jti - a unique identifier for this JWT
  2. Your application obtains an access token

    The JWT created in step 1 will be sent to the token endpoint in a POST request. The payload is Form Url-Encoded and it should have the following parameters:

    • grant_type - always client_credentials
    • client_assertion_type - always urn:ietf:params:oauth:client-assertion-type:jwt-bearer
    • client_assertion - the JWT generated in step 1
    • scope - requested scopes

    Example

    Request

    POST https://dev-53834000.okta.com/oauth2/aus4iqk1j2177jl9N5d7/v1/token
    Content-Type: application/x-www-form-urlencoded
       
    client_assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCIsImtpZCI6IjRiNDlhNzM5ZDFlYjExNWIzMjI1ZjRjZjliZWI2ZDFiIn0.   eyJpc3MiOiIwb2E2YTRkeWxwZExqbjdhVTVkNyIsInN1YiI6IjBvYTZhNGR5bHBkTGpuN2FVNWQ3IiwiYXVkIjoiaHR0cHM6Ly9kZXYtNTM4MzQwMDAub2t0YS5jb20vb2F1dGgyL2F1czRpcWsxajIxNzdqbDlO   NWQ3L3YxL3Rva2VuIiwiZXhwIjoxNjY1NzcyNzk3LCJqdGkiOiI0MTE3YmZmNGQwNjgwYTk4YjU4YTk5ZDc3Zjc3NWNmYjkyMzk1OGRiYjczYjU4YzU4NTNmOTQ0MjkzZjhlNmU2In0.   klD80a-HkfZObbe-oZaPWJ02Iv2WaPwU6-nzITg5o4LZO_w6xpZnylZj2LdKekJpDPzQXH8WDitn7Si_8s9SvY6dATEKbekhi2gZe_LtXGoxJSZ7SBtMDP8bmaLnFkPr&   client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&grant_type=client_credentials&scope=system%2F%2A.read
    

    Response

    {
      "token_type": "Bearer",
      "expires_in": 86400,
      "access_token": "eyJraWQiOiJpLUs5RzVMdl9EOFpfcGZfYTVpeUtaeTVaSkpiM1l6TDJfOUhDOXZTMTdRIiwiYWxnIjoiUlMyNTYifQ.   eyJ2ZXIiOjEsImp0aSI6IkFULkJwZ1JqcmllZUk0aEpSWHMxTHZ4eHhoNTZrNmQtTjk4M1VDT0xJVUtfdXMiLCJpc3MiOiJodHRwczovL2Rldi01MzgzNDAwMC5va3RhLmNvbS9vYXV0aDIvYXVzNGlxazFqMj   E3N2psOU41ZDciLCJhdWQiOiJodHRwczovL3I0Y2VydC5tZWRpY2Fzb2Z0LnVzL2ZoaXIiLCJpYXQiOjE2NjU3NzI0OTgsImV4cCI6MTY2NTg1ODg5OCwiY2lkIjoiMG9hNmE0ZHlscGRMam43YVU1ZDciLCJz   Y3AiOlsic3lzdGVtLyoucmVhZCJdLCJzdWIiOiIwb2E2YTRkeWxwZExqbjdhVTVkNyIsInZhbGlkX2NvbnNlbnQiOiJ0cnVlIn0.   lX8uPwfS149SaxQ6orEtfkLVlv0R_oVn7aeDydjkpx5C5zysiUC5__ETdEGl3cvf5sE-GDBwg-fwUnfKDEJj1XhmW3NZ01G6_NGvEmYzw6UO89djTe07JAqqu1OI6NPkmRHaKsqN_4cNtctWjvlXkZkHbgkYfZ   LSZUrE97igNwpcUx2Us29DAZgaTvU5yezM4ZSRKEHupCkBCeP_0Cciq_xQ19vynM46HCfH4T8ckA56BZEcRmb0udRPSj_EnfDH6LVSnPJIKWR3DrwTRe2AneyvAaVkWyw7Ktd3Lif3Jjc_6SbzNI2sep8Tuw3K   dGd2XQwJEEgzboZR2jLUzYBKvQ",
      "scope": "system/*.read"
    }
    

    Token refresh for native applications

A native application is treated by the NXT platform just as any other public application following the standalone launch sequence. As such in order to request a new access token it will have to present the refresh token received during step 3 above along with an Authorization header set with the client_id and client_secret (see step 5 above). The native application should take steps to protect the client secret. For best practices please refer to OAuth 2.0 for Mobile and Native Apps. The NXT FHIR API does not support at this moment the PKCE flow but it makes efforts to provide additional authorization protection in the future.