FHIR Authorization
As described in the SMART on FHIR Authorization Flow, to make API calls to the Kodjin FHIR Server API, the client application provides an access token as a bearer token.
The access token SHALL be obtained during the authorization flow by calling the authorization endpoint on the authorization server. The link for the authorization endpoint can be found here.
For applications that use a two-legged authentication (system-to-system), an access token can be obtained by directly calling the token endpoint. Applications that use a three-legged authentication must first call the authorization endpoint to request and obtain an end user's consent. The token endpoint response for three-legged authentication applications may also contain an ID token, refresh token, or launch context.
A proof key for code exchange (PKCE) is disabled in this version of the implementation
Authorize the client
The authorization endpoint is used for end user login, limits scopes requested by application, and gives consent. These actions are prerequisites to requesting an access token. This endpoint SHOULD be obtained from the authorization endpoint, which temporarily redirects the end user to the Kodjin FHIR Server API login where the user is asked to log in or get automatically authenticated using an existing session. The user is then prompted for scope limitations and consent form. Afterwards, the user is redirected back to the application requesting the access token with an authorization code. The app then provides this authorization code to the token endpoint to obtain an access token.
The flow described above is a browser flow only because the authorization server will redirect the user's browser to the provided redirect URL.
METHOD GET
GET [authorization_endpoint]?response_type=code&client_id=[client_id]&redirect_uri=[redirect_uri]&scope=[scope]&state=[state]&aud=[aud]
PARAMS
authorization_endpoint
- authorization endpoint SHALL be observed from the FHIR base url authorization observation endpoint.client_id
- client ID for registered developers application.redirect_url
- url for for developers application which browser redirect after successfull authorization. Must exactly match a redirect URI configured for the developers application client credentials during registration.scope
- requested optional scopes by application delimited by space, case sensitive. At a minimum, the client must request the OpenID Connect scope (openid) for successful authentication and to obtain an ID token in the token endpoint response. To obtain a refresh token in the token endpoint response, the client must request the offline_access scope. To perform a SMART app launch sequence, the client must request either the launch or launch/patient scope (for provider EHR launch or patient standalone launch) in addition to resource-level scopes for those FHIR endpoints you will access through your app launch. Details about scopes.state
- a one-time use arbitrary string provided by developers application (client) and subsequently returned by the authorized endpoint. The intent of this parameter, per OAuth specification, is for applications to compare the request and response values to prevent cross-site request forgery attacks.aud
- FHIR base URL, used to specify the organization for which the end user will be authenticated.
RESPONSES
code
- authorization code generated by Kodjin FHIR Server API authorization server and required to make a token request.state
- identical value to the state parameter provided in client app’s authorize request.
Example
https://demo.kodjin.com/auth/realms/fhir/protocol/openid-connect/auth?response_type=code&client_id=my-app&redirect_uri=https%3A%2F%2Fmy.app.com%2Fsuites%2Fcustom%2Fsmart%2Fredirect&scope=launch%2Fpatient+openid+fhirUser+offline_access+patient%2FMedication.read+patient%2FAllergyIntolerance.read+patient%2FCarePlan.read+patient%2FCareTeam.read+patient%2FCondition.read+patient%2FDevice.read+patient%2FDiagnosticReport.read+patient%2FDocumentReference.read+patient%2FEncounter.read+patient%2FGoal.read+patient%2FImmunization.read+patient%2FLocation.read+patient%2FMedicationRequest.read+patient%2FObservation.read+patient%2FOrganization.read+patient%2FPatient.read+patient%2FPractitioner.read+patient%2FProcedure.read+patient%2FProvenance.read+patient%2FPractitionerRole.read+patient%2FServiceRequest.read&state=e75c105d-04b4-47e6-b4af-a36773cc2600&aud=https%3A%2F%2Fdemo.kodjin.com%2Ffhir
Access token
Obtain an access token. The token endpoint is used for two-legged authorization applications. This method only works if the client supports this type of authorization.
METHOD POST
PARAMS
[token_endpoint url] - token endpoint SHALL be observed from the FHIR base url authorization observation endpoint.
BODY
Body SHALL be provided as Content-Type: application/x-www-form-urlencoded
.
client_id
- ID for the client-registered appgrant_type
- 'client_credentials'client_secret
- client secret for the registered appscope
- requested optional scopes delimited by space (e.g.,patient/*.read launch/patient
)
HEADERS
The authorization token SHALL be obtained during the authentication and authorization process. Refer to authentication and authorization for further details.
Header | Type | Required/Optional | Value |
---|---|---|---|
Content-Type | string | required | application/x-www-form-urlencoded |
RESPONSES
Code | Description | Comment |
---|---|---|
200 | OK | The request was processed successfully, and the access token was returned. |
400 | Bad request | Invalid request parameters, e.g., client ID or grant type. |
401 | Unauthorized | Invalid client secret. |
404 | no Route matched with those values | The request was able to communicate with a given server, but the server could not find what was requested. |
500 | Internal Server Error | The server has encountered a situation it doesn't know how to handle. |
The body will contain the JSON request response. If the token was obtained successfully, the body SHALL contain:
access_token
- signed base64 JWT access tokenexpires_in
- time in seconds until token expiration daterefresh_expires_in
- time in seconds until token expiration datetoken_type
- Type:Barear
scope
- list of the granted default client's scope
Example - Access token
eyJhbGciOiJSUzI1NiIs2nRqcCIgOiAiSldUIiwia2lkIiA6ICJMcEZjdWVzMzJqUFRkaF9pOFNVY0I1Tk5HenNQZD24REc0SHZNQTlIVXJvIn0.eyJleHAiOjE2NjYsNDQ5NDIsImlhdCI6MTY2NjU0NDY0MiwianRpIjoiNzRhNDIxN2QtN2VhYi00NWNmLTgxYjktNGFhNDhmM2U4NmU1IiwiaXNzIjoiaHR0cHM6Ly9zYW5kYm94LmZoaXIuZWxhdGlvbmVtci5jb20vYXV0aC9yZWFsbXMvZmhpciIsInN1YiI6IjEwZGZhY2RjLWIxNmYtNDI5OS1hY2M4LWM3Y2M4YTE3NDlhMiIsanR5cCI6IkJlYXJlciIsImF6cCI6ImluZmVybm8iLCJhY3IiOiIxIiwic2NvcGUiOiJsYXVuY2gvcGF0aWVudCIsImNsaWVudElkIjoiaW5mZXJubyIsImNsaWVudEhvc3QiOiIxMC4xLjEwLjExMCIsImNsaWVudEFkZHJlc3MiOiIxMC4xLjEwLjExMCIsImdyb3VwIjpbXX0.U8Q9zcFo_JeQIA2UG8j42Bu9eLASuF4D_hSJ-mPy6HT6xJ_9huSYa4FkkpFZ5gKKZQx7dTmye3qbwqyFBDrOWMZ1Z2lrh9DXXq6vP6FgSdyzqAu-Xvj-WdKdOXBsQ8gNP5LDg-PVdiMqNTne7uWJkX3CIv9mYOz72KjJf8GvGFDdKvArIN-t3aKFYR9Y41XGRqi9eph-91PbpZygZ4HcVjhM2nY8mR4EoKai5MQUtB6S8Y8VRkTaxpivcreXVe15YQ-34_rwcFjXczhCemmo4poVxWcpT-PU8bf1Obum_yKlNE1uJrTA223Knd_auyFUszyYm-xoCIJA6KxkoWsHew
Token Introspection
Endpoint to check the token’s status and the metadata content of a JWT token.
METHOD POST
PARAMS
[introspection_endpoint] - token introspection endpoint url SHALL be observed from the FHIR base url
BODY
Body SHALL provide as x-www-form-url-encoded
client_id
- ID for the client-registered appclient_secret
- client secret for the registered apptoken
- token value for the introspection
HEADERS
The authorization token SHALL be obtained during the authentication and authorization process. Go to authentication and authorization for further details.
Header | Type | Required/Optional | Value |
---|---|---|---|
Content-Type | string | required | application/x-www-form-urlencoded |
RESPONSES
Code | Description | Comment |
---|---|---|
200 | OK | The request was processed successfully, and an access token was returned. |
400 | Bad request | Invalid request parameters, e.g., client ID or grant type. |
401 | Unauthorized | Invalid client secret. |
404 | no Route matched with those values | The request was able to communicate with a given server, but the server could not find what was requested. |
500 | Internal Server Error | The server has encountered a situation it doesn't know how to handle. |
The body will contain the JSON request response. If the token was obtained successfully, the body SHALL contain:
active
- true or false. If the token is active, additional token information will be provided.exp
- time until token expiration date (seconds since Unix epoch)iat
- time when token was issued (seconds since Unix epoch)jti
- JWT ID, unique token IDsub
- list of the granted default client's scopeiss
- token issuer and signertyp
- type of the tokenazp
- client (application)acr
- authentication context classscope
- granted scopes for the tokenclientId
- optional client IDclientHost
- optional hostclientAddress
- optional host
Example
curl --location --request POST 'https://demo.kodjin.com/auth/realms/fhir/protocol/openid-connect/token/introspect' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: cookie=f9dd0e1484656621' \
--data-urlencode 'token=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJMcEZjdWVzMzJqUFRkaF9pOFNVY0I1Tk5HenNQZDF4REc0SHZNQTlIVXJvIn0.eyJleHAiOjE2NjY1NTI3NTcsImlhdCI6MTY2NjU1MjQ1NywianRpIjoiZWI3NWNmZWUtZDQ2NS00OGFkLWI5MTAtMzBhYjFmOTcxNTZhIiwiaXNzIjoiaHR0cHM6Ly9zYW5kYm94LmZoaXIuZWxhdGlvbmVtci5jb20vYXV0aC9yZWFsbXMvZmhpciIsInN1YiI6IjEwZGZhY2RjLWIxNmYtNDI5OS1hY2M4LWM3Y2M4YTE3NDlhMiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImluZmVybm8iLCJhY3IiOiIxIiwic2NvcGUiOiJsYXVuY2gvcGF0aWVudCIsImNsaWVudElkIjoiaW5mZXJubyIsImNsaWVudEhvc3QiOiIxMC4xLjEwLjExMCIsImNsaWVudEFkZHJlc3MiOiIxMC4xLjEwLjExMCIsImdyb3VwIjpbXX0.CBORAyD25vahskhUbzb-MXXG2KzNIXd_h30IpquvRdvCb5p0CyVbIlNk3dKUXdH9Axrmq5tT8iwbeZDeeRQQYLUdrgy_S8VTQnpquLRwS9PUqccGtH0hYIEwwwFgkyol3CibBh0jb9RFF5q9_JYpa_TSnpIiF7hvNLuevjK_OveUcBwa0ZJqt6shx4sI9po6JyHA3kmJwG5p-LRp6I-aZoc2DWkxk0F-LRfFAiv4m19xkLDMKHOsYSJ9ybqK-5h78YewATC9t1hrprczVFPaz0enBGmWwLIb0N_v5s354lo4JTAROCXcOKjIL3CORH0GuOcdR1clLGvi42LmGSAFvA' \
--data-urlencode 'client_id=my-app' \
--data-urlencode 'client_secret=67dmuHxjqdCh32r3itbPVIMhOREhXbOs'
{
"exp": 1666552757,
"iat": 1666552457,
"jti": "eb75cfee-d465-48ad-b910-30ab1f97156a",
"iss": "https://demo.kodjin.com/auth/realms/fhir",
"sub": "10dfacdc-b16f-4199-acc8-c7cd8a1749a2",
"typ": "Bearer",
"azp": "my-app",
"acr": "1",
"scope": "launch/patient",
"clientId": "my-app",
"clientHost": "192.168.10.110",
"clientAddress": "192.168.10.110",
"group": [],
"client_id": "my-app",
"username": "service-account-my-app",
"active": true
}
Token revocation
The token revocation is a mechanism for clients to indicate to the Kodjin FHIR Server API authorization server that an access token is no longer needed. This is used to enable a "log out" feature in clients, allowing the authorization server to clean up any security credentials associated with the authorization.
METHOD POST
PARAMS
[revocation_endpoint] - token revocation endpoint URL SHALL be observed from the FHIR base URL authorization observation endpoint
BODY
Body SHALL provide as x-www-form-url-encoded
client_id
- ID for the client registered appclient_secret
- client secret for the registered apptoken
- token value for the revocation
HEADERS
The Authorization token SHALL be obtained during Authentication and Authorization process. Goto Authentication and Authorization for further details.
Header | Type | Required/Optional | Value |
---|---|---|---|
Content-Type | string | required | application/x-www-form-urlencoded |
RESPONSES
Code | Description | Comment |
---|---|---|
200 | OK | The request was processed successfully, and the token was revoked. |
400 | Bad request | Invalid request parameters, e.g., client ID or client_secret or token. |
404 | no Route matched with those values | The request was able to communicate with a given server, but the server could not find what was requested. |
500 | Internal Server Error | The server has encountered a situation it doesn't know how to handle. |
Example - Request
curl --location --request POST 'https://demo.kodjin.com/auth/realms/fhir/protocol/openid-connect/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: cookie=f9dd0e1484656621' \
--data-urlencode 'client_id=my-app' \
--data-urlencode 'client_secret=bdmuHxjqMdh3Pr3itbLVIMhOREhXbOs' \
--data-urlencode 'token=eyJhbGciOiJSUzI1wiIsS1nR5cCIgOiAiSldUIiwia2lkIiA6ICJMcEZjdWVzMzJqUFRkaF9pOFNVY0I1Tk5HenNQZDF4REc0SHZNQTlIVXJvIn0.eyJleHAiOjE2NjY1NTI3NTcsImlhdCI6MTY2NjU1MjQ1NywianRpIjoiZWI3NWNmZWUtZDQ2NS00OGFkLWI5MTAtMzBhYjFmOTcxNTZhIiwiaXNzIjoiaHR0cHM6Ly9zYW5kYm94LmZoaXIuZWxhdGlvbmVtci5jb20vYXV0aC9yZWFsbXMvZmhpciIsInNsYiI6IjEwZGZhY2RjLWIxNmYtNDI5OS1hY2M4LWM3Y2M4YTE3NDlhMiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImluZmVybm8iLCJhY3IiOiIxIiwic2NvcGUiOiJsYXVuY2gvcGF0aWVudCIsImNsaWVudElkIjoiaW5mZXJubyIsImNsaWVudEhvc3QiOiIxMC4xLjEwLjExMCIsImNsaWVudEFkZHJlc3MiOiIxMC4xLjEwLjExMCIsImdyb3VwIjpbXX0.CBORAyD25vahskhUbzb-MXXG2KzNIXd_h30IpquvRdvCb5p0CyVbIlNk3dKUXdH9Axrmq5tT8iwbeZDeeRQQYLUdrgy_S8VTQnpquLRwS9PUqccGtH0hYIEwwwFgkyol3CibBh0jb9RFF5q9_JYpa_TSnpIiF7hvNLuevjK_OveUcBwa0ZJqt6shx4sI9po6JyHA3kmJwG5p-LRp6I-aZoc2DWkxk0F-LRfFAiv4m19xkLDMKHOsYSJ9ybqK-5h78YewATC9t1hrprczVFPaz0enBGmWwLIb0N_v5s354lo4JTAROCXcOKjIL3CORH0GuOcdR1clLGvi42LmGSAFvA'