Skip to main content

OpenID Connect

This document contains information regarding usage of OpenID Connect as authentication and authorization method for Bliksund EWA. The document will only cover the things that are specific to EWA; for basic information regarding the OpenID Connect identity layer and specs go to OpenID Connect.

Implementation in EWA

Flow and token usage

When configured to use OpenID Connect; both the EWA Client and Insight use the Authorization Code Flow.
After successful login the Client will use the Access Token for any requests towards the ClientAPI, and Insight will use the ID Token.

Library usage

OpenID Connect is implemented in EWA using the following well-known libraries:

Token requirements

In order to comply with security requirements in the Norwegian health sector we require the token to contain additional claim values that can be used to read the user's name, national id/social security number, organizations and departments.

The claim name for each of these claims is configurable in the EWA system using the Migration and Seeding tool.

Token Claim Requirements:

  • 1 claim containing the user ID
  • 1 claim containing the user's national id/social security number
  • 1 claim containing the full name of the user - Recommended name value format: "{First Name} {Surname}"
  • At least 1 claim with the user's organization id
    • Can be more if the user is employed in several organizations, is employed in several departments, or has several roles within each department.
    • We recommend using alphanumeric IDs which uniquely identifies the organization rather than names. In Norway that could f.ex. be the organization ID from Brønnøysundregistrene.
  • At least 1 claim with the user's department id
    • Can be more if the user is employed in several departments or has more than one role in each department.
    • We recommend using alphanumeric IDs which uniquely identifies the organization rather than names. In Norway this could f.ex. be RESH-ID.
  • At least 1 claim with the user's role
    • Can be more if the user is employed in multiple places or if the user has more than one role in the system.

Organizations, departments and roles

Organizations, departments and roles claims are required in the tokens in order to filter data based on the user's roles within different organization and departments without an internal user database or access to an external user database.

Index-based organization, department, role hierarchy

The system supports that a user has multiple employment affiliations, or combinations of organizations, departments and roles. In order to create a map of exactly which department and organization a role comes from we can use the indexes, or item position, for claim values in each list.

The idea behind mapping the lists based on index is simple: We take each of the organizations, departments and roles lists and put them next to each other, then we read each row as a specific "organization - department -role" combination.

Index-based hierarchy token requirement

The number of claim values in each of the organizations, departments and roles lists MUST be the same.
This means that if a user has two roles in the same department, then the token must contain duplicate values of the organization the department is in, and duplicate values of the department.

If the number of claim values in the organizations, departments and roles lists are not the same; the system will use a fallback solution which is outlined below.

Index-based hierarchy examples

In order to demonstrate this index-based structure, and provide examples we must first define some example users:

USER 1: Sonja Dahl

UserIdUser SSNName
sonja.dahl@bliksundhf.no28096900254Sonja Dahl
OrganizationDepartmentRole
BliksundAmbulancestation_1Journalregistration

USER 2: Mykke Plasme

UserIdUser SSNName
mykke.plasme@bliksundhf.no18118500284Mykke Plasme
OrganizationDepartmentRole
BliksundAmbulancestation_1Journalregistration
BliksundAmbulancestation_1Clinical Reporting

USER 3: Borg Thale

UserIdUser SSNName
borg.thale@bliksundhf.no14076800236Borg Thale
OrganizationDepartmentRole
BliksundAmbulancestation_1Journalregistration
BliksundPediatricLabClinical Reporting
OtherOrgPediatricLabPatient Complaint Handling

Correct index-based token value examples

Note: The examples below only contains values relevant to the demonstration. Real tokens will contain additional claims.

Example 1: Sonja Dahl

Token:

{
"userId": "sonja.dahl@bliksundhf.no",
"name": "Sonja Dahl",
"userSSN": "00000000000",
"organizations": [
"Bliksund"
],
"departments": [
"Ambulancestation_1"
],
"roles": [
"Journalregistration"
]
}

Token above only contains 1 value each for organizations, departments and roles.


Example 2: Mykke Plasme

Token:

{
"userId": "mykke.plasme@bliksundhf.no",
"name": "Mykke Plasme",
"userSSN": "00000000000",
"organizations": [
"Bliksund",
"Bliksund"
],
"departments": [
"Ambulancestation_1",
"Ambulancestation_1"
],
"roles": [
"Journalregistration",
"Clinical Reporting"
]
}

In the token above there are duplicate values in both the organizations and departments. These duplicates exist in order for the system to recognize that Mykke has both the Journalregistration and Clinical Reporting roles from his employment in Bliksund - Ambulancestation_1.

Internally in EWA this user's organization, department, role list will be parsed as such:

[
{
"OrganizationId": "Bliksund",
"Departments": [
{
"DepartmentId": "Ambulancestation_1",
"Roles": [
"Journalreporting",
"Clinical Reporting"
]
}
]
}
]

List contains 1 organization with id "Bliksund", this organization contains 1 department with id "Ambulancestation_1", and this department contains 2 roles; "Journalreporting" and "Clinical Reporting"


Example 3: Borg Thale

Token:

{
"userId": "borg.thale@bliksundhf.no",
"name": "Borg Thale",
"userSSN": "00000000000",
"organizations": [
"Bliksund",
"Bliksund",
"OtherOrg"
],
"departments": [
"Ambulancestation_1",
"PediatricLab",
"PediatricLab"
],
"roles": [
"Journalregistration",
"Clinical Reporting",
"Patient Complaint Handling"
]
}

Another example of how duplicates are used to create a strong connection to the exact employment affiliation of where the different roles come from:

  • Role 0 (Journalregistration) comes from Department 0 (Ambulancestation_1) which is in Organization 0 (Bliksund)
  • Role 1 (Clinical Reporting) comes from Department 1 (PediatricLab) which is in Organization 1 (Bliksund)
  • Role 2 (Patient Complaint Handling) comes from Department 2 (PediatricLab) which is in Organization 2 (OtherOrg)

Internally in EWA this user's organization, department, role list will be parsed as such:

[
{
"OrganizationId": "Bliksund",
"Departments": [
{
"DepartmentId": "Ambulancestation_1",
"Roles": [
"Journalreporting"
]
},
{
"DepartmentId": "PediatricLab",
"Roles": [
"Clinical Reporting"
]
}
]
},
{
"OrganizationId": "OtherOrg",
"Departments": [
{
"DepartmentId": "PediatricLab",
"Roles": [
"Patient Complaint Handling"
]
}
]
}
]

List contains 2 organizations:

  1. OrganizationId = Bliksund; organization contains 2 departments:
    1. DepartmentId = Ambulancestation_1; department contains 1 role:
      1. Journalreporting
    2. DepartmentId = PediatricLab; department contains 1 role:
      1. Clinical Reporting
  2. OrganizationId = OtherOrg; organization contains 1 department:
    1. DepartmentId = PediatricLab; department contains 1 role:
      1. Patient Complaint Handling

Non-index fallback

When the number of organizations, departments and roles claim values are not the same the system will fall back on a much more fuzzy mapping. Since we are no longer able to accurately tell which department belongs in which organization, and which role comes from which department we will do the following:

  • Add all roles to a list
  • Add all departments to a list
    • Go through each department and add the "all roles" list to it
  • Add all organizations to a list
    • Go through each organization and add the "all departments" list to it

Fallback example using Borg Thale

Token:

{
"userId": "borg.thale@bliksundhf.no",
"name": "Borg Thale",
"userSSN": "00000000000",
"organizations": [
"Bliksund",
"OtherOrg"
],
"departments": [
"Ambulancestation_1",
"PediatricLab"
],
"roles": [
"Journalregistration",
"Patient Complaint Handling",
"Clinical Reporting"
]
}

This token has 3 roles, but only 2 departments and 2 organizations so we need to use the fallback solution.

Internally in EWA this token's organization, department, role list will be parsed as

[
{
"OrganizationId": "Bliksund",
"Departments": [
{
"DepartmentId": "Ambulancestation_1",
"Roles": [
"Journalreporting",
"Patient Complaint Handling",
"Clinical Reporting"
]
},
{
"DepartmentId": "PediatricLab",
"Roles": [
"Journalreporting",
"Patient Complaint Handling",
"Clinical Reporting"
]
}
]
},
{
"OrganizationId": "OtherOrg",
"Departments": [
{
"DepartmentId": "Ambulancestation_1",
"Roles": [
"Journalreporting",
"Patient Complaint Handling",
"Clinical Reporting"
]
},
{
"DepartmentId": "PediatricLab",
"Roles": [
"Journalreporting",
"Patient Complaint Handling",
"Clinical Reporting"
]
}
]
}
]

List contains 2 organizations:

  1. OrganizationId = Bliksund; organization contains 2 departments:
    1. DepartmentId = Ambulancestation_1; department contains 3 roles:
      1. Journalreporting
      2. Patient Complaint Handling
      3. Clinical Reporting
    2. DepartmentId = PediatricLab; department contains 3 roles:
      1. Journalreporting
      2. Patient Complaint Handling
      3. Clinical Reporting
  2. OrganizationId = OtherOrg; organization contains 2 departments:
    1. DepartmentId = Ambulancestation_1; department contains 3 roles:
      1. Journalreporting
      2. Patient Complaint Handling
      3. Clinical Reporting
    2. DepartmentId = PediatricLab; department contains 3 roles:
      1. Journalreporting
      2. Patient Complaint Handling
      3. Clinical Reporting