diff --git a/fhir-info-gateway/docker-compose-smart_keyclock.yml b/fhir-info-gateway/docker-compose-smart_keyclock.yml new file mode 100644 index 00000000..04cd3548 --- /dev/null +++ b/fhir-info-gateway/docker-compose-smart_keyclock.yml @@ -0,0 +1,15 @@ +version: "3.9" + +services: + smart-config: + image: jembi/keycloak-config + networks: + - fhir-info-gateway_default + environment: + KEYCLOAK_BASE_URL: ${KC_API_URL} + KEYCLOAK_USER: ${KC_ADMIN_USER} + KEYCLOAK_PASSWORD: ${KC_ADMIN_PASSWORD} + KEYCLOAK_REALM: ${KC_REALM_NAME} +networks: + fhir-info-gateway_default: + diff --git a/fhir-info-gateway/keycloak-config.json b/fhir-info-gateway/keycloak-config.json new file mode 100644 index 00000000..36e154bb --- /dev/null +++ b/fhir-info-gateway/keycloak-config.json @@ -0,0 +1,732 @@ +{ + "keycloak": { + "serverUrl": "${KEYCLOAK_BASE_URL}", + "adminUser": "${KEYCLOAK_USER}", + "adminPassword": "${KEYCLOAK_PASSWORD}", + "adminClientId": "admin-cli", + "realms": { + "${KEYCLOAK_REALM}": { + "enabled": true, + "clientScopes": { + "fhirUser": { + "protocol": "openid-connect", + "description": "Permission to retrieve current logged-in user", + "attributes": { + "consent.screen.text": "Permission to retrieve current logged-in user" + }, + "mappers": { + "fhirUser Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-patient-prefix-usermodel-attribute-mapper", + "config": { + "user.attribute": "resourceId", + "claim.name": "fhirUser", + "jsonType.label": "String", + "id.token.claim": "true", + "access.token.claim": "false", + "userinfo.token.claim": "true" + } + } + } + }, + "launch/patient": { + "protocol": "openid-connect", + "description": "Used by clients to request a patient-scoped access token", + "attributes": { + "display.on.consent.screen": "false" + }, + "mappers": { + "Patient ID Claim Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-usermodel-attribute-mapper", + "config": { + "user.attribute": "resourceId", + "claim.name": "patient_id", + "jsonType.label": "String", + "id.token.claim": "false", + "access.token.claim": "true", + "userinfo.token.claim": "false" + } + }, + "Patient ID Token Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-usersessionmodel-note-mapper", + "config": { + "user.session.note": "patient_id", + "claim.name": "patient", + "jsonType.label": "String", + "id.token.claim": "false", + "access.token.claim": "false", + "access.tokenResponse.claim": "true" + } + }, + "Group Membership Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-group-membership-mapper", + "config": { + "claim.name": "group", + "full.path": "false", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + } + } + }, + "online_access": { + "protocol": "openid-connect", + "description": "Request a refresh_token that can be used to obtain a new access token to replace an expired one, and that will be usable for as long as the end-user remains online.", + "attributes": { + "consent.screen.text": "Retain access while you are online" + } + }, + "patient/*.read": { + "protocol": "openid-connect", + "description": "Read access to all data", + "attributes": { + "consent.screen.text": "Read access to all data for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/AllergyIntolerance.read": { + "protocol": "openid-connect", + "description": "Read access to AllergyIntolerance", + "attributes": { + "consent.screen.text": "Read access to AllergyIntolerance for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/CarePlan.read": { + "protocol": "openid-connect", + "description": "Read access to CarePlan", + "attributes": { + "consent.screen.text": "Read access to CarePlan for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/CareTeam.read": { + "protocol": "openid-connect", + "description": "Read access to CareTeam", + "attributes": { + "consent.screen.text": "Read access to CareTeam for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Condition.read": { + "protocol": "openid-connect", + "description": "Read access to Condition", + "attributes": { + "consent.screen.text": "Read access to Condition for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Device.read": { + "protocol": "openid-connect", + "description": "Read access to Device", + "attributes": { + "consent.screen.text": "Read access to Device for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/DiagnosticReport.read": { + "protocol": "openid-connect", + "description": "Read access to DiagnosticReport", + "attributes": { + "consent.screen.text": "Read access to DiagnosticReport for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/DocumentReference.read": { + "protocol": "openid-connect", + "description": "Read access to DocumentReference", + "attributes": { + "consent.screen.text": "Read access to DocumentReference for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Encounter.read": { + "protocol": "openid-connect", + "description": "Read access to Encounter", + "attributes": { + "consent.screen.text": "Read access to Encounter for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/ExplanationOfBenefit.read": { + "protocol": "openid-connect", + "description": "Read access to ExplanationOfBenefit", + "attributes": { + "consent.screen.text": "Read access to ExplanationOfBenefit for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Goal.read": { + "protocol": "openid-connect", + "description": "Read access to Goal", + "attributes": { + "consent.screen.text": "Read access to Goal for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Immunization.read": { + "protocol": "openid-connect", + "description": "Read access to Immunization", + "attributes": { + "consent.screen.text": "Read access to Immunization for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Location.read": { + "protocol": "openid-connect", + "description": "Read access to Location", + "attributes": { + "consent.screen.text": "Read access to Location for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Medication.read": { + "protocol": "openid-connect", + "description": "Read access to Medication", + "attributes": { + "consent.screen.text": "Read access to Medication for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/MedicationDispense.read": { + "protocol": "openid-connect", + "description": "Read access to MedicationDispense", + "attributes": { + "consent.screen.text": "Read access to MedicationDispense for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/MedicationRequest.read": { + "protocol": "openid-connect", + "description": "Read access to MedicationRequest", + "attributes": { + "consent.screen.text": "Read access to MedicationRequest for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Observation.read": { + "protocol": "openid-connect", + "description": "Read access to Observation", + "attributes": { + "consent.screen.text": "Read access to Observation for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Organization.read": { + "protocol": "openid-connect", + "description": "Read access to Organization", + "attributes": { + "consent.screen.text": "Read access to Organization for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Patient.read": { + "protocol": "openid-connect", + "description": "Read access to Patient", + "attributes": { + "consent.screen.text": "Read access to Patient for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Practitioner.read": { + "protocol": "openid-connect", + "description": "Read access to Practitioner", + "attributes": { + "consent.screen.text": "Read access to Practitioner for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/PractitionerRole.read": { + "protocol": "openid-connect", + "description": "Read access to PractitionerRole", + "attributes": { + "consent.screen.text": "Read access to PractitionerRole for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Procedure.read": { + "protocol": "openid-connect", + "description": "Read access to Procedure", + "attributes": { + "consent.screen.text": "Read access to Procedure for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/Provenance.read": { + "protocol": "openid-connect", + "description": "Read access to Provenance", + "attributes": { + "consent.screen.text": "Read access to Provenance for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "patient/RelatedPerson.read": { + "protocol": "openid-connect", + "description": "Read access to RelatedPerson", + "attributes": { + "consent.screen.text": "Read access to RelatedPerson for the patient" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "user/Device.read": { + "protocol": "openid-connect", + "description": "Read access to Device", + "attributes": { + "consent.screen.text": "Read access to all Device" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "user/Organization.read": { + "protocol": "openid-connect", + "description": "Read access to Organization", + "attributes": { + "consent.screen.text": "Read access to all Organization" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "user/Practitioner.read": { + "protocol": "openid-connect", + "description": "Read access to Practitioner", + "attributes": { + "consent.screen.text": "Read access to all Practitioner" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + }, + "user/PractitionerRole.read": { + "protocol": "openid-connect", + "description": "Read access to PractitionerRole", + "attributes": { + "consent.screen.text": "Read access to all PractitionerRole" + }, + "mappers": { + "Audience Mapper": { + "protocol": "openid-connect", + "protocolmapper": "oidc-audience-mapper", + "config": { + "included.custom.audience": "${FHIR_BASE_URL}", + "access.token.claim": "true" + } + } + } + } + }, + "defaultDefaultClientScopes": [], + "defaultOptionalClientScopes": [ + "fhirUser", + "launch/patient", + "offline_access", + "online_access", + "profile", + "patient/*.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/ExplanationOfBenefit.read", + "patient/Goal.read", + "patient/Immunization.read", + "patient/Location.read", + "patient/Medication.read", + "patient/MedicationDispense.read", + "patient/MedicationRequest.read", + "patient/Observation.read", + "patient/Organization.read", + "patient/Patient.read", + "patient/Practitioner.read", + "patient/PractitionerRole.read", + "patient/Procedure.read", + "patient/Provenance.read", + "patient/RelatedPerson.read", + "user/Device.read", + "user/Organization.read", + "user/Practitioner.read", + "user/PractitionerRole.read" + ], + "clients": { + "inferno": { + "consentRequired": true, + "publicClient": true, + "bearerOnly": false, + "enableDirectAccess": false, + "rootURL": "http://localhost:4567/inferno", + "redirectURIs": [ + "http://localhost:4567/inferno/*", + "http://localhost:4567/inferno2/*" + ], + "adminURL": "http://localhost:4567/inferno", + "webOrigins": ["http://localhost:4567"], + "defaultClientScopes": ["launch/patient"], + "optionalClientScopes": [ + "fhirUser", + "offline_access", + "online_access", + "profile", + "patient/*.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/ExplanationOfBenefit.read", + "patient/Goal.read", + "patient/Immunization.read", + "patient/Location.read", + "patient/Medication.read", + "patient/MedicationDispense.read", + "patient/MedicationRequest.read", + "patient/Observation.read", + "patient/Organization.read", + "patient/Patient.read", + "patient/Practitioner.read", + "patient/PractitionerRole.read", + "patient/Procedure.read", + "patient/Provenance.read", + "patient/RelatedPerson.read", + "user/Device.read", + "user/Organization.read", + "user/Practitioner.read", + "user/PractitionerRole.read" + ] + } + }, + "authenticationFlows": { + "SMART App Launch": { + "description": "browser based authentication", + "providerId": "basic-flow", + "builtIn": false, + "authenticationExecutions": { + "SMART Login": { + "requirement": "ALTERNATIVE", + "userSetupAllowed": false, + "authenticatorFlow": true, + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "authenticationExecutions": { + "Audience Validation": { + "authenticator": "audience-validator", + "requirement": "DISABLED", + "priority": 10, + "authenticatorFlow": false, + "configAlias": "localhost", + "config": { + "audiences": "${FHIR_BASE_URL}" + } + }, + "Username Password Form": { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 20, + "authenticatorFlow": false + }, + "Patient Selection Authenticator": { + "authenticator": "auth-select-patient", + "requirement": "REQUIRED", + "priority": 30, + "authenticatorFlow": false, + "configAlias": "host.docker", + "config": { + "internalFhirUrl": "${FHIR_BASE_URL}" + } + } + } + } + } + } + }, + "browserFlow": "SMART App Launch", + "groups": { + "fhirUser": {} + }, + "defaultGroups": ["fhirUser"], + "users": { + "fhiruser": { + "enabled": true, + "password": "change-password", + "passwordTemporary": false, + "attributes": { + "resourceId": ["Patient1"] + }, + "groups": ["fhirUser"] + } + }, + "eventsConfig": { + "saveLoginEvents": true, + "expiration": 23328000, + "types": [ + "FEDERATED_IDENTITY_LINK", + "LOGOUT", + "LOGIN_ERROR", + "IDENTITY_PROVIDER_LINK_ACCOUNT", + "REFRESH_TOKEN", + "FEDERATED_IDENTITY_LINK_ERROR", + "IDENTITY_PROVIDER_POST_LOGIN", + "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", + "CODE_TO_TOKEN_ERROR", + "IDENTITY_PROVIDER_FIRST_LOGIN", + "REFRESH_TOKEN_ERROR", + "IDENTITY_PROVIDER_POST_LOGIN_ERROR", + "LOGOUT_ERROR", + "CODE_TO_TOKEN", + "LOGIN", + "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" + ], + "saveAdminEvents": true + } + } + } + } +} diff --git a/fhir-info-gateway/package-metadata.json b/fhir-info-gateway/package-metadata.json index bfb968be..87f3e40c 100644 --- a/fhir-info-gateway/package-metadata.json +++ b/fhir-info-gateway/package-metadata.json @@ -6,13 +6,15 @@ "version": "0.0.1", "dependencies": ["mpi-mediator"], "environmentVariables": { - "MPI_PROXY_URL": "http://localhost:5001", + "MPI_PROXY_URL": "http://openhim-core:5001/fhir", "ACCESS_CHECKER": "patient", "RUN_MODE": "DEV", - "FHIR_INFO_GATEWAY_IMAGE": "jembi/fhir-info-gateway:v0.0.1", + "FHIR_INFO_GATEWAY_IMAGE": "jembi/fhir-info-gateway:v0.0.2", "BACKEND_TYPE": "HAPI", "KC_API_URL": "http://identity-access-manager-keycloak:9088", "KC_REALM_NAME": "platform-realm", + "KC_ADMIN_PASSWORD": "dev_password_only", + "KC_ADMIN_USEERNAME": "admin", "FHIR_INFO_GATEWAY_INSTANCES": "1", "FHIR_INFO_GATEWAY_MAX_REPLICAS_PER_NODE": "1", "FHIR_INFO_GATEWAY_CPU_LIMIT": "0",