Introduction
This document is a specification for the technical integration with kjernejournal portal. Kjernejournal is implemented as an embedded browser, which is opened in the EHR system.
Purpose
The purpose of this document is to clarify the premises for the technical organisation of the EHR vendor for integration with kjernejournal, including detailed solution design, clarifications, user stories and the test descriptions.
Target audience
The target audience for this document are technical resources and project management with a responsibility for implementing an integration with kjernejournal.
Limitations
This document is limited to the services and needs that support integration.
This document do not include
establishment of operating routines
establishment of monitoring routines
Solution description
Portal integration with kjernejournal consists mainly of two parts:
The kjernejournal icon
The kjernejournal portal
The kjernejournal icon is placed on the patient page of the EHR system. When the user opens a new patient, the EHR system makes an API call to kjernejournal’s health indicator API, which indicates if the patient is registered in kjernejournal, and if any critical information is registered. The EHR system changes the appearance of the kjernejournal icon according to the response from the health indicator API, to signify to the user the level of information that exists in kjernejournal on the patient.
If the user chooses to open kjernejournal, by clicking on the kjernejournal icon, the EHR system opens the kjernejournal portal in an embedded browser, showing the patient in kjernejournal.
Workflow
Main functional steps
The health professional logs into the EHR system.
The user opens the patient in the EHR system.
The EHR system calls the kjernejournal Health indicator service with the patients national identity. The response has the patients critical info status and a ticket.
The user chooses to open kjernejournal by clicking on the KJ icon.
The EHR system opens the kjernejournal portal in an integrated browser window. The URL used to open kjernejournal contains the ticket that identifies the patient.
The patient’s kjernejournal is shown in the integrated browser.
Kjernejournal icon
The kjernejournal icon should be placed on a logical, and visible, place on the patient page in the EHR system. There are five variants that corresponds to the different statuses returned from the health indicator API.
Status value | Icon | Description |
---|---|---|
0 | Error (the icon should not be clickable, as it is not possible to open kjernejournal on a patient with this status) | |
1 | The patient is not registered in kjernejournal (the icon should not be clickable, as it is not possible to open kjernejournal on a patient with this status) | |
2 | The patient is registered in kjernejournal | |
3 | The patient has filled in health information (illness history, communication issues) in kjernejournal | |
4 | Attention: The patient has critical information in kjernejournal |
(The icons are available in SVG format. See attachements.)
The API response also contains a textual description of the status, which should be used as a tooltip on the icon.
In the case of an error, the icon for status value 0 should be used. If the error originated from kjernejournal, the “brukermelding” (user message) from the response should be used as a tooltip. If the error did not originate from kjernejournal, the tooltip should be a general error message: “Feil i kontakten med kjernejournal”.
Authentication
For the API call, the EHR system must be authenticated as a system on an organization level. This is done by using HelseID, the national authentication solution for the healthcare sector.
When the user uses the kjernejournal portal, they must be authenticated on a personal level. This can either be done by kjernejournal when the user opens a patient, or it can be SSO with the EHR system, if the user is already authenticated on the required security level. In the SSO scenario, HelseID is used for federation.
User authentication
Using kjernejournal
In the non-SSO scenario, the user must log on to kjernejournal the first time they open a patient. The user will be redirected to kjernejournal’s login page, which supports authenticating users with ID cards from Buypass and Commfides.
The user can choose identity provider by clicking on the tabs above the identification dialog. Which tab is active when the page is loaded is determined by the following:
idprov parameter: If the EHR system sent an idprov parameter in the request with a valid value (buypassjavafri or commfidesjavafri), then this tab will be selected.
Cookie: If the URL does not contain the idprov parameter, or the idprov parameter has an invalid value, the last selected tab will be retrieved from a cookie and used again.
Fallback: If the URL does not contain the idprov parameter, or the idprov parameter has an invalid value and the cookie with previous selections is not set, then buypass will be selected.
Please note that the two tabs that uses Java applets (“… med java”) exists solely for legacy reasons, and are not to be used in new installations. The corresponding options without Java (“… javafri”) should be used instead.
Using HelseID
If the user is already authenticated with HelseID on the required security level (the SSO scenario), or if it is desirable to use other authentication methods (e.g. BankID), the user authentication can be handled by HelseID. The EHR system must be configured to use a special parameter in the URL, and then kjernejournal will redirect the user to HelseID for authentication.
Integration description
Health indicator service
The Health indicator REST service returns the patients status in kjernejournal.
It’s a POST
to /v1/helseindikator
, with a JSON body (Content-type: application/json
) with the following input:
Input:
Field | Location | Required | Description |
---|---|---|---|
fnr | Body | Yes | Patient identifier (Norwegian national identity number). |
samtykke | Body | No | Consent for opening the patient’s kjernejournal (used if the ticket from the response is later used to access the patient’s kjernejournal). Can be one of the following values:
|
Authorization | HTTP Header | Yes | A token from HelseID sent as a bearer token. |
X-EPJ-System | HTTP Header | Yes | Which EHR system, and which version, the request originated from. |
Output in case of successful request:
Field | Location | Description |
---|---|---|
status | Body | One of the following values:
Is to be used to determine what icon should be shown to the user. |
sistEndretKritiskInfoDato | Body | Timestamp for last change in information for patients with status 4. Only present if the status is 4. |
returTekst | Body | Description of the response status. Is to be used in the tooltip of the icon. |
ticket | Body | An opaque string which represents:
Is to be used in the subsequent opening of the portal. Only present if the status is 2 or higher. |
X-EVENT-ID | Header | The ID of the request in kjernejournal. Can be used for debugging and correlation between the systems. |
Output in case of failed request:
Field | Location | Description |
---|---|---|
status | Body | The HTTP status of the response. |
utviklermelding | Body | A developer friendly description of the error. |
brukermelding | Body | A user friendly description of the error. Is to be used in the tooltip of the error icon. |
feilkode | Body | An error code which is associated with the error condition. See list at the bottom. |
X-EVENT-ID | Header | The ID of the request in kjernejournal. Can be used for debugging and correlation between the systems. |
All API responses from kjernejournal may have an arbitrary gibberish extra field. This is to ensure that consumers can handle new fields in the response.
The response status decides which kjernejournal icon is to be displayed, as described in the “Kjernejournal icon” section. If the patient has status 0 or 1, or the request failed, the icon should not be clickable, as it is not possible to open kjernejournal on the patient.
The ticket in the response represents the organization, the patient, and optionally the consent given to access the patient’s kjernejournal, and is used to tie the health indicator request to the portal request. So this must be stored by the EHR system, and used when the user opens the kjernejournal portal.
The consent parameter in the health indicator request MUST NOT be specified if the EHR system only have portal integration with kjernejournal, as the user will be asked to specify consent when the patient’s kjernejournal is opened in the portal. The consent parameter is only to be used if the EHR system has both API and portal integration, and is used to reuse the consent from an API request in the portal.
The API lookup MUST NOT block the opening of the patient in the EHR. In the case of a timeout or slow response from KJ, the user MUST be able to use the EHR system normally.
Request example:
POST /v1/helseindikator/ HTTP/1.1 Host: api.kjernejournal.no:8000 Content-Type: application/json Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkE4...u_UjgeTxzxI2g X-EPJ-System: ACME EHR system versjon 42.01 {"fnr":"18048201209"} |
Successful response example:
HTTP/1.1 200 OK Cache-Control: no-cache, must-revalidate, private, s-maxage=0 Pragma: no-cache X-EVENT-ID: Id-513f826053dfa2c6dc91b8dsa Content-Type: application/json { "returTekst": "OBS: Kritisk informasjon i kjernejournal", "sistEndretKritiskInfoDato": "2017-11-29T16:35:19.003Z", "status": 4, "ticket": "ca2gveFcW%2BdZqO2Fx7EG773Lh0TUvO2gtz45gQCbbUrKpXBJf8yS3ROacFn%2Bq" } |
Failed response example:
HTTP/1.1 403 FORBIDDEN Cache-Control: no-cache, must-revalidate, private, s-maxage=0 Pragma: no-cache X-EVENT-ID: Id-543f826025992c6dc91b8dsa Content-Type: application/json { "status" : 403, "utviklermelding" : "Organisasjonsnummeret finnes ikke i kjernejournal", "brukermelding" : "Virksomheten har ikke tilgang til kjernejournal (KJF-000226)", "feilkode" : "KJF-000226" } |
Security
The Health indicator service requires a bearer token, which must be a client access token from HelseID (that authenticates the organization, not the user), so the EHR must retrieve a token from HelseID before calling kjernejournal.
Kjernejournal will not accept tokens with more than one audience, or which was authenticated with a client secret, so when the EHR system requests an access token from HelseID, it must:
Ask specifically for the scope
nhn:kjernejournal/api
Use a signed JWT as client assertion (
urn:ietf:params:oauth:client-assertion-type:jwt-bearer
), signed with either an enterprise certificate or RSA key
As the volume of requests against the health indicator service quickly becomes quite high, the EHR system SHOULD re-use a token throughout its validity period, to reduce the amount of requests against HelseID. But it is vital that the token always represents the correct organization of the user, so if the EHR system supports multiple organizations, the token MUST NOT be shared between users of different organizations.
See helseid.no and dokumentasjon.helseid.no for more information about integrating with HelseID.
The portal
Get patient
If the Health indicator service returns a status with value 2 or higher, the user can open kjernejournal for the patient by clicking on the kjernejournal icon. This is done by the EHR system opening the “get patient url” in the embedded browser.
In order to connect the opening of the portal with the earlier health indicator request, the ticket from the health indicator response must be supplied as a parameter. This will ensure that the request is tied to the correct organization, and the correct patient is opened.
The service is available at /hpp-webapp/hentpasient
and it takes the following parameters:
Parameter | Location | Required | Description |
---|---|---|---|
ticket | URL | yes | URL encoded ticket from the health indicator service. |
idprov | URL | no | The preferred ID provider. |
X-EPJ-System | HTTP Header or URL | yes | Which EHR system, and which version, the request originated from. |
As web based EHR systems aren’t able to add HTTP headers to the portal requests, they MAY send the X-EPJ-System parameter in the URL instead
Example with ticket only
https://KJERNEJOURNAL_URL/hpp-webapp/hentpasient?ticket=PmDvQLzdcnbkiYSmk8bym5iDRWPuUlkpsvMyxEXAiVkvjHzwItVizUXFeq7bQDgD
Hold session
The kjernejournal session should be “synchronized” with the usage of the EHR system, and this is done through the hold session mechanism. The kjernejournal session will last up to 12 hours, but the user will be logged out after 19 minutes of inactivity, so the EHR system must keep the kjernejournal session alive as long as the user is active in the EHR system. Active in the EHR system means general activity of the user in the EHR system, not limited to kjernejournal.
There are several reasons this is important for the user experience. Correct implementation of hold session will:
avoid the need for repeated logons (not applicable with SSO)
avoid the need for the user to repeatedly enter consent to open a patient’s kjernejournal, or unlock blocked tabs, when returning to a earlier patient
avoid loss of information, if the user has entered information without saving it in the kjernejournal portal
Keeping the session alive is done by opening a special web page in the integrated browser, in the background, at a fixed interval (as long as the user is active). This should be hidden from the user, but the same browser context/environment must be used (so that it shares the same session cookies). The interval should be configurable, but default to 15 minutes.
The hold session service is available at /hpp-webapp/holdsesjon
, and expects nothing more than a simple GET
.
Session timer start
The EHR must start the timer:
When the kjernejournal icon is pressed for the first time in the EHR
OR
When the browser is redirected from the login application to the original URL that was opened after a click on the kjernejournal icon. This provides a more accurate calculation of when the user's session started with the kjernejournal, but may be somewhat more complicated to implement.
Session timer stop
If the session is no longer valid, e.g. after 12 hours, or a manual logoff, the hold session request will end in a redirect. If that is to happen, then the hold session timer should stop. This can be implemented by checking the final page of the browser - if it is not the same as the one originally opened (/hpp-webapp/holdsesjon
), then the session is no longer valid.
If the EHR system calls the Logout service (see below), the timer must also be terminated.
Session timer reset
If the timer has previously been terminated and the user opens kjernejournal again (see conditions under “Session timer start”), the EHR system should start the timer again.
Logout
The EHR system should terminate the kjernejournal session when the user logs off the EHR system, switches to another user, or shuts down the EHR system. This is done by opening the URL /hpp-webapp/logout
in the embedded browser in the background. This will terminate the session on the kjernejournal side.
Additionally the EHR system MUST destroy all session cookies in the embedded browser, regardless of their domain.
Patient context
It is vital that there is no room for confusion about which patient is opened in the kjernejournal portal at any time, so the EHR system must take great care to ensure that the patient opened in kjernejournal is always the same as the one opened in the EHR. This means that if the user changes patients in the EHR, the kjernejournal browser must be closed or hidden.
If the EHR system reuses the browser instance between patients, it is important to clear the screen between patients, e.g. by loading about:blank
, so that slow loading or network problems don’t show the old patient. Preferably a new browser instance/window is used for every patient (but it must share the same context/environment, so that session cookies are shared between them).
To summarize: The embedded browser MUST NOT, under any circumstances, show the the wrong/old patient in kjernejournal.
Browser requirements
Kjernejournal supports, and are testet in, Chromium based browsers. Therefore the browser component must be based on Chromium.
There is functionality for downloading PDFs in the kjernejournal portal, and the embedded browser must therefore support showing, printing and saving these. But if a user opens a PDF, it should not be saved to disk permanently by default. Either it should be opened in memory, or the temporary location should be cleared out when the EHR system shuts down.
Additionally, there are some requirements to make kjernejournal more closely integrated. When using the kjernejournal portal:
there must not be an address field visible
there must not be any navigation buttons visible
there must not be any right click functionality
Ctrl + A, Ctrl + C, Ctrl + V must work as expected
And it is important to remember that browsers are security critical software, and should be kept up to date.
Ping service
Kjernejournal also exposes a simple ping service, which can be used to test system authentication without opening a patient. It is not required to make use of this service, but it can be useful to use it as a method to verify connectivity and that the organization has been granted access to kjernejournal. This is usually implemented as a “test connection” button in the settings, and the error message here should be as detailed as possible (including stack trace or similar), as it is used by technical personnel.
It is a simple GET
to /v1/ping
. The authentication and error responses are identical to the health indicator service.
Input:
Field | Location | Required | Description |
---|---|---|---|
Authorization | HTTP Header | Yes | A token from HelseID sent as a bearer token. |
X-EPJ-System | HTTP Header | Yes | Which EHR system, and which version, the request originated from. |
Output in case of successful request:
Field | Location | Description |
---|---|---|
Pong | Body | Timestamp |
X-EVENT-ID | Header | The ID of the request in kjernejournal. Can be used for debugging and correlation between the systems. |
Request example
GET /v1/ping/ HTTP/1.1 Host: api.kjernejournal.no:8000 Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkE4...u_UjgeTxzxI2g X-EPJ-System: ACME EHR system versjon 42.01 |
Response example
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache X-EVENT-ID: Id-93f2826025992c6dc91b8cfd Content-Type: application/json { "pong" : "2021-04-23T16:15:15.973Z", "imperdieteleifendcommodo" : "Ukjent felt skal støttes av konsument" } |
All API responses from kjernejournal may have an arbitrary gibberish extra field. This is to ensure that consumers can handle new fields in the response.
Activation
The kjernejournal integration must be placed behind a toggle function, so that it can be (de)activated on an installation basis. It should also be possible to choose which user group or users that have access to the kjernejournal integration.
Endpoints
Service | Environment | URL |
---|---|---|
Portal | Test | https://st2.kjernejournal-test.no/ |
API | Test | https://api.st2.kjernejournal-test.no:8000/ |
Portal | Prod | https://kjernejournal.no/ |
API | Prod | https://api.kjernejournal.no:8000/ |
Related error codes
Errors that can be returned from the API (not all are applicable for the health indicator API):
Error codes and messages - Application errors
Errors that can happen when a user logs in to the portal:
Error codes and messages - Authentication errors