0 Abonnés · 17 Publications

Articles et questions concernant l'authentification OAuth2.

Annonce Adeline Icard · Avr 24, 2025

InterSystems IRIS 2025.2.0 introduit plusieurs fonctionnalités pour améliorer l'expérience utilisateur lors de la configuration d'OAuth2.

- OAuth2 est désormais un type d'authentification natif et peut être facilement activé pour vos services et applications web. Auparavant, OAuth2 était un type d'authentification déléguée.

- Vous pouvez désormais créer des serveurs de ressources avec la nouvelle classe OAuth2.ResourceServer, qui simplifie considérablement la configuration des serveurs de ressources. Auparavant, les serveurs de ressources étaient des instances d'OAuth2.Client.

0
0 23
Article Lorenzo Scalese · Avr 16, 2025 7m read

Qu'est-ce que JWT ??

JWT (JSON Web Token) est un standard ouvert (RFC 7519) qui offre une méthode légère, compacte et autonome pour transmettre en toute sécurité des renseignements entre deux parties. Il est couramment utilisé dans les applications web pour l'authentification, l'autorisation et l'échange d'informations.

Un JWT est généralement composé de trois parties:

1. En-tête JOSE (JSON Object Signing and Encryption)
2. Payload
3. Signature

Ces parties sont encodées au format Base64Url et concaténées avec des points (.) qui les séparent.

Structure d'un JWT

En-tête

{ "alg": "HS256", "typ": "JWT"}

Payload

{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}

Signature:
La signature permet de vérifier que l'expéditeur du JWT est bien celui qu'il prétend être et de s'assurer que le message n'a pas été falsifié.

Pour créer la signature:

1. base64 En-tête et payload encodés en base64.
2. Application de l'algorithme de signature (par exemple, HMAC SHA256 ou RSA) avec une clé secrète (pour les algorithmes symétriques tels que HMAC) ou une clé privée (pour les algorithmes asymétriques tels que RSA).
3. Codage Base64Url du résultat pour obtenir la signature.

Exemple de JWT. Consultez le contenu du JWT 

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Création de JWT dans IRIS

Remarque : Avant 2024, la classe %OAuth2.JWT était utilisée pour générer des JWT dans IRIS. La classe %Net.JSON.JWT est désormais la classe principale pour la création de JWT, et j'utiliserai cette classe dans l'exemple de code.

JWK overview

Les JWK représentent une clé cryptographique, en particulier pour la signature et la vérification des JWT. Les JWK permettent de représenter les clés publiques (pour la vérification) et les clés privées (pour la signature) dans un format normalisé qui peut être facilement échangé entre les systèmes. Les JWKS contiennent plusieurs JWKs

Flux de travail JWT

1. Construisez votre en-tête en tant que %DynamicObject et ajoutez des en-têtes personnalisés si nécessaire.

2. Construisez le corps/les revendications directement en tant que %DynamicObject

3. Appelez la méthode Create de la classe %Net.JSON.JWT.

Set sc = ##Class(%Net.JSON.JWT).Create(header, , claims, jwks, , .JWT)

Création de JWK

Set sc = ##Class(%Net.JSON.JWK).Create("HS256","1212ASD!@#!#@$@#@$$#SDFDGD#%+_)(*@$SFFS",.privateJWK,.publicJWK)

Cela renverra la clé privée

{"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"

Quelques propriétés importantes de JWK

"kty": "oct" - représente l'algorithme symétrique
"kty": "RSA" / "kty": "EC" - represente l'algorithme asymétrique

Une fois que le JWK est créé, il peut être ajouté aux JWKS.

Créons des JWKS dans IRIS

Set sc = ##class(%Net.JSON.JWKS).PutJWK(jwk,.JWKS)

Cette méthode renvoie le JWKS

Génération du JWT dans IRIS

Vous pouvez créer des JWT à clé symétrique ou asymétrique dans IRIS. La classe %Net.JSON.JWK est essentiellement utilisée pour générer le JWT. Avant d'appeler la méthode, assurez-vous de créer et d'envoyer les JWKS pour le chiffrement symétrique et asymétrique lors de la génération du JWT.

Encryptage symétrique

Les algorithmes symétriques utilisent une clé secrète partagée, où l'expéditeur et le destinataire utilisent la même clé pour signer et vérifier le JWT. Ces algorithmes, tels que HMAC (HS256, HS512, HS384), génèrent un hachage (signature) pour le payload du JWT. Cette approche n'est pas recommandée pour les systèmes de haute sécurité, car la signature et la vérification sont exposées, ce qui pose des risques potentiels pour la sécurité.

La méthode Create de la classe %Net.JSON.JWK est utilisée pour générer le JWK. Elle accepte deux paramètres d'entrée et renvoie deux paramètres de sortie:

1. algorithm - l'algorithme pour lequel le JWK doit être créé.
2. secert - la clé utilisée pour signer et vérifier le JWT
3. privateJWK - la clé Web JSON privée qui est créée.
4. publicJWK - la clé Web JSON publique qui est créée.

Pour les algorithmes à clé symétrique, vous obtiendrez privateJWK

Pour les algorithmes à clé asymétrique, vous obtiendrez privateJWK et publicJWK

 
SymmetricKeyJWT

Le résultat 

LEARNING>d ##class(Learning.JWT.NetJWT).SymmetricKeyJWT()
privateJWK={"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"}  ; <DYNAMIC OBJECT>
privateJWKS="{""keys"":[{""kty"":""oct"",""k"":""MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT"",""alg"":""HS256""}]}"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsIngtYyI6InRlIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.PcCs_I8AVy5HsLu-s6kQYWaGvuwqwPAElIad11NpM_E

Encryptage asymétrique

L'encryptage asymétrique fait référence à l'utilisation d'une paire de clés : une clé pour signer le jeton (clé privée) et l'autre pour le vérifier (clé publique). Il diffère de l'encryptage symétrique

Clé privée : cette clé est utilisée pour signer le jeton JWT. Elle est gardée secrète et ne doit jamais être exposée.
Clé publique : Cette clé est utilisée pour vérifier l'authenticité du JWT. Elle peut être partagée et distribuée en toute sécurité car elle ne peut pas être utilisée pour signer de nouveaux jetons.

Vous pouvez générer l'encryptage asymétrique JWT avec une clé/un certificat privé via %SYS.X509Credentials. Vous devez donc stocker votre certificat dans cette classe persistante.

 
AsymmetricWithx509

JWT dans les applications Web.

À partir de la version de 2023 , IRIS inclut par défaut la création de JWT intégrée pour les applications Web. Assurez-vous que l'authentification JWT est activée lors de la configuration de votre application Web

J'ai ajouté une brève explication  sur la configuration

1. Activez l' Authentication JWTdans votre application Web
2. Créez une classe REST si vous ne l'avez pas déjà fait
3. La ressource endpoint par défaut « /login » est incluse. Effectuez un appel API REST en utilisant l'authentification de base avec le payload comme {"user": "_SYSTEM", "password": "SYS"}.
4. La réponse sera un JSON contenant le "access_token," "refresh_token," et d'autres détails pertinents.
5. Utilisez le token d'accès pour l'autorisation.

0
1 42
Article Iryna Mykhailova · Jan 27, 2025 1m read

Dans votre production d'interopérabilité, vous pouvez toujours avoir une Business Operation qui est un client HTTP, qui utilise OAuth 2.0 pour l'authentification, mais vous avez du personnaliser l'opération pour cette méthodologie d'authentification. Depuis la version v2024.3, qui a été récemment publiée, il existe une nouvelle fonctionnalité, fournissant de nouveaux paramètres, pour gérer cela plus facilement.

Dans votre Business Operation qui utilise l'outbound adaptateur HTTP, vous trouverez de nouveaux paramètres, sous le groupe OAuth.

0
0 42
Article Guillaume Rongier · Jan 8, 2025 4m read

Il y a environ un mois, j'ai commencé à travailler sur l'utilisation du logiciel Epic on FHIR.

Création d'une paires de clés publiques-privées

mkdir /home/ec2-user/path_to_key
openssl genrsa -out ./path_to_key/privatekey.pem 2048

Pour les applications back-end, vous pouvez exporter la clé publique vers un certificat X.509 encodé en base64 intitulé publickey509.pem à l'aide de la commande ci-dessous...

openssl req -new -x509 -key ./path_to_key/privatekey.pem -out ./path_to_key/publickey509.pem -subj '/CN=medbank'

où '/CN=medbank' est le nom du sujet (par exemple le nom de l'application) pour lequel la paire de clés est utilisée. Le nom du sujet n'a pas d'impact fonctionnel dans ce cas, mais il est nécessaire pour créer un certificat X.509.

Le logiciel Epic on FHIR est une ressource gratuite pour les développeurs qui créent des applications

J'ai enregistré mon application "medbank" afin d'obtenir un identifiant client Screenshot J'ai supprimé les identifiants client et modifié l'URL du jeu JWK hors production (Non-Production JWK Set URL) afin de protéger l'adresse IP réelle. Screenshot

La documentation d'Epic indique que votre application effectue une requête HTTP POST au point de terminaison OAuth 2.0 du serveur d'autorisation pour obtenir un jeton d'accès. J'ai essayé d'écrire du code, mais je n'ai jamais réussi à obtenir un jeton d'accès.

J'ai appelé le WRC InterSystems pour obtenir de l'aide.

Nous avons configuré un client OAuth2 en utilisant le type de certificat "JWT Authorization" et la "private key JWT" pour l'authentification.

Nous avons ensuite essayé de l'exécuter sur le terminal en utilisant IsAuthorized() et GetAccessTokenJWT(), mais la réponse a été "invalid client ID".

Quelques jours plus tard, nous avons vu que le grant_type était en fait supposé être client_credentials, nous avons donc changé pour utiliser cela en passant de GetAccessTokenJWT() à GetAccessTokenClient() et cela a fonctionné.

Je souhaiterais mettre en œuvre Epic sur FHIR en tant que cas d'utilisation pour les iris-http-calls

J'ai utilisé Docker pour déployer les iris-http-calls dans AWS.

sudo docker build --no-cache --progress=plain . -t oliverwilms/iris-http-calls 2>&1 | tee build.log
sudo docker run -d -p57700:52773 oliverwilms/iris-http-calls

J'ai copié des fichiers de clés privées et publiques avec un accès en lecture pour IRIS

chmod 644 privatekey.pem
sudo docker cp ./privatekey.pem container_name:/home/irisowner/dev/ 
sudo docker cp ./publickey509.pem container_name:/home/irisowner/dev/
chmod 600 privatekey.pem

J'ai créé des informations d'identification X509 dans IRIS

Set oX509Credentials = ##class(%SYS.X509Credentials).%New()
Set oX509Credentials.Alias = "medbank"
Set tSC = oX509Credentials.LoadCertificate("/home/irisowner/dev/publickey509.pem")
Do $System.Status.DisplayError(tSC)
Set tSC = oX509Credentials.LoadPrivateKey("/home/irisowner/dev/privatekey.pem")
Do $System.Status.DisplayError(tSC)
Set tSC = oX509Credentials.%Save()
Do $System.Status.DisplayError(tSC)

Configuration d'un client OAuth2

http://localhost:57700/csp/sys/sec/%25CSP.UI.Portal.OAuth2.Client.ServerList.zen

Screenshot

Cliquez sur Create Server Description (Créer une description de serveur)

Création de la description du serveur

Screenshot Renseignez le champ Issuer Endpoint, choisissez SSL/TLS Configuration et cliquez sur Discover and Save (Découvrir et enregistrer).
https://fhir.epic.com/interconnect-fhir-oauth/oauth2
Screenshot

J'ai cliqué sur Annuler (Cancel) et je suis retourné à

http://localhost:57700/csp/sys/sec/%25CSP.UI.Portal.OAuth2.Client.ServerList.zen

Screenshot

Cliquez sur le lien Client Configurations (configuration des clients).

Création de la configuration des clients

Screenshot

Cliquez sur Create Client Configuration (Créer une configuration des clients)

Screenshot

Sous l'onglet General, indiquez le nom de l'application:

medbank

Choisissez le type de client: Confidential

Choisissez la configuration SSL

Sous l'URL de redirection du client, indiquez le nom de l'hôte

localhost

Port

57700

Décochez la case Use TLS/SSL

Sous Types de certificats requis, cochez la case d'informations d'identification du client "Client Credentials"

Sous Type d'authentification, choisissez clé privée JWT

Sous Algorithme de signature d'authentification, choisissez RS384

Remplissez le champ Audience

https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token
Screenshot

Sous l'onglet JWT Settings (Paramètres JWT), cochez la case Create JWT Settings (Créer des paramètres JWT) à partir d'informations d'identification X509. Choisissez vos informations d'identification dans la liste déroulante. Dans la colonne de signature Signing de la ligne des algorithmes de jetons d'accès, choisissez RS384.

Screenshot

Sous l'onglet Client Credentials (Informations d'identification du client), j'ai copié l'identifiant client hors production que j'avais reçu du logiciel Epic on FHIR. Le code secret client est requis. Je l'ai rempli comme x.

Screenshot

Important: N'oubliez pas de cliquer sur Save (Enregistrer)

0
0 46
Article Guillaume Rongier · Juil 25, 2024 28m read

Cet article a pour objectif de fournir au lecteur les informations suivantes:

  • Configuration et utilisation du serveur FHIR
  • Création d'un serveur d'autorisation OAuth2
  • Liaison entre le serveur FHIR et le serveur d'autorisation OAuth2 pour la prise en charge de SMART sur FHIR
  • Utilisation des capacités d'interopérabilité dans "IRIS for Health" pour filtrer les ressources FHIR
  • Création d'une opération personnalisée sur le serveur FHIR

Schéma de l'article:

Schema

Flux de travail de l'article:

Workflow

1. Table des matières

2. Objectifs

Cette session de formation vise à fournir aux participants les compétences suivantes:

  • Configuration et utilisation du serveur FHIR
  • Création d'un serveur d'autorisation OAuth2
  • Liaison entre le serveur FHIR et le serveur d'autorisation OAuth2 pour la prise en charge de SMART sur FHIR
  • Utilisation des capacités d'interopérabilité dans "IRIS for Health" pour filtrer les ressources FHIR
  • Création d'une opération personnalisée sur le serveur FHIR

3. Installation

Pour installer l'environnement de formation, vous devez avoir installé Docker et Docker Compose sur votre machine.

Vous pouvez installer Docker et Docker Compose en suivant les instructions sur le site Docker website.

Une fois Docker et Docker Compose installés, vous pouvez cloner ce dépôt et exécuter la commande suivante:

docker-compose up -d

Cette commande démarre le conteneur "IRIS for Health" et le conteneur "Web Gateway" pour exposer le serveur FHIR via HTTPS.

3.1. Accès au serveur FHIR

Une fois les conteneurs démarrés, vous pouvez accéder au serveur FHIR à l'URL suivante:

https://localhost:4443/fhir/r5/

3.2. Accés au Portail de Gestion d'InterSystems IRIS

Vous pouvez accéder au portail de gestion InterSystems IRIS à l'adresse suivante:

http://localhost:8089/csp/sys/UtilHome.csp

Le nom d'utilisateur et le mot de passe par défaut sont "SuperUser" et "SYS" respectivement.

4. Configuration du serveur d'autorisation OAuth2

Pour configurer le serveur d'autorisation OAuth2, il faut se connecter au portail de gestion InterSystems IRIS et naviguer jusqu'à l'administration du système: System Administration > Security > OAuth 2.0 > Servers.

OAuth2 Servers

Ensuite, nous remplirons le formulaire pour créer un nouveau serveur d'autorisation OAuth2.

4.1. Onglet Généralités

Nous commençons d'abord par l'onglet Généralités.

General Tab

Les paramètres sont les suivants:

  • Description: La description du serveur d'autorisation OAuth2
    • Serveur d'autorisation Oauth2 Auth
  • Émetteur: L'URL du serveur d'autorisation OAuth2
    • https://webgateway/oauth2
    • REMARQUE : Nous utilisons ici l'URL de la passerelle Web Gateway pour exposer le serveur FHIR via HTTPS. Il s'agit du nom DNS interne du conteneur de la passerelle Web Gateway.
  • Types de subventions pris en charge: Les types de subventions pris en charge par le serveur d'autorisation OAuth2
    • Code d'autorisation
    • Informations d'identification du client
    • Autorisation JWT
    • REMARQUE : Nous utiliserons le type de subvention de Client Credentials (informations d'identification du client) pour authentifier le serveur FHIR auprès du serveur d'autorisation OAuth2.
  • Configuration SSL/TLS: La configuration SSL/TLS à utiliser pour le serveur d'autorisation OAuth2.
    • Par défaut: BFC_SSL

4.2. Onglet Périmètre

Ensuite, nous passons à l'onglet Périmètre.

Scope Tab

Nous allons créer 3 périmètres:

  • user/Patient.read: Le périmètre de lecture des ressources disponibles pour les patients
  • VIP: Le périmètre de lecture des ressources disponibles pour les patients VIP
  • user/.: Le périmètre de lecture toutes les ressources, à des fins administratives

4.3. Onglet JWT

Ensuite, nous passons à l'onglet JWT.

JWT Tab

Ici, nous sélectionnons simplement l'algorithme à utiliser pour le JWT..

Nous utiliserons l'algorithme RS256.

Si nécessaire, nous pouvons sélectionner le cryptage pour le JWT. Nous n'utiliserons pas de cryptage pour cette session de formation.

4.4. Onglet Personnalisation

Ensuite, nous passons à l'onglet Personnalisation.

Customization Tab

Voici toutes les classes de personnalisation pour le serveur d'autorisation OAuth2.

Nous changeons les classes suivantes:

  • Classe de génération du jeton: La classe à utiliser pour générer le jeton
    • FROM : %OAuth2.Server.Generate
    • TO : %OAuth2.Server.JWT

Nous pouvons maintenant enregistrer le serveur d'autorisation OAuth2.

Félicitations, nous avons maintenant configuré le serveur d'autorisation OAuth2. 🥳

5. Configuration du Client

Pour configurer le Client, il faut se connecter au portail de gestion InterSystems IRIS et naviguer jusqu'à l'administration du système: System Administration > Security > OAuth 2.0 > Client.

OAuth2 Clients

Pour créer un nouveau client, il faut d'abord enregistrer le serveur d'autorisation OAuth2.

5.1. Enregistrement du serveur d'autorisation OAuth2

Sur la page client, cliquez sur le bouton de création d'une description de serveur Create Server Description.

Create Server Description

5.2. Description du serveur

Dans le formulaire Description du serveur, nous devons remplir les paramètres suivants:

Server Description

  • URL du serveur: L'URL du serveur d'autorisation OAuth2
  • Configuration SSL/TLS: La configuration SSL/TLS à utiliser pour le serveur d'autorisation OAuth2
    • Par défaut: BFC_SSL

Cliquez sur le bouton Discover and Save (Découvrir et enregistrer). Félicitations, nous avons maintenant enregistré le serveur d'autorisation OAuth2.

Server Description

5.3. Création d'un nouveau client

Ensuite, nous pouvons créer un nouveau client.

Sur la page client, nous avons un nouveau bouton Client Configuration (Configuration Client).

Client Configuration

Cliquez sur le bouton de lien Client Configuration vers la description du serveur.

Nous pouvons maintenant créer un nouveau client..

Create Client

5.3.1. Onglet Généralités

Nous commençons d'abord par l'onglet Généralités.

General Tab

Les paramètres sont les suivants:

  • Nom de l'application: Le nom du client
    • App
    • REMARQUE : C'est le nom du client.
  • Nom du client: Le nom du client
    • App
  • *Type de client: Le type du client
    • Confidentiel
    • REMARQUE : Nous utiliserons le type de client "confidentiel" pour authentifier le serveur FHIR auprès du serveur d'autorisation OAuth2.
  • URI de redirection: L'URI de redirection du client
    • https://webgateway/oauth2
    • REMARQUE : Nous utilisons ici l'URL de la passerelle Web Gateway pour exposer le serveur FHIR via HTTPS. Il s'agit du nom DNS interne du conteneur de la passerelle Web Gateway.
    • REMARQUE : Ceci ne sera pas utilisé dans cette session de formation.
  • Types de subventions: Les types de subventions pris en charge par le client
    • Informations d'identification du client
    • REMARQUE : Nous utiliserons le type de subvention de Client Credentials (informations d'identification du client) pour authentifier l'application client (Client Application) auprès du serveur d'autorisation OAuth2.
  • Type d'authentification: Le type d'authentification du client
    • Basique
    • REMARQUE : Nous utiliserons le type d'authentification Basique pour authentifier l'application client (Client Application) auprès du serveur d'autorisation OAuth2.

Maintenant, nous pouvons cliquer sur le bouton Dynamic Registration (Enregistrement dynamique)..

Félicitations, nous avons maintenant créé le client. 🥳

Si nous allons dans l'onglet Client Credentials (Informations d'identification du client), nous pouvons voir les informations d'identification du client.

Notez que les informations d'identification du client sont Client ID et Client Secret (l'Identifiant du client et le Secret du client).

6. Configuration du serveur FHIR

⚠️ AVERTISSEMENT ⚠️ : Assurez-vous d'être sur l'espace de noms FHIRSERVER.

Namespace

Pour configurer le serveur FHIR, il faut se connecter au portail de gestion InterSystems IRIS et naviguer: Health > FHIR Configuration > Servers.

FHIR Servers

Ensuite, nous allons créer un nouveau serveur FHIR.

Cliquez sur le bouton Server Configuration (Configuration du Serveur).

Server Configuration

6.1. Création un nouveau serveur FHIR

Dans le formulaire Configuration du serveur, nous devons remplir les paramètres suivants:

Server Configuration

  • Paquet de base FHIR: Le paquet de base FHIR à utiliser pour le serveur FHIR
    • r5
  • Adresse URL: L'URL du serveur FHIR
    • /fhir/r5
  • Stratégie d'interactions: La stratégie d'interactions à utiliser pour le serveur FHIR
    • FHIR.Python.InteractionsStrategy
    • ⚠️ AVERTISSEMENT ⚠️ : Pas comme sur la photo, il faut sélectionner la stratégie d'interactions FHIR.Python.InteractionsStrategy.

Cliquer sur le bouton Add.

Cela peut prendre quelques minutes. 🕒 Allons prendre un café. ☕️

Félicitations, nous avons maintenant créé le serveur FHIR. 🥳

6.2. Liaison entre le serveur FHIR et le serveur d'autorisation OAuth2

Sélectionnez le serveur FHIR et descendez jusqu'au bouton Edit (modifier).

FHIR Server

Dans le formulaire Serveur FHIR , nous devons remplir les paramètres suivants:

FHIR Server

  • Nom du Client OAuth2: Le nom du Client
    • App

Cliquez sur le bouton Save (sauvegarder).

Félicitations, nous avons maintenant lié le serveur FHIR au serveur d'autorisation OAuth2. 🥳

6.3. Test du serveur FHIR

Pour tester le serveur FHIR, vous pouvez utiliser la commande suivante:

GET https://localhost:4443/fhir/r5/Patient

Sans l'en-tête Authorization, vous obtiendrez une réponse 401 Unauthorized.

Pour authentifier la demande, vous devez ajouter l'en-tête Authorization avec le jeton Bearer.

Pour ce faire, demandons un jeton au serveur d'autorisation OAuth2.

POST https://localhost:4443/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <client_id>:<client_secret>

grant_type=client_credentials&scope=user/Patient.read&aud=https://localhost:4443/fhir/r5

Vous obtiendrez une réponse 200 OK avec le jeton d'accès access_token et le type de jeton token_type.

Maintenant, vous pouvez utiliser jeton d'accès access_token pour authentifier la demande auprès du serveur FHIR.

GET https://localhost:4443/fhir/r5/Patient
Authorization: Bearer <access_token>
Accept: application/fhir+json

Félicitations, vous avez maintenant authentifié la demande sur le serveur FHIR. 🥳

7. Filtrage des ressources FHIR avec "InterSystems IRIS for Health"

Eh bien, nous aborderont maintenant un grand sujet.

Le but de ce sujet sera de mettre en place les capacités d'interopérabilité d'IRIS for Health entre le serveur FHIR et l'application cliente.

Ci-dessous, une vue macro de l'architecture:

Interoperability

Et voici le flux de travail:

Workflow

Ce que nous remarquons ici, c'est que l'EAI (capacités d'interopérabilité d'IRIS for Health) servira de chemin d'accès pour les demandes entrantes vers le serveur FHIR. Il filtrera la réponse du serveur FHIR en fonction des champs d'application et enverra la réponse filtrée à l'application cliente.

Avant d'aller plus loin, permettez-moi de vous présenter rapidement les capacités d'interopérabilité d'IRIS for Health.

7.1. Cadre d'Interopérabilité

Il s'agit du cadre IRIS Framework.

FrameworkFull

L'objectif de ce cadre est de fournir un moyen de relier différents systèmes entre eux.

Nous avons 4 composants principaux:

  • Services métiers: Le point d'entrée du cadre. Il reçoit la demande entrante et l'envoie à la production.
  • Processus métier: Le flux de travail du cadre. Il traite la demande entrante et l'envoie à l'opération métier.
  • Operations métier: Le point de sortie du cadre. Il traite la demande entrante et l'envoie au service métier.
  • Messages: Les données du cadre. Elles contiennent la requête entrante et la réponse sortante.

Pour cette session de formation, nous utiliserons les composants suivants:

  • Un service métier Business Service pour recevoir la demande de l'application cliente.
  • Un processus métier Business Process pour filtrer la réponse du serveur FHIR en fonction des péramètres.
  • Une opération métier Business Operation pour envoyer les messages au serveur FHIR.

Pour cette session de formation, nous utiliserons une production d'interopérabilité pré-construite.

Nous nous concentrerons uniquement sur le processus métier Business Process permettant de filtrer la réponse du serveur FHIR en fonction des périmètres.

7.2. Installation de l'IoP

Pour cette partie, nous utiliserons l'outil IoP. IoP signifie l'Interopérabilité sur Python..

Vous pouvez installer l'outil IoP en suivant les instructions du référentiel de l'IoP

L'outil IoP est pré-installé dans l'environnement de formation.

Connectez-vous au conteneur en cours d'exécution:

docker exec -it formation-fhir-python-iris-1 bash

Et exécutez la commande suivante:

iop --init

Ainsi l'IoP sera installée sur le conteneur IRIS for Health.

7.3. Création de la Production d'Interopérabilité

Toujours dans le conteneur, exécutez la commande suivante:

iop --migrate /irisdev/app/src/python/EAI/settings.py

Ainsi, la production d'interopérabilité sera créée.

Vous pouvez maintenant accéder à la production d'interopérabilité à l'adresse URL suivante:

http://localhost:8089/csp/healthshare/eai/EnsPortal.ProductionConfig.zen?$NAMESPACE=EAI&$NAMESPACE=EAI&

Vous pouvez maintenant lancer la production.

Félicitations, vous avez créé la production d'interopérabilité. 🥳

7.3.1. Test de la Production d'Interopérabilité

Obtenez un jeton du serveur d'autorisation OAuth2.

POST https://localhost:4443/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization : Basic <client_id>:<client_secret>

grant_type=client_credentials&scope=user/Patient.read&aud=https://webgateway/fhir/r5

⚠️ AVERTISSEMENT ⚠️ : we change the aud parameter to the URL of the Web Gateway to expose the FHIR server over HTTPS.

Faites passer un patient par la production d'interopérabilité.

GET https://localhost:4443/fhir/Patient
Authorization : Bearer <Token>
Accept: application/fhir+json

Vous pouvez voir la trace de la requête dans la production d'interopérabilité.

http://localhost:8089/csp/healthshare/eai/EnsPortal.MessageViewer.zen?SOURCEORTARGET=Python.EAI.bp.MyBusinessProcess

7.4. Modification du processus métier

Tout le code pour le processus métier Business Process se trouve dans le fichier suivant : https://github.com/grongierisc/formation-fhir-python/blob/main/src/python/EAI/bp.py

Pour cette session de formation, nous adopterons une approche de développement piloté par les tests, TTD (Test Driven Development)..

Tous les tests pour le processus métier Business Process se trouve dans le fichier suivant : https://github.com/grongierisc/formation-fhir-python/blob/main/src/python/tests/EAI/test_bp.py

7.4.1. Préparation de votre environnement de développement

Pour préparer votre environnement de développement, il faut créer un environnement virtuel.

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

7.4.2. Exécution des tests

Pour exécuter les tests, vous pouvez utiliser la commande suivante:

pytest

Les tests échouent.

7.4.3. Mise en œuvre du code

Nous avons 4 fonctions à mettre en œuvre:

  • check_token
  • on_fhir_request
  • filter_patient_resource
  • filter_resources

Vous pouvez mettre en œuvre le code dans https://github.com/grongierisc/formation-fhir-python/blob/main/src/python/EAI/bp.py file.

7.4.3.1. check_token

Cette fonction vérifie si le jeton est valide et si le champ d'application contient le périmètre VIP. Si le jeton est valide et que le périmètre contient le périmètre VIP, la fonction renvoie True (vrai), sinon elle renvoie False (faux). Nous utiliserons la bibliothèque jwt pour décoder le jeton.

Cliquez pour voir le code
def check_token(self, token:str) -> bool:

    # décoder le jeton
    try:
        decoded_token= jwt.decode(token, options={"verify_signature": False})
    except jwt.exceptions.DecodeError:
        return False

    # vérifier si le jeton est valide
    if 'VIP' in decoded_token['scope']:
        return True
    else:
        return False

7.4.3.2. filter_patient_resource

Cette fonction filtrera la ressource patient.

Cela supprimera les champ name, address, telecom and birthdate (nom, adresse, télécom et date de naissance) de la ressource patient..

La fonction renverra la ressource patient filtrée sous forme de chaîne.

Nous utiliserons la bibliothèque fhir.resources pour analyser la ressource patient.

Notez la signature de la fonction.

La fonction prend une chaîne en entrée et renvoie une chaîne comme le résultat.

Nous devons donc analyser la chaîne d'entrée en un objet fhir.resources.patient.Patient, puis analyser l'objet fhir.resources.patient.Patient en une chaîne.

Cliquez pour voir le code
def filter_patient_resource(self, patient_str:str) -> str:
    # filtrer le patient
    p = patient.Patient(**json.loads(patient_str))
    # supprimer le nom
    p.name = []
    # supprimer l'adresse
    p.address = []
    # supprimer le télécom
    p.telecom = []
    # supprimer la date de naissance
    p.birthDate = None

    return p.json()

7.4.3.3. filter_resources

Cette fonction filtrera les ressources.

Nous devons vérifier le type de ressource et filtrer la ressource en fonction du type de ressource.

Si le type de ressource est Bundle (Paquet), nous devons filtrer toutes les entrées du paquet qui sont de type Patient.

Si le type de ressource est Patient, nous devons filtrer la resource de type patient.

La fonction renverra la ressource filtrée sous forme de chaîne.

Nous utiliserons la bibliothèque fhir.resources pour analiser la ressource.

Cliquez pour voir le code
    def filter_resources(self, resource_str:str) -> str:
        # analyser le payload
        payload_dict = json.loads(resource_str)

        # quel est le type de ressource?
        resource_type = payload_dict['resourceType'] if 'resourceType' in payload_dict else 'None'
        self.log_info('Resource type: ' + resource_type)

        # c'est un paquet?
        if resource_type == 'Bundle':
            obj = bundle.Bundle(**payload_dict)
            # filtrer le paquet
            for entry in obj.entry:
                if entry.resource.resource_type == 'Patient':
                    self.log_info('Filtering a patient')
                    entry.resource = patient.Patient(**json.loads(self.filter_patient_resource(entry.resource.json())))

        elif resource_type == 'Patient':
            # filtrer le patient
            obj = patient.Patient(**json.loads(self.filter_patient_resource(resource_str)))
        else:
            return resource_str

        return obj.json()

7.4.3.4. on_fhir_request

Cette fonction sera le point d'entrée du processus métier Business Process.

Elle recevra la demande du service métier Business Service, vérifiera le jeton, filtrera la réponse du serveur FHIR en fonction des champs d'application et enverra la réponse filtrée au service métier Business Service.

La fonction renverra la réponse du serveur FHIR.

Nous utiliserons la bibliothèque iris pour envoyer la requête au serveur FHIR.

Le message sera un objet iris.HS.FHIRServer.Interop.Request.

Cet objet contient la requête au serveur FHIR.

Il consiste des composant suivants: Method, URL, Headers et Payload.

Pour vérifier le jeton, nous utiliserons la fonction check_token et pour obtenir un jeton, il faut utiliser l'en-tête USER:OAuthToken.

Pour filtrer la reponse, nous utiliserons la fonction filter_resources et pour lire la réponse du serveur FHIR, nous utiliserons QuickStream.

Cliquez pour voir le code
def on_fhir_request(self, request:'iris.HS.FHIRServer.Interop.Request'):
    # Faire quelque chose avec la requête
    self.log_info('Received a FHIR request')

    # La passer à la cible
    rsp = self.send_request_sync(self.target, request)

    # Essayer d'obtenir le jeton de la requête
    token = request.Request.AdditionalInfo.GetAt("USER:OAuthToken") or ""

    # Faire quelque chose avec la réponse
    if self.check_token(token):
        self.log_info('Filtering the response')
        # Filtrer la réponse
        payload_str = self.quick_stream_to_string(rsp.QuickStreamId)

        # Si le payload est vide, renvoyer la réponse
        if payload_str == '':
            return rsp

        filtered_payload_string = self.filter_resources(payload_str)
        if filtered_payload_string == '':
            return rsp

        # écrire la chaîne json dans un flux rapide
        quick_stream = self.string_to_quick_stream(filtered_payload_string)

        # renvoyer la réponse
        rsp.QuickStreamId = quick_stream._Id()

    return rsp

7.4.4. Exécution des tests

Pour exécuter les tests, vous pouvez utiliser la commande suivante:

pytest

Les tests passent. 🥳

Vous pouvez maintenant tester le processus métier Business Process avec la production d'interopérabilité.

8. Création de l'opération personnalisée

Dernière partie de la session de formation. 🏁

Nous allons créer une opération personnalisée sur le serveur FHIR.

L'opération personnalisée sera opération de fusion de patients Patient et le résultat sera la différence entre les deux patients.

exemple:

POST https://localhost:4443/fhir/r5/Patient/1/$merge
Authorization : Bearer <Token>
Accept: application/fhir+json
Content-Type: application/fhir+json

{
  "resourceType": "Patient",
  "id": "2",
  "meta": {
    "versionId": "2"
  }
}

La réponse sera la différence entre les 2 patients.

{
    "values_changed": {
        "root['address'][0]['city']": {
            "new_value": "fdsfd",
            "old_value": "Lynnfield"
        },
        "root['meta']['lastUpdated']": {
            "new_value": "2024-02-24T09:11:00Z",
            "old_value": "2024-02-28T13:50:27Z"
        },
        "root['meta']['versionId']": {
            "new_value": "1",
            "old_value": "2"
        }
    }
}

Avant de poursuivre, permettez-moi de présenter rapidement l'opération personnalisée sur le serveur FHIR..

L'opération de personnalisation se décline en trois types:

  • Opération d'instance: L'opération est effectuée sur une instance spécifique d'une ressource.
  • Opération de type: L'opération est effectuée sur un type de ressource.
  • Opération de système: L'opération est effectuée sur le serveur FHIR.

Pour cette session de formation, pour la création de l'opération personnalisée nous utiliserons l'Instance Operation.

8.1. Codage de l'opération personnalisée

Une opération personnalisée doit hériter de la classe OperationHandler à partir du module FhirInteraction.

Voici la signature de la classe OperationHandler:

class OperationHandler(object):

    @abc.abstractmethod
    def add_supported_operations(self,map:dict) -> dict:
        """
        @API Enumerate the name and url of each Operation supported by this class
        @Output map : A map of operation names to their corresponding URL.
        Example:
        return map.put("restart","http://hl7.org/fhir/OperationDefinition/System-restart")
        """

    @abc.abstractmethod
    def process_operation(
        self,
        operation_name:str,
        operation_scope:str,
        body:dict,
        fhir_service:'iris.HS.FHIRServer.API.Service',
        fhir_request:'iris.HS.FHIRServer.API.Data.Request',
        fhir_response:'iris.HS.FHIRServer.API.Data.Response'
    ) -> 'iris.HS.FHIRServer.API.Data.Response':
        """
        @API Process an Operation request.
        @Input operation_name : The name of the Operation to process.
        @Input operation_scope : The scope of the Operation to process.
        @Input fhir_service : The FHIR Service object.
        @Input fhir_request : The FHIR Request object.
        @Input fhir_response : The FHIR Response object.
        @Output : The FHIR Response object.
        """

Comme nous l'avons fait dans la partie précédente, nous utiliserons une approche TTD (Développement piloté par les tests).

Tous les tests pour le Processus d'Affaires sont dans ce fichier : https://github.com/grongierisc/formation-fhir-python/blob/main/src/python/tests/FhirInteraction/test_custom.py

8.1.1. add_supported_operations

Cette fonction ajoute l'opération de fusion de patients Patient aux opérations prises en charge.

La fonction retournera un dictionnaire avec le nom de l'opération et l'adresse URL de l'opération. Sachez que le dictionnaire d'entrée peut être vide.

Le résultat attendu est le suivant:

{
  "resource": 
    {
      "Patient": 
        [
          {
            "name": "merge",
            "definition": "http://hl7.org/fhir/OperationDefinition/Patient-merge"
          }
        ]
    }
}

This json document will be added to the CapabilityStatement of the FHIR server.

Cliquez pour voir le code
def add_supported_operations(self,map:dict) -> dict:
    """
    @API Enumerate the name and url of each Operation supported by this class
    @Output map : A map of operation names to their corresponding URL.
    Example:
    return map.put("restart","http://hl7.org/fhir/OperationDefinition/System-restart")
    """

    # verify the map has attribute resource 
    if not 'resource' in map:
        map['resource'] = {}
    # verify the map has attribute patient in the resource
    if not 'Patient' in map['resource']:
        map['resource']['Patient'] = []
    # add the operation to the map
    map['resource']['Patient'].append({"name": "merge" , "definition": "http://hl7.org/fhir/OperationDefinition/Patient-merge"})

    return map

8.1.2. process_operation

Cette fonction traitera l'opération de fusion Patient.

La fonction renverra la différence entre les 2 patients.

Nous allons utiliser la bibliothèque deepdiff pour obtenir la différence entre les 2 patients.

Les paramètres d'entrée sont les suivants:

  • operation_name: Le nom de l'opération à traiter.
  • operation_scope: Le périmètre de l'opération à traiter.
  • body: Le corps de l'operation.
  • fhir_service: L'objet FHIR Service.
    • fhir_service.interactions.Read
      • Une méthode pour lire une ressource à partir du serveur FHIR.
      • Les paramètres d'entrée sont les suivants:
        • resource_type: Le type de la ressource à lire.
        • resource_id: L'identifiant de la ressource à lire.
      • Le résultat est un objet %DynamicObject
  • fhir_request: L'objet de requête FHIR Request..
    • fhir_request.Json
      • Propriété permettant d'obtenir le corps de la requête, c'est un objet %DynamicObject
  • fhir_response: L'objet de réponse FHIR Response.
    • fhir_response.Json
      • Propriété permettant de définir le corps de la réponse, c'est un objet %DynamicObject.

%DynamicObject est une classe permettant de manipuler des objets JSON.

C'est la même chose qu'un dictionnaire Python mais pour ObjectScript.

Téléchargement d'objet JSON:

json_str = fhir_request.Json._ToJSON()
json_obj = json.loads(json_str)

Définition d'objet JSON:

json_str = json.dumps(json_obj)
fhir_response.Json._FromJSON(json_str)

Assurez-vous que la fonction de traitement process_operation est appelée pour vérifier si operation_name est merge, operation_scope est Instance et RequestMethod est POST.

Cliquez pour voir le code
def process_operation(
    self,
    operation_name:str,
    operation_scope:str,
    body:dict,
    fhir_service:'iris.HS.FHIRServer.API.Service',
    fhir_request:'iris.HS.FHIRServer.API.Data.Request',
    fhir_response:'iris.HS.FHIRServer.API.Data.Response'
) -> 'iris.HS.FHIRServer.API.Data.Response':
    """
    @API Process an Operation request.
    @Input operation_name : The name of the Operation to process.
    @Input operation_scope : The scope of the Operation to process.
    @Input fhir_service : The FHIR Service object.
    @Input fhir_request : The FHIR Request object.
    @Input fhir_response : The FHIR Response object.
    @Output : The FHIR Response object.
    """
    if operation_name == "merge" and operation_scope == "Instance" and fhir_request.RequestMethod == "POST":
        # obtenir la ressource primaire
        primary_resource = json.loads(fhir_service.interactions.Read(fhir_request.Type, fhir_request.Id)._ToJSON())
        # obtenir la ressource secondaire
        secondary_resource = json.loads(fhir_request.Json._ToJSON())
        # retrouver la différence entre les deux ressources
        # utiliser deepdiff pour obtenir la différence entre les deux ressources
        diff = DeepDiff(primary_resource, secondary_resource, ignore_order=True).to_json()

        # créer un nouvel %DynamicObject pour stocker le résultat
        result = iris.cls('%DynamicObject')._FromJSON(diff)

        # mettre le résultat dans la réponse
        fhir_response.Json = result
    
    return fhir_response

à tester :

POST https://localhost:4443/fhir/r5/Patient/1/$merge
Authorization : Bearer <Token>
Accept: application/fhir+json

{
  "resourceType": "Patient",
  "id": "2",
  "meta": {
    "versionId": "2"
  }
}

Vous obtiendrez la différence entre les 2 patients.

{
    "values_changed": {
        "root['address'][0]['city']": {
            "new_value": "fdsfd",
            "old_value": "Lynnfield"
        },
        "root['meta']['lastUpdated']": {
            "new_value": "2024-02-24T09:11:00Z",
            "old_value": "2024-02-28T13:50:27Z"
        },
        "root['meta']['versionId']": {
            "new_value": "1",
            "old_value": "2"
        }
    }
}

Félicitations, vous avez créé l'opération personnalisée. 🥳

9. Trucs et Astuces

9.1. Journal de Csp

In %SYS

set ^%ISCLOG = 5
zw ^ISCLOG

9.2. Solution de BP

Cliquez pour voir le code
from grongier.pex import BusinessProcess
import iris
import jwt
import json
from fhir.resources import patient, bundle

class MyBusinessProcess(BusinessProcess):

    def on_init(self):
        if not hasattr(self, 'target'):
            self.target = 'HS.FHIRServer.Interop.HTTPOperation'
            return

    def on_fhir_request(self, request:'iris.HS.FHIRServer.Interop.Request'):
        # Faire quelque chose avec la requête
        self.log_info('Received a FHIR request')

        # La passer à la cible
        rsp = self.send_request_sync(self.target, request)

        # Essayez d'obtenir le jeton de la requête
        token = request.Request.AdditionalInfo.GetAt("USER:OAuthToken") or ""

        # Faire quelque chose avec la réponse
        if self.check_token(token):
            self.log_info('Filtering the response')
            # Filtrer la reponse
            payload_str = self.quick_stream_to_string(rsp.QuickStreamId)

            # si le payload est vide, renvoyer la réponse
            if payload_str == '':
                return rsp

            filtered_payload_string = self.filter_resources(payload_str)
            if filtered_payload_string == '':
                return rsp

            # écrire la chaîne json dans un flux rapide
            quick_stream = self.string_to_quick_stream(filtered_payload_string)

            # renvoyer la réponse
            rsp.QuickStreamId = quick_stream._Id()

        return rsp
    
    def check_token(self, token:str) -> bool:

        # décoder le jeton
        decoded_token= jwt.decode(token, options={"verify_signature": False})

        # vérifier si le jeton est valide
        if 'VIP' in decoded_token['scope']:
            return True
        else:
            return False

    def quick_stream_to_string(self, quick_stream_id) -> str:
        quick_stream = iris.cls('HS.SDA3.QuickStream')._OpenId(quick_stream_id)
        json_payload = ''
        while quick_stream.AtEnd == 0:
            json_payload += quick_stream.Read()

        return json_payload
    
    def string_to_quick_stream(self, json_string:str):
        quick_stream = iris.cls('HS.SDA3.QuickStream')._New()

        # écrire la chaîne json dans le payload
        n = 3000
        chunks = [json_string[i:i+n] for i in range(0, len(json_string), n)]
        for chunk in chunks:
            quick_stream.Write(chunk)

        return quick_stream

    def filter_patient_resource(self, patient_str:str) -> str:
        # filtrer le patient
        p = patient.Patient(**json.loads(patient_str))
        # supprimer le nom
        p.name = []
        # supprimer l'adresse
        p.address = []
        # supprimer le télécom
        p.telecom = []
        # supprimer la date de naissance
        p.birthDate = None

        return p.json()

    def filter_resources(self, resource_str:str) -> str:
        # analyser le payload
        payload_dict = json.loads(resource_str)

        # quel est le type de ressource?
        resource_type = payload_dict['resourceType'] if 'resourceType' in payload_dict else 'None'
        self.log_info('Resource type: ' + resource_type)

        # c'est un paquet?
        if resource_type == 'Bundle':
            obj = bundle.Bundle(**payload_dict)
            # filrer le paquet
            for entry in obj.entry:
                if entry.resource.resource_type == 'Patient':
                    self.log_info('Filtering a patient')
                    entry.resource = patient.Patient(**json.loads(self.filter_patient_resource(entry.resource.json())))

        elif resource_type == 'Patient':
            # filtrer le patient
            obj = patient.Patient(**json.loads(self.filter_patient_resource(resource_str)))
        else:
            return resource_str

        return obj.json()
0
0 50
Article Lorenzo Scalese · Juin 14, 2024 5m read

Nous concluons cette série d'articles SMART On FHIR avec Auth0 et le référentiel FHIR d'InterSystems IRIS en passant en revue notre application développée en Angular 16.

Rappelons à quoi ressemble l'architecture définie pour notre solution:

Notre application qui servira de front-end correspond à la deuxième colonne et comme vous pouvez le voir, elle sera en charge de deux choses:

  1. Redirigez la demande de connexion vers Auth0 et recevez la réponse.
  2. Envoyez et recevez la réponse des requêtes via REST envoyées au serveur FHIR.

Angular

Angular est un cadre d'application web développé en TypeScript, open source, maintenu par Google, utilisé pour créer et maintenir des applications web mono-page. Cette conception "applications web mono-page" permet de concevoir des applications beaucoup plus dynamiques pour l'utilisateur. Comme nous l'avons déjà expliqué dans le premier article, nous allons utiliser le serveur NGINX comme serveur d'application et reverse proxy qui évitera les problèmes dérivés de CORS en modifiant les en-têtes d'appel pour qu'ils correspondent à ceux du serveur.

Conception de l'application

Nous avons conçu notre application avec Angular Material pour simuler la conception d'une application mobile. Dans notre exemple, l'application est destinée à enregistrer une série de données de patients telles que la fréquence cardiaque, la pression artérielle et le poids et pour cela nous allons envoyer deux types de ressources FHIR à notre serveur, la première sera de type Patient avec laquelle l'utilisateur enregistrera ses données ; La seconde correspondra à la ressource Observation dans laquelle nous enverrons chacun des types de données que nous allons envoyer.

Cette application permettra à l'utilisateur de voir un graphique de l'évolution des données enregistrées.

Écran de connexion

Lorsque l'utilisateur accède à l'itinéraire https:\\localhost, l'écran initial s'affichera à partir duquel on peut demander à se connecter.

 

En cliquant sur le bouton de connexion, l'application redirigera automatiquement l'utilisateur vers la page Auth0 activée pour l'API configurée:

Après avoir introduit notre nom d'utilisateur et notre mot de passe, Auth0 nous demandera d'autoriser l'application à accéder à nos données. Une fois l'accès aux données confirmé, Auth0 nous redirigera vers l'adresse URL que nous avons indiqué lors du processus de configuration. Une fois le jeton d'accès généré, la bibliothèque Auth0 se chargera de l'inclure dans l'en-tête de tous les appels que nous lançons au serveur. On peut le voir dans l'image suivante :

Écran initial

Une fois connecté, la première communication avec notre serveur FHIR permettra de demander les informations disponibles pour l'utilisateur connecté. Pour cela, nous utiliserons une requête par paramètre en envoyant un appel GET du type suivant:

https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersystems.com

La réponse du serveur sera une ressource de type Bundle (paquet) avec les informations suivantes:

{
    "resourceType":"Bundle",
    "id":"8c5b1efd-cfdd-11ee-a06b-0242ac190002",
    "type":"searchset",
    "timestamp":"2024-02-20T10:48:14Z",
    "total":0,
    "link":[
        {
            "relation":"self",
            "url":"https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersystems.com"
        }
    ]
}

Comme nous pouvons le voir, nous avons un total de 0 patients avec cette adresse e-mail, donc notre application nous montrera un écran initial à partir duquel nous pouvons enregistrer nos données.

 

Comme vous pouvez le voir, le champ email est déjà rempli avec l'email de l'utilisateur connecté, car comme vous l'avez vu dans la requête initiale, il va être utilisé comme identifiant. Une fois le formulaire rempli, nous allons envoyer un appel du type suivant via POST:

https://localhost:8443/smart/fhir/r5/Patient

With the message body formed by a Patient resource:

{
    "resourceType":"Patient",
    "birthDate":"1982-03-08",
    "gender":"male",
    "identifier":[
        {
            "type":{
                "text":"ID"
            },
            "value":"12345678A"
        }
    ],
    "name":[
        {
            "family":"PÉREZ RAMOS",
            "given":[
                "LUIS ÁNGEL"
                ]
        }
    ],
    "telecom":[
        {
            "system":"phone",
            "value":"600102030"
        },
        {
            "system":"email",
            "value":"lperezra@intersystems.com"
        }
    ]
}

Les données du patient étant enregistrées sur notre serveur, la requête du patient renvoie maintenant un résultat, ce qui nous permet d'enregistrer les différentes données d'observation. Voyons à quoi ressemble l'écran initial:

Observations screen

De la même manière que nous avons envoyé les données du patient, nous enverrons les résultats d'observation à partir de leurs écrans spécifiques:

Pour chaque ressource envoyée au serveur, l'application ajoute un nouveau point dans le diagramme:

Pour ce faire, elle lancera une requête au serveur demandant les ressources type Observation (résultats d'observation) appartenant à l'utilisateur:

https://localhost/smart/fhir/r5/Observation?patient=Patient/1

Et le serveur retournera à nouveau une ressource type Bundle (paquet) avec tous les résultats d'observations enregistrés pour le patient:

Avec le résultat obtenu, l'application extrait toutes les valeurs numériques et construit les diagrammes pertinents.

Conclusion

Comme vous l'avez vu dans cet article et dans les deux précédents, la conception et la création d'applications SMART On FHIR n'est pas très complexe et nous permet de construire rapidement et de manière agile des applications qui profitent de toutes les fonctionnalités disponibles sur notre serveur FHIR.

Une application de ce type ne requiert pas la mise au point d'un back-end complexe pour gérer les opérations type CRUD sur les données et, grâce à l'utilisation d'OAuth2, il n'est pas nécessaire de gérer les utilisateurs à partir de l'application, cette fonctionnalité étant déléguée à Auth0 ou au serveur d'authentification et d'autorisation choisi par l'utilisateur.

Avec SMART On FHIR, nous pouvons, d'une manière simple et aisée, mettre les outils nécessaires à la gestion des données cliniques à la disposition des patients et des professionnels de la santé.

TMerci infiniment pour votre attention!

0
0 56
Article Lorenzo Scalese · Juin 12, 2024 7m read

Dans l'article précédent, nous avons présenté l'architecture de notre projet SMART On FHIR, il est donc temps de passer aux choses sérieuses et de commencer à configurer tous les éléments qui seront nécessaires.

Nous commençons avec Auth0.

Configuration de l'Auth0

Commençons par créer un compte Auth0 avec un email valide, une fois enregistré il nous faut créer notre première application, et nous le ferons à partir du menu de gauche:

Application menu

Dans notre exemple, l'application sera de type application web monopage car il s'agit d'une application développée dans Angular 16. Nous sélectionnons cette option et cliquons sur Create (Créer).

Single Page Web Application

Dans l'écran suivant, il faut définir les champs suivants:

ATTENTION! Les adresses URL doivent toutes être HTTPS, c'est l'une des exigences pour les connexions OAuth2.

Avec cela, nous avons configuré les adresses URL dont Auth0 a besoin pour rediriger l'utilisateur après le processus d'authentification et d'autorisation. Si vous voyez les URL, elles n'ont pas de port défini, c'est parce qu'avec le déploiement du projet Angular dans Docker via NGINX, nous avons indiqué qu'il sera accessible via le port HTTPS par défaut, 443. Vous pouvez mettre le nom qui vous convient le mieux.

Application configuration

Pour la configuration ultérieure de notre projet Angular, indiquez les valeurs que nous trouvons à la fois dans Domain et Client ID (identifiant de domaine et identifiant de client).

Notre application étant configurée, il est temps de définir l'API qui recevra les requêtes de notre application Angular et nous le ferons à nouveau à partir du menu de gauche:

Cette option nous montrera un nouvel écran pour saisir toutes les données nécessaires:

API configuration

Pour se connecter correctement, il vous faudra définir un identifiant pour l'API qui sera ensuite utilisé par l'application Angular comme "environnement". Comme vous pouvez le voir, il est recommandé de saisir une adresse URL, mais il n'est pas nécessaire que cette adresse soit fonctionnelle, puisqu'elle ne servira que d'identifiant. Dans notre cas, nous pouvons définir:

https://localhost/smart/fhir/r5

Enfin, nous configurons un algorithme de signature RS256 et passons à l'onglet Permissions, où nous définissons le périmètre de FHIR pour les utilisateurs connectés

API permission

Si vous souhaitez approfondir le sujet des contextes FHIR, vous pouvez consulter l'URL de la page officielle en cliquant ici. Pour notre exemple, nous avons défini le périmètre de l'utilisateur/*.* qui permet à l'utilisateur validé d'effectuer des opérations CRUD sur toutes les ressources du serveur FHIR.

Parfait! Nous venons de configurer notre compte Auth0 pour qu'il fonctionne comme un serveur OAuth2.

Configuration de l'application Angular

Je souhaiterais développer l'application en Angular 17, qui introduit pas mal de changements, mais malheureusement la documentation associée à Auth0 et ses bibliothèques ne sont que pour Angular 16, j'ai donc décidé de suivre un chemin facile et je l'ai développée dans la version 16.

Pour configurer notre projet Angular, il suffit d'ouvrir la page app.module.ts et de rechercher le fragment de code suivant:

Examinons la signification de chaque paramètre à configurer:

  • domain: correspond à la valeur Domain générée lors de la création de notre application dans Auth0.
  • clientId: identique à ce qui précède, mais avec la valeur Client ID générée.
  • audience: correspond à l'URL que nous avons configuré comme identifiant de notre API.
  • uri: avec cette valeur, nous indiquons à la bibliothèque TypeScript Auth0 d'intercepter tous les appels que nous faisons aux adresses URL qui contiennent cette URI et d'inclure l'Access_token qu'Auth0 renverra lorsque nous validerons (en ajoutant le paramètre Authorization à l'en-tête de l'appel: Bearer....).

Une fois ces valeurs modifiées, notre application Angular est configurée pour fonctionner avec Auth0. Dans le prochain article, nous verrons plus en détail comment nous invoquerons Auth0 depuis notre interface utilisateur.

Configuration d'InterSystems IRIS for Health

Ce projet est configuré pour installer automatiquement le serveur FHIR pendant le processus de déploiement, afin de nous épargner une étape. Dans notre cas, nous avons défini l'URI/smart/fhir/r5 comme point de terminaison de notre serveur FHIR. Pour ceux d'entre vous qui ne sont pas familiers avec la terminologie FHIR, r5 fait référence à la dernière version de FHIR, disponible depuis des mois sur IRIS.

Pour configurer notre instance IRIS, nous devons d'abord démarrer notre Docker et déployer les 3 conteneurs disponibles dans le projet. Il nous suffira d'exécuter la commande suivante dans le terminal depuis la racine du projet:

docker-compose up -d --build

Cela nous permettra de construire et d'exécuter les conteneurs contenus dans le projet. Pour les utilisateurs de Windows, si vous utilisez Docker Desktop, un écran comme celui-ci devrait s'afficher:

Docker Desktop

Voici nos 3 conteneurs:

  • iris: avec l'instance IRIS dans laquelle se trouve notre serveur FHIR.
  • smart-ui: avec le code de notre application web déployée depuis le serveur NGINX configuré à son tour pour que toutes les connexions se fassent via SSL avec les certificats associés.
  • webgateway: avec son serveur Apache associé (rappelons que depuis la version officielle 2023.1, le serveur Web privé (Private Web Server) a été supprimé, bien qu'il soit encore disponible dans les versions communautaires).

Passerelle Web

Je le répète encore une fois, pour utiliser OAuth2 avec notre serveur FHIR, il est obligatoire que toutes les connexions se fassent par HTTPS, le serveur Apache doit donc être configuré pour n'accepter que les appels de ce type, si vous jetez un œil au fichier /webgateway/shared/CSP.conf vous pouvez voir la section suivante responsable de la configuration du serveur Apache:

# SECTION SSL #
# Activez SSL/TLS (https://) sur le serveur Web Apache.
# L'utilisateur est responsable de fournir des certificats SSL valides.
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile "/webgateway-shared/apache_webgateway.cer"
SSLCertificateKeyFile "/webgateway-shared/apache_webgateway.key"
Header add ACCESS-CONTROL-ALLOW-ORIGIN "*"
</VirtualHost>

Vous pouvez voir comment la configuration est faite pour que les appels passent par le port 443, c'est-à-dire que l'adresse URL de notre webgateway serait https://webgateway et que tous les appels que nous lançons depuis notre application web vers notre serveur FHIR devraient être redirigés vers cette adresse URL (webgateway est le masque attribué au réseau du conteneur Docker créé par ce dernier).

Tous les appels au serveur depuis Angular viendront avec l'URL https://localhost/smart/fhir/r5 et le serveur NGINX sera en charge de rediriger ce localhost vers le webgateway. Si vous ouvrez le fichier /smart-ui/nginx.conf, vous pourrez voir la configuration suivante:

 

Dans cette configuration, nous voyons que notre application web écoutera sur le port 443 et que tous les appels qui ont la valeur / dans l'URL seront gérés par l'application Angular, tandis que ceux qui incluent /smart/ seront redirigés vers https://webgateway.

Faites attention avec proxy_set_header, qui sera la valeur qui permettra d'éviter les maux de tête avec CORS. Pour éviter que notre passerelle Web ne rejette les appels provenant d'autres serveurs, nous devons modifier la valeur de l'en-tête Host pour la configurer avec l'adresse de la passerelle Web.

InterSystems IRIS

Maintenant il faut configurer notre IRIS pour qu'il fonctionne avec Auth0, pour cela il faut le configurer en tant que client OAuth2. Pour ce faire, il suffit d'accéder au Portail de gestion avec les identifiants superuser/SYS et d'accéder à l'option System Administration > Security > OAuth 2.0 > Client, puis de cliquer sur Create Server Description et de remplir l'endpoint Issuer avec la valeur Domain que nous avons obtenue au moment de la création de l'application à Auth0 (https://[MY_DOMAIN]/). Soyez prudent! L'adresse URL doit se terminer par"/". Enfin, nous sélectionnons la configuration SSL/TLS et cliquons sur Discover and Save (Découvrir et Sauvegarder):

IRIS client

Notre instance IRIS récupère automatiquement les informations dont elle a besoin auprès d'Auth0.

Issuer endpoint

Il suffit d'ajouter un client au serveur précédemment configuré. En appuyant sur Client Configuration (Configuration client), nous accéderons à un nouvel écran où nous définirons le nom de l'application et du client. Ce nom de client sera celui que nous utiliserons plus tard pour configurer notre serveur FHIR.

Serveur FHIR

The last step to finish the configuration of our project is to tell our FHIR server which OAuth2 client will be used for the connection. Pour accéder à la configuration, nous allons ouvrir le Portail de Gestion et sélectionnez Health > FHIR > Configuration du FHIR > Configuration du serveur et nous allons ouvrir le point de terminaison qui s'affiche à l'écran, nous irons à la fin de celui-ci et cliquerons sur Edit (Modifier). Enfin, nous ajoutons dans le champ de nom du client OAuth OAuth Client Name le nom avec lequel nous avons créé la configuration du client.

FHIR OAuth Configuration

Conclusion

Nous avons déjà configuré notre projet, dans le prochain article nous étudierons comment notre application Angular interagit avec chacun des acteurs.

Je vous remercie de votre attention!

0
0 57
Article Lorenzo Scalese · Juin 10, 2024 4m read

Introduction

J'ai récemment participé à une séance pratique formidablement organisée par @Patrick Jamieson au cours de laquelle une application Angular a été configurée avec un serveur IRIS FHIR en suivant les protocoles définis par SMART On FHIR. J'ai trouvé cela très intéressant et j'ai donc décidé de développer ma propre application Angular et de profiter ainsi de ce que j'ai appris en la publiant au sein de la communauté.

SMART On FHIR

Voyons ce que Google nous dit sur SMART On FHIR:

SMART on FHIR est un standard de données qui permet aux applications d'accéder aux informations contenues dans les systèmes de dossiers médicaux électroniques (DME). Un développeur d'application peut écrire une application unique qui se connecte à n'importe quel système de DME adopté selon ce standard.

Les principaux concepts que nous allons traiter dans SMART On FHIR sont:

  • Authentification et autorisation déléguées par OAuth2 ou OpenID.
  • Gestion des ressources FHIR dans le contexte défini.
  • Communications HTTPS.

Architecture de notre projet

Pour cet exercice, nous avons configuré les éléments suivants à la fois dans Docker et dans le service Auth0:

  • Une application développée en Angular qui servira de front-end, et qui a été développée selon les principes de SMART On FHIR.
  • Serveur web NGINX et serveur proxy inverse qui publiera notre application développée en Angular.
  • Auth0 nous fournira le service d'authentification et d'autorisation via OAuth2.
  • InterSystems IRIS dans lequel nous déploierons notre serveur FHIR et auquel nous nous connecterons via la passerelle Web incluant un serveur Apache déjà disponible dans son image Docker.

Auth0

Bien que nous puissions déléguer l'authentification et l'autorisation des utilisateurs à un autre serveur IRIS déployé à cet effet, nous allons à cette occasion utiliser le service offert par Auth0.

Qu'est-ce que Auth0?

Auth0 est un service qui nous fournit l'ensemble du mécanisme pour gérer l'autorisation et l'authentification de nos plateformes.

Auth0 dispose également de bibliothèques spécifiques dans différentes langues pour pouvoir s'intégrer facilement à n'importe quel projet, c'est donc toujours une option à prendre en compte pour les développements basés sur SMART On FHIR.

Intégration d'Auth0 dans notre application

L'utilisation d'OAuth2 étant une condition requise pour l'utilisation de SMART On FHIR, cela implique l'inclusion d'un serveur OAuth2 dans le processus habituel d'authentification, d'autorisation et d'accès à l'application. Dans le diagramme suivant, nous pouvons voir la route suivie par les informations envoyées au système avec le service Auth0:

Analysons le processus:

  • Login request:
    1. Demande de connexion: L'utilisateur accède à l'application dans son navigateur Internet et demande à se connecter.
    2. Demande de connexion: L'application Angular transmet la demande au service Auth0.
    3. Page de connexion: Auth0 envoie une redirection vers votre propre page au navigateur Internet de l'utilisateur.
  • Authentification sur Auth0:
    1. Informations d'identification de l'utilisateur: L'utilisateur saisit son adresse électronique et le mot de passe avec lequel il est enregistré dans Auth0.
    2. Authentification & Autorisation: Auth0 valide les données et génère un Access_token comprenant le contexte attribué à l'utilisateur.
    3. Réponse & redirection de l'Access_token: Auth0 redirige la réponse vers l'URL indiquée dans la configuration du projet en incluant le jeton généré.
    4. Écran du patient: L'application Angular montre à l'utilisateur la page d'enregistrement de ses données personnelles.
  • Enregistrement des Ressources FHIR:
    1. Enregistrer le patient: l'utilisateur remplit le formulaire avec ses données, et l'application Angular transforme le formulaire en un objet JSON au format de la ressource FHIR Patient.
    2. Requête POST: l'application Angular envoie un appel HTTP POST au serveur FHIR déployé dans IRIS en incluant l'access_token comme jeton d'authentification dans l'en-tête de la requête
    3. Réponse POST: après avoir reçu la demande POST via Web Gateway, IRIS vérifie la validité du jeton et le contexte de la demande. Si tout est correct, il valide la ressource reçue et l'enregistre sur le serveur FHIR, en renvoyant un HTTP 201 indiquant la création de la nouvelle ressource et en joignant l'identifiant attribué à la nouvelle ressource dans un en-tête.
    4. Opération réussie: L'application Angular redirigera l'utilisateur vers l'écran présentant les principales fonctionnalités.

Une fois connecté, la bibliothèque Auth0 intégrée au projet sera chargée d'intercepter toutes les requêtes que nous faisons à notre serveur FHIR pour y inclure le jeton d'accès reçu d'Auth0.

A venir...

Dans les prochains articles, nous allons voir comment il faut configurer chacun des systèmes concernés et enfin comment les connecter à notre application Angular. Pour ceux qui ne peuvent pas attendre, vous pouvez consulter le README.md présent sur le GitHub associé au projet OpenExchange lié à cet article, qui explique en détail comment configurer à la fois Auth0 et InterSystems IRIS.

Awfully Good: Stay Tuned (1992) with John Ritter

0
0 80
Annonce Sylvain Guilbaud · Fév 23, 2024

Salut les développeurs,

Obtenez une présentation d'InterSystems IRIS dans les différents rôles dans OAuth 2.0 et les menus de configuration de ces rôles. Regardez des démonstrations pratiques d'InterSystems IRIS dans ces rôles et voyez comment ils se connectent aux concepts OAuth 2.0 : 

⏯ OAuth 2.0 en pratique avec les produits InterSystems au Global Summit 2023

0
0 53
Question Moussa SAMB · Nov 2, 2023

Bonjour, 

Je cherche à me connecter via OAuth2 sur un serveur outlook.office365.com et récupérer les messages avec IMAP.

J'ai un programme qui fonctionne avec la connexion plain, cependant je n'arrive pas à me connecter avec certains e-mails.

Raison pour la quelle je pense que la connexion plain est désactivé pour ces comptes.

Pour faire le client IMAP je me suis inspiré de ce Post : https://community.intersystems.com/post/implementing-imap-client-inters…

4
0 424
Question Neil Thaiss · Sept 15, 2023

Salut,

Je suis vraiment nouveau sur le sujet de JWT, alors s'il vous plaît, veuillez pardonner mon ignorance.

Le Trust pour lequel je travaille actuellement souhaite créer un cadre dans lequel ils peuvent créer des services API REST, au sein de HealthConnect, et y accorder l'accès à l'aide de l'autorisation de jeton Web JSON et des porteurs de jetons. Cela serait similaire à la manière dont le Trust se connecte actuellement à d'autres API REST, à savoir : DocMan Connect et GOV.UK Notify.

2
0 81
Article Guillaume Rongier · Oct 19, 2022 13m read

Bonjour, chers développeurs !

Dans cet article, nous allons nous concentrer sur OAuth2, un protocole qui est de plus en plus utilisé en combinaison avec FHIR pour effectuer des autorisations.

Dans cette partie 1, nous allons démarrer le conteneur Docker pour IRIS for Health et Apache, configurer la fonction de serveur d'autorisation OAuth2 sur IRIS for Health, y accéder depuis l'outil de développement REST Postman, et obtenir un jeton d'accès. En outre, dans la deuxième partie et au-delà, nous ajouterons la fonctionnalité de référentiel FHIR à IRIS for Health, nous ajouterons la configuration du serveur de ressources OAuth2 et nous expliquerons comment exécuter des requêtes FHIR avec des jetons d'accès depuis Postman.

Plusieurs excellents articles ont déjà été publiés au sein de la communauté des développeurs pour expliquer la fonctionnalité OAuth2 des produits d'InterSystems ; cependant, je voudrais expliquer à nouveau comment configurer la dernière version. Mise en œuvre d'InterSystems IRIS Open Authorization Framework (OAuth 2.0) - partie 1

Dans cet article, nous utiliserons la dernière version d'InterSystems IRIS for Health 2020.3 Preview Edition. Si vous envisagez de créer un environnement basé sur cet article, veillez à utiliser cette version ou une version ultérieure du kit. Certaines fonctionnalités ne sont pas incluses dans les produits antérieurs à cette version.

Préparatifs préliminaires

La première étape consiste à effectuer des préparatifs préliminaires. Il y a beaucoup de choses à préparer pour construire un environnement sécurisé.

IRIS for Health 2020.3 Preview Edition est uniquement disponible en version conteneur Docker. (InterSystems Docker Hub/IRIS for Health)
Pour effectuer la configuration d'OAuth2, vous devrez également effectuer la configuration du serveur web et de SSL. Dans cet article, nous utiliserons Apache. Lors de la configuration SSL sur Apache, le certificat de configuration SSL doit correspondre au nom d'hôte du serveur. Veuillez tenir compte de ce point.

Obtenir des fichiers d'exemple à partir du dépôt GitHub d'intersystems-jp

Le fichier docker-compose.yml/Dockerfile et d'autres exemples de fichiers utilisés dans cette configuration sont disponibles dans le dépôt GitHub réservé à la communauté des développeurs InterSystems. Tout d'abord, décompressez ce fichier dans votre environnement à l'aide de la commande suivante. (Vous pouvez également le faire à partir de la pièce jointe à cet article). Ce fichier docker-compose.yml/Dockerfile et d'autres fichiers sont créés en se référant à l' application iris-webgateway-example published on OpenExchange.

git clone https://github.com/Intersystems-jp/IRIS4H-OAuth2-handson.git

Modification de la configuration en fonction du kit utilisé

Dans ce fichier docker-compose.yml, deux conteneurs sont configurés pour être démarrés : le conteneur IRIS for Health et le conteneur Apache (httpd) seront créés par la commande docker build. Le fichier docker-compose.yml, disponible sur GitHub, fait référence à IRIS for Health Community Edition Preview Edition (2020.3.200.0). L'édition communautaire peut être utilisée pour l'évaluation des produits InterSystems.

iris:
    image: store/intersystems/irishealth-community:2020.3.0.200.0

Si vous utilisez une version différente (version officielle ou version plus récente), veuillez modifier cette partie de la spécification.

Le conteneur Apache sera construit avec le contenu du Dockerfile, qui nécessite un kit WebGateway pour se connecter à IRIS depuis Apache. Pour savoir comment obtenir ce kit, les partenaires d'InterSystems peuvent consulter le site de téléchargement du kit WRC ou contacter le centre de support WRC. Pour toute autre question, veuillez nous contacter à cet adresse.

Modifiez les parties suivantes du Dockerfile en fonction du produit que vous avez obtenu. Quel que soit le système d'exploitation de la machine hôte (Windows/Ubuntu/CentOS), la plate-forme sera lnxubuntux64 car le système d'exploitation du conteneur httpd de base est Debian.

ARG version=2020.3.0.200.0
ARG platform=lnxubuntux64
ADD WebGateway-${version}-${platform}.tar.gz /tmp/

Préparation d'un certificat SSL

À l'étape suivante, un certificat SSL est préparé. Lorsque l'on accède à l'autorisation OAuth2, le certificat SSL défini dans le serveur Web est vérifié pour voir s'il correspond à l'URL à laquelle on accède. Il n'est pas nécessaire d'utiliser un certificat officiel ; il est possible d'utiliser OpenSSL, etc. Saisissez le nom d'hôte dans le champ "Nom commun" lors de la création du certificat.

De plus, comme le certificat que vous avez créé sera chargé automatiquement au moment du lancement, vous devez modifier le fichier pour qu'il ne nécessite pas de mot de passe. Veuillez vous référer à la commande suivante.

$ openssl rsa -in cert.key.org -out cert.key

Placez les fichiers CRT et KEY créés dans le même répertoire que le Dockerfile, avec les noms de fichiers server.crt / server.key respectivement.

En plus de l'utiliser avec le serveur web Apache, vous aurez besoin d'un certificat SSL pour la configuration d'OAuth2. Il n'est pas nécessaire d'entrer un nom d'hôte, etc., mais vous devez créer trois ensembles. (Dans les configurations suivantes, ils apparaissent sous la forme auth.cer/auth.key , client.cer/client.key , resserver.cer/resserver.key)

Construction de docker et démarrage d'un conteneur docker

Maintenant, vous êtes enfin prêt ! En plus des quatre fichiers que vous avez téléchargés, vous avez maintenant un ensemble d'installation de la passerelle Web et deux certificats SSL dans votre répertoire. Faites attention aux autorisations d'accès et d'exécution de chaque fichier. (Par exemple, j'ai ajouté la permission d'exécution à webgateway-entrypoint.sh).

docker-compose build
docker-compose up -d

Une fois lancé, utilisez la commande docker ps pour vérifier que les deux conteneurs fonctionnent.

Nom du conteneur Apache:<directoryname>_web
Nom du conteneur IRIS for Health:store/intersystems/irishealth-community:2020.3.0.200.0(ou autre nom en fonction de l'ensemble)

Essayez maintenant d'accéder au portail de gestion selon les trois méthodes suivantes. Si la troisième méthode fonctionne, votre configuration SSL via le serveur web Apache est un succès !

http://[hostname]:52773/csp/sys/UtilHome.csp :L'accès à cette URL se fait par le biais de Private Apache dans le conteneur IRIS. Elle ne passe pas par l'Apache configuré.

http://[hostname]/csp/sys/UtilHome.csp : Cette URL permet d'accéder au portail de gestion via l'Apache configuré.

https://[hostname]/csp/sys/UtilHome.csp : Cette URL permet d'accéder au portail de gestion en utilisant une connexion SSL via Apache, que vous avez configurée.

Création d'une configuration SSL

Maintenant que IRIS for Health est opérationnel et que nous avons accès au portail de gestion, créons la configuration SSL pour les derniers préparatifs.

Allez sur le Portail de gestion -> Administration du système -> Sécurité -> Configuration SSL/TLS et créez trois configurations SSL en utilisant les trois paires de clés de certificat que vous avez préparées.

Vous pouvez choisir le nom que vous voulez, mais dans cet article, nous utiliserons SSL4AUTH/SSL4CLIENT/SSL4RESSERVER, conformément aux articles précédents sur OAuth2.

image

*À propos du partage de répertoire entre les hôtes et les conteneurs

La spécification des volumes suivants dans le fichier docker-compose indique l'emplacement actuel du répertoire hôte = /ISC dans le conteneur. Veuillez utiliser ce répertoire lorsque vous spécifiez le fichier de certificat dans les paramètres ci-dessus, etc.

    volumes:
      - .:/ISC

Ce répertoire contiendra non seulement des fichiers mais aussi des fichiers de base de données IRIS et des fichiers de configuration. Consultez le document “Persistant %SYS pour le stockage des données d'instance persistantes” pour plus d'information.

Configuration de OAuth2 dans IRIS for Health

Il est maintenant temps d'entrer dans les détails de l'accès à IRIS for Health en utilisant OAuth2 !

Configuration du serveur d'autorisation OAuth2

Tout d'abord, configurons le serveur d'autorisation OAuth2 ! Allez dans Portail de gestion → Administration du système → Sécurité → OAuth 2.0 → Serveur.

Suivez les instructions ci-dessous pour configurer les paramètres.

Paramètres dans l'onglet "Général"
Point de terminaison de l'émetteur : Nom d'hôteSaisissez le nom d'hôte réel.
Point de terminaison de l'émetteur : PrefixVous pouvez saisir la valeur de votre choix, mais ici nous l'avons fixée à "authserver".
Types de subventions pris en chargeDans cet article, nous n'utiliserons que le "Code d'autorisation", mais si vous souhaitez tester d'autres "Types de subventions", veuillez ajouter une coche. Ajoutez également une coche à "Autorisation JWT"
Configuration SSL/TLSSpécifiez la configuration SSL que vous venez d'ajouter.

image

Dans l'onglet "Scopes", cliquez sur " Ajouter un Scope supporté " pour les ajouter. Plus tard, l'écran de connexion du code d'autorisation affichera la "description" que vous avez écrite ici.

image

Ne modifiez pas l'onglet "Intervalles" par rapport à la valeur par défaut. Dans l'onglet " Paramètres JWT ", sélectionnons " RS512 " comme algorithme de signature.

image

Dans le denier onglet "Personnalisation", changez la spécification "Génération de classe de jeton" en %OAuth2.Server.JWT.

image

Une fois que vous avez saisi les informations, cliquez sur le bouton "Enregistrer" pour sauvegarder la configuration.

Maintenant que vous avez la configuration nécessaire pour qu'IRIS for Health fonctionne comme un serveur d'autorisation OAuth2, vous êtes prêt à l'essayer ! Essayons d'y accéder à partir de Postman et voyons si nous pouvons obtenir un jeton d'accès !

Cependant, avant de faire cela, nous devons effectuer deux autres configurations.

Ajout d'une description du client

Tout d'abord, ajoutez les informations de Postman auxquelles vous souhaitez accéder en tant que client OAuth2. L'enregistrement du client OAuth2 peut être ajouté par le biais d'un enregistrement dynamique ou d'autres méthodes.

Cliquez sur "Description du client" sur la page de configuration du serveur pour continuer.

image

Cliquez sur "Créer une description du client" pour ajouter une entrée.

Suivez les instructions ci-dessous pour créer une souscription du client.

Paramètres dans l'onglet "Général"
NomEntrez un nom de votre choix. Dans ce cas, nous avons choisi " postman ".
Type du ClientSelectionnez “Confidentiel”
Redirection d'URLsCliquez sur le bouton "Add URL" pour ajouter une URL de redirection pour Postman. https://www.getpostman.com/oauth2/callback comme URL de redirection pour Postman.
Types de subventions pris en chargeSpécifiez le même "Code d'autorisation" (Authorization Code) qui a été configuré dans les paramètres du serveur d'autorisation OAuth2. (Par défaut) Ajoutez un contrôle si vous souhaitez également tester d'autres types de subventions. Cependant, les paramètres doivent être les mêmes que la configuration du serveur d'autorisation. Cochez également la case "Autorisation JWT". Précisez ici
Authenticated Signing AlgorithmVérifiez "JWT authorization" sous Supported grant Types (Types de subventions pris en charge) pour pouvoir le sélectionner. Sélectionnez "RS512".

image

Une fois que vous avez saisi les informations, cliquez sur le bouton "Enregistrer" pour sauvegarder la description du client.

Cliquez sur l'onglet " Références du client " pour voir l'ID du client et la clé privée du client pour cette entrée. Vous aurez besoin de cet ID et de cette clé privée lorsque vous effectuerez des tests à partir de POSTMAN.

image

Ajout d'une application Web

Un autre paramètre important doit être ajouté avant d'y accéder à partir de POSTMAN. L'écran de configuration du serveur d'autorisation OAuth2 a déterminé que le point de terminaison pour cette configuration est https://<hostname>/authserver/oauth2. Pour que l'accès à ce point de terminaison soit traité correctement par IRIS, nous devons ajouter une application Web pour cette route URL.

Allez dans Administration système→Sécurité→Applications→Applications Web, et cliquez sur "Créer une nouvelle application Web".

image

Un modèle d'application web OAuth2 est fourni, il faut donc d'abord sélectionner "/oauth2" dans " Copier à partir de ".

Paramètres "Editer l'application Web"
Copie à partir de“/oauth2” : Sélectionnez toujours celui-ci en premier dans la liste déroulante.
Nom/authserver/oauth2
ActivationCochez la case d'option "REST".

Après avoir saisi chaque valeur, enregistrez-la.

image

Test d'OAuth2 à partir de POSTMAN

Testons-le à partir de POSTMAN. Les tests peuvent également être effectués à partir d'autres outils ou du programme lui-même. L'explication détaillée de POSTMAN dépasse le cadre de cet article, mais un point à noter est que la vérification du certificat SSL doit être changée en OFF dans les paramètres de POSTMAN.

Après avoir créé une nouvelle demande dans POSTMAN, sélectionnez "OAuth 2.0" dans l'onglet TYPE d'autorisation et cliquez sur "Obtenir un nouveau jeton d'accès".

Dans l'écran suivant, saisissez les valeurs selon les indications suivantes.

Paramètres「GET NEW ACCESS TOKEN」
Nom du jetonEntrez un nom de votre choix.
Type de subventionChoisissez "Code d'autorisation".
Callback URLhttps://www.getpostman.com/oauth2/callback
Auth URLhttps://<hostname>/authserver/oauth2/authorize Saisissez la valeur du point de terminaison +/authorize. En ajoutant ?ui_locales=ja, vous pouvez afficher l'écran de connexion en japonais.
Auth Token URLhttps:///authserver/oauth2/token. Saisissez la valeur du point de terminaison +/token.
Client IDSaisissez l'ID du client affiché dans l'onglet Références du client après l'enregistrement de la description du client.
Clé Secrète du clientSaisissez la clé privée du client, affichée dans l'onglet Références du client après l'enregistrement de la description du client.
ChampEntrez le champ d'application enregistré dans la configuration du serveur d'autorisation, par exemple "scope1". Vous pouvez également spécifier plusieurs champs séparés par des espaces.
ÉtatEntrez le paramètre d'état "State", qui est utilisé pour les contre-mesures contre CSRF. Il n'est pas explicitement utilisé mais ne peut pas être laissé vide, donc nous entrons une chaîne arbitraire.

Après avoir entré les paramètres et cliqué sur le bouton " Demande de jeton ", vous voyez l'écran de connexion comme indiqué ci-dessous.

image

Essayez de vous connecter avec les informations de l'utilisateur (par exemple, _SYSTEM) ayant accès au portail de gestion.

Sur l'écran suivant après la connexion, vous pouvez décider d'accorder des permissions à cette application. Après avoir cliqué sur " Autoriser ", si le jeton d'accès s'affiche sur l'écran suivant, comme indiqué ci-dessous, le test d'acquisition du jeton d'accès est réussi !

Test d'OpenID Connect

IRIS for Health peut effectuer un traitement d'autorisation OAuth2 ainsi qu'un traitement d'authentification conforme à OpenID Connect. Pour plus de détails consultez ce document.

Dans cette configuration, OpenID Connect est activé, alors testons si nous pouvons également obtenir le jeton d'identification OpenID Connect !

C'est facile à mettre en œuvre. Dans l'écran GET NEW ACCESS TOKEN, ajoutez "openid" à son champ d'application et faites une demande.

OpenID Connect sera également affiché sur la page de demande d'autorisation. Après avoir ouvert une session et donné vos autorisations, assurez-vous que vous obtenez également un jeton d'identification (id_token) lorsque vous voyez l'écran suivant. (Vous devrez peut-être faire défiler l'écran).

Avez-vous réussi à obtenir le jeton d'accès et l'id_token ?

Bien que certains préparatifs, tels que les certificats, nécessitent un peu de temps et d'efforts, nous pourrions construire un serveur d'autorisation OAuth2 avec une telle simplicité en utilisant IRIS for Health, une plateforme de base de données.

Dans la prochaine partie de cette série, je vous montrerai enfin comment construire un référentiel FHIR, enregistrer le référentiel FHIR en tant que serveur de ressources OAuth2 et vous montrer comment accéder par REST au référentiel FHIR en utilisant un jeton d'accès OAuth2 depuis POSTMAN.

0
0 131
Article Guillaume Rongier · Oct 17, 2022 8m read

Bonjour, chers développeurs !

Dans cet article, je vais vous montrer comment configurer le référentiel FHIR + le serveur d'autorisation OAuth2/serveur de ressources sur IRIS for Health en suivant l'article précédent.

Dans la partie 1, nous vous présentons les préparatifs préliminaires, la configuration du serveur d'autorisation OAuth2 et l'obtention du jeton d'accès.
La partie 2 vous explique comment construire un référentiel FHIR et configurer un client/serveur de ressources OAuth2.

La configuration du référentiel FHIR et le serveur client/ressource OAuth2 que nous allons configurer aujourd'hui peuvent être utilisés séparément de l'instance IRIS du serveur d'autorisation OAuth2 que nous avons configuré dans la partie 1 précédente, ou ils peuvent être co-localisés dans la même instance. Dans cet article, nous allons le configurer dans la même instance que le précédent.

Construction du référentiel FHIR et spécification du nom du client OAuth

La construction d'un référentiel FHIR est décrite dans le document “Installer et configurer un serveur FHIR”.

Dans l'écran suivant, après l'avoir construit, cliquez sur l'URL du point de terminaison /csp/healthshare/fhirserver/fhir/r4 pour ouvrir l'écran de configuration.

Sur l'écran de configuration, saisissez le nom de configuration client OAuth2 que vous allez créer dans le champ Nom du client OAuth. Si vous avez déjà configuré un client OAuth2, veuillez faire correspondre son nom.

Dans cet exemple, nous allons utiliser la chaîne "FHIRResource". Pour la modifier, cliquez sur le bouton "Modifier" dans l'écran ci-dessus, puis sur le bouton "Mettre à jour" pour enregistrer les modifications.

Configuration client OAuth2

Dans ce qui suit, nous allons créer la configuration client OAuth2.

Accédez à Administration du système → Sécurité → OAuth2.0 dans le portail de gestion et sélectionnez "Client " au lieu de "Serveur ", contrairement à la partie précédente 1.

Sur l'écran suivant, cliquez sur "Creation de la Description du Serveur" pour créer la configuration de la connexion au serveur d'autorisation OAuth2. image

Pour le point de terminaison de l'émetteur, la page Description du serveur indique le point de terminaison du serveur d'autorisation configuré dans la partie 1.

Voici l'écran de configuration du serveur d'autorisation OAuth2 configuré dans la partie 1.

image

Pour la configuration SSL/TLS, entrez la configuration SSL/TLS "SSL4CLIENT" que vous avez créée lors de la préparation de la Partie 1.

Après avoir saisi les éléments, exécutez " Découvrir et sauvegarder " pour obtenir les informations du serveur d'autorisation OAuth2 !

image

Si l'accès est réussi, les informations obtenues s'afficheront, comme indiqué ci-dessous. Veuillez noter qu'une erreur peut se produire au cours de ce processus si le certificat SSL spécifiant le nom d'hôte que vous avez préparé précédemment dans la préparation de la partie 1 n'est pas créé correctement et reconnu.

Attention: Même si vous utilisez le fichier docker-container DL dans la partie 1 de cette série, vous pouvez avoir des difficultés à accéder au conteneur IRIS -> conteneur Apache en spécifiant le nom d'hôte. Dans ce cas, vous pouvez résoudre le problème en entrant le nom d'hôte et l'adresse IP de votre machine dans le fichier docker-compose.yml en tant que extra_hosts, comme indiqué ci-dessous.

  extra_hosts:
    - <yourhostname>:<your ip address>

image

image

Une fois que vous avez enregistré la configuration, cliquez sur " Sauvegarder " pour revenir à la page suivante, puis sélectionnez " Configuration client " pour créer la configuration du référentiel FHIR.

Ajout d'une configuration client au client OAuth2

C'est un titre compliqué, mais l'étape suivante consiste à ajouter la configuration client (informations sur le référentiel FHIR spécifique, l'application CSP, etc. que vous souhaitez connecter au serveur d'autorisation OAuth2 en tant que client OAuth2) à la configuration client OAuth2 que vous venez de créer ( avec des informations sur le serveur d'autorisation OAuth2 auquel se connecter).

image

Sur l'écran suivant, cliquez sur " Créer une configuration client " pour afficher l'écran suivant et régler les éléments nécessaires.

Si vous sélectionnez d'abord le type de client = Serveur de ressources, l'écran de saisie sera le même que ci-dessous.

Nom d'applicationFHIRResource: Saisissez la valeur que vous avez entrée pour " Nom du client OAuth " dans la configuration du référentiel FHIR.
Nom du clientIl s'agit du nom du client qui sera enregistré auprès du serveur d'autorisation OAuth2. Il peut être identique au nom de l'application ; cependant, nous avons choisi un nom différent ici.
DescriptionSaisissez une description pour cette configuration.
Type du clientSélectionnez " Serveur de ressources ".
Configuration SSL/TLSSpécifiez la configuration SSL/TLS que vous avez préparée précédemment lors de la préparation de la partie 1.

image

Après avoir rempli le formulaire, cliquez sur le bouton " Enregistrement dynamique et sauvegarde " pour sauvegarder et enregistrer le fichier sur le serveur. C'est un peu confus, mais lorsque le bouton passe de " Enregistrement dynamique et sauvegarde " à " Obtenir les métadonnées de mise à jour et sauvegarder ", l'enregistrement a réussi.

Examinons les informations de configuration de l'autorisation OAuth2 côté serveur et vérifions si elle est enregistrée.

Sur la page Portail de gestion→Administration du système→Gestion de la sécurité→OAuth2.0→Serveur, cliquez sur "Description du client", et vous verrez qu'il est enregistré comme indiqué ci-dessous. image

Confirmez que le nom est celui que vous avez spécifié dans le nom du client.

Dans la première partie, lorsque nous avons testé l'accès à partir de Postman, nous avons copié manuellement l'ID client et la clé privée qui s'affichent plus bas dans l'écran du descripteur client. Cependant, cette fois-ci, ces informations sont transmises au côté client pendant le processus d'enregistrement dynamique.

Accès au référentiel FHIR à partir de Postman en utilisant un jeton d'accès OAuth2

Et enfin, il est temps d'y accéder depuis Postman !

Tout d'abord, nous devons obtenir un jeton d'accès. La méthode de base est la même que celle utilisée à la fin de la partie 1, mais nous devons ajouter un paramètre audience pour indiquer où le jeton d'accès sera émis.

aud=https://[hostname]/csp/healthshare/fhirserver/fhir/r4

Pour l'ajouter spécifiquement dans Postman, ajoutez-le comme paramètre à l'URL du point de terminaison du code d'autorisation comme suit : ( A cause des limitations de l'écran de Postman, vous ne pouvez pas voir tous les paramètres, mais veuillez inclure tous les éléments ci-dessus aud=https://[hostname]/csp/healthshare/fhirserver/fhir/r4 )

Attention : Vous n'avez pas besoin de changer l'ID client et le Secret client que vous entrez dans Postman pour ceux émis dans l'enregistrement dynamique du serveur de ressources plus tôt. Utilisez l'ID et la clé secrète du client émis pour Postman que vous avez ajouté dans la partie 1.

Après avoir obtenu le jeton d'accès, veuillez copier son contenu.

Dans Postman, si vous laissez le TYPE d'autorisation comme OAuth2, vous disposez d'une fonction pour envoyer le jeton d'accès. Toutefois, dans le référentiel FHIR d'IRIS for Health, il est également nécessaire d'envoyer les informations relatives à l'utilisateur et au mot de passe de l'autorisation de base.

À cette fin, lors d'un accès à partir de Postman, le TYPE d'Autorisation (qui est un peu difficile) doit être Basic Auth, le nom d'utilisateur et le mot de passe doivent être saisis, et le jeton d'accès doit être envoyé comme paramètre dans la demande REST au référentiel FHIR.

En détail : tout d'abord, saisissez le nom d'utilisateur et le mot de passe comme indiqué dans l'écran suivant. Ces informations d'utilisateur seront vérifiées pour voir si elles correspondent aux informations d'utilisateur dans le sous jeton d'accès ; il doit donc s'agir du même utilisateur que celui que vous avez saisi lorsque vous avez obtenu le jeton d'accès.

Dans l'onglet Params, pour access_token, entrez la valeur du jeton d'accès que vous venez de saisir pour le paramètre.

Si vous venez de construire le référentiel FHIR, il n'y a pas de données dans le référentiel, mais vous pouvez demander les données du patient !

Pour l'URL de la demande, entrez https://[hostname]/csp/healthshare/fhirserver/fhir/r4/Patient, et sélectionnez GET comme méthode HTTP (comme indiqué dans la figure ci-dessus).

Appuyez sur le bouton "Envoyer" pour soumettre la demande ! Si vous obtenez le Paquet FHIR comme indiqué ci-dessous, vous avez réussi à accéder au référentiel FHIR en utilisant le jeton d'accès !

Pour plus d'informations sur la manière d'enregistrer et de rechercher des données dans le référentiel FHIR, veuillez consulter la documentation et les articles de la communauté IRIS for Health.

Documentation d'IRIS pour la santé 2020.3 Dépôt de ressources

Comment avez-vous réussi à accéder au référentiel FHIR ?

La configuration décrite dans cette série est la plus simple. Dans un projet FHIR réel, le contenu des données à renvoyer dépendra du contenu approuvé par l'utilisateur, ce qui devra être pris en compte et mis en œuvre.

Nous continuerons à tenir la communauté des développeurs informée de FHIR.

0
0 99
Article Lorenzo Scalese · Sept 7, 2022 7m read

Introduction

Dans ce premier article, un tutoriel simple vous a aidé à mettre en place votre déploiement FHIRaaS.

Maintenant, allons plus loin et présentons une bibliothèque JS pour accéder à la ressource FHIR.

À la fin, deux exemples d'utilisation de cette bibliothèque seront présentés, explorant le type de ressource FHIR Appointment pour les rendez-vous.

SMART sur la bibliothèque FHIR JavaScript

FHIR est une API REST, vous pouvez donc utiliser n'importe quel client HTTP pour l'utiliser. Mais c'est toujours une bonne idée d'avoir de l'aide.

En outre, il existe une initiative intéressante appelée SMART qui vise à fournir des normes pour un accès facile aux données de santé stockées dans des systèmes de santé. Cette API s'appuie sur FHIR comme couche de communication. C'est ce qu'on appelle les SMART sur les applications FHIR.

L'équipe SMART a développé une bibliothèque de client JS, qui nous aide à créer des applications compatibles avec les normes SMART. Par exemple, pour initier le flux de code d'autorisation OAuth2, vous avez juste besoin de ce code.

FHIR.oauth2.authorize({
"client_id": "<your-app-client-id>",
"clientSecret": "<your-app-client-secret>",
"scope": "openid profile user/*.*",
"redirect_uri": "http://localhost:64755/iris-on-fhir/index.html",
"iss": "https://fhirauth.lrwvcusn.static-test-account.isccloud.io/oauth2"
});

Remarque : ce code est fourni pour que vous le copiez et le copiez dans l'onglet OAuth 2.0 :

Afin de respecter la norme SMART, vous devez placer ce code dans une page appelée launch.html. Ainsi, un lanceur SMART sera capable de trouver le lanceur de votre application.

Notez que la méthode authorize() fait beaucoup de travail pour nous :

  • Initialise le flux OAuth, en amenant l'utilisateur à la page de connexion de l'IdP.
  • Si la connexion est réussie, stocke le jeton d'autorisation.
  • Appelle l'URI de rafraîchissement du jeton, lorsque le jeton expire.
  • Une fois qu'un jeton est récupéré, cette méthode l'utilise jusqu'à son expiration, mais vous pouvez ignorer toutes ces étapes

Une autre caractéristique intéressante de cette bibliothèque est qu'il suffit de fournir la ressource FHIR, et elle sélectionne automatiquement les chemins d'accès à l'API. Par exemple, pour obtenir des patients, il suffit d'utiliser la méthode request et de spécifier le type de ressource Patient :

FHIR.oauth2.ready()
  .then(client => client.request("Patient/1223"))
  .then(resource => console.log(resource))
  .catch(console.error);

Cette commande récupère une ressource de type Patient. Ainsi, si vous modifiez cette ressource, vous pouvez l'éditer ou même en créer une autre à partir de ce patient, par les méthodes de mise à jour et d'édition, respectivement :

// enregistre les changements dans la ressource patient
FHIR.oauth2.ready()
  .then(client => client.update(resource))
  .then(() => console.log('patient updated'))
  .catch(console.error);

// crée une nouvelle ressource patient
FHIR.oauth2.ready()
  .then(client => client.create(resource))
  .then(() => console.log('patient created'))
  .catch(console.error);

Notez que vous n'avez pas spécifié de chemin d'accès à l'API FHIR, car la bibliothèque résout le chemin d'accès correct à l'API en fonction du type de la ressource.

Enfin, pour supprimer une ressource :

FHIR.oauth2.ready()
  .then(client => client.delete(`Patient/1223`))
  .then(() => console.log('patient deleted'))
  .catch(console.error);

Ressource FHIR pour les rendez-vous

Afin de montrer l'utilisation d'une autre ressource, créons une simple application de rendez-vous en manipulant la ressource FHIR Appointment.

Veuillez noter qu'il s'agit d'un cas d'utilisation très simple de cette ressource, qui n'utilise que quelques-unes de ses propriétés. En outre, cette ressource est liée à d'autres, qui ne sont pas couvertes ici. Si vous souhaitez en savoir plus sur ces ressources et le flux de travail entre elles, vous devez vous reporter à la spécification HL7 FHIR.

Tout d'abord, un objet modèle est récupéré à partir de la ressource API Development for Appointment. Cet objet est utilisé pour fournir un prototype pour la création et l'édition de rendez-vous.

function getAppointmentTemplate() {
    return {
        "resourceType": "Appointment",
        "id": "examplereq",
...
    };
}

Ensuite, une fonction permettant de modifier le prototype est créée. Cette fonction reçoit le prototype de ressource Appointment de rendez-vous et une instance d'un événement de calendrier. Cet objet d'événement contient des propriétés remplies par l'utilisateur via un composant de calendrier, qui seront introduites dans le prototype de ressource.

function setEventDataToResoruce(resource, eventData) {
    if (eventData.id) {
        resource.id = eventData.id;
    }

    const patient = getSelectedPatientObject();
    resource.participant[0].actor.reference = `Patient/${patient.id}`;
    resource.participant[0].actor.display = patient.name[0].given[0];
    resource.description = eventData.title;
    resource.comment = eventData.extendedProps.description;
    if (!resource.comment) {
        delete resource.comment;
    }

    if (eventData.allDay) {
        eventData.start = eventData.start.split(" ")[0];
        eventData.end = eventData.end.split(" ")[0];
    }

    const hasTime = {
        start: eventData.start.indexOf(" ") > -1,
        end: eventData.end.indexOf(" ") > -1
    }
    if (hasTime.start || hasTime.end) {
        resource.requestedPeriod[0].start = new Date(eventData.start).toISOString();
        resource.requestedPeriod[0].end = new Date(eventData.end).toISOString();
    } else {
        resource.requestedPeriod[0].start = eventData.start;
        resource.requestedPeriod[0].end = eventData.end;
    }

    return resource;
}

Grâce à ces deux fonctions, nous pouvons créer et remplir correctement une ressource Rendez-vous. Maintenant, nous devons utiliser la bibliothèque SMART pour effectuer les opérations CRUD sur cette ressource, finalisant ainsi notre application simple de rendez-vous :

function getAppointments(client) {
    return client.request(`Appointment`);
}

function createAppointment(eventData) {
    const resource = setEventDataToResoruce(
        getAppointmentTemplate(), eventData
    );
    return getFHIRClient()
        .then(client => {
            return client.create(resource);
        });
}

function updateAppointment(eventData) {
    const resource = setEventDataToResoruce(
        getAppointmentTemplate(), eventData
    );
    return getFHIRClient()
        .then(client => {
            return client.update(resource);
        });
}

function deleteAppointment(id) {
    return getFHIRClient()
        .then(client => {
            return client.delete(`Appointment/${id}`);
        });
}

Voici un screencast de l'application en cours d'exécution :

N'oubliez pas que le code exposé ici est simplement l'essentiel pour comprendre l'application. Mais, si vous souhaitez plus de détails, veuillez consulter le code source.

Bot Telegram

Comme dernière démonstration de ce que vous pouvez faire de cool avec FHIRaaS, je voudrais montrer un bot Telegram très simple.

J'ai entièrement basé cette fonctionnalité sur les travaux de Nikolay Soloviev et Sergey Mikhailenko. Dans l'article de Nikolay, vous pouvez voir comment créer le robot dans Telegram. Consultez également l'application de Sergey Mikhailenko pour obtenir plus d'informations sur les bots Telegram.

Comme le plus gros du travail a déjà été fait par Nikolay et Serguey, j'ai juste ajouté une couche supplémentaire de code. Cette couche récupère l'identifiant du patient, ainsi que la date et l'heure du rendez-vous, auprès des utilisateurs de Telegram, dans le cadre d'une simple interaction de type chat, sans fonctionnalités NLP. Après avoir récupéré ces informations, un point de terminaison FHIRaaS est appelé pour afficher un nouveau rendez-vous.

Voici un screencast du bot en action :

Si vous souhaitez obtenir plus de détails sur la mise en œuvre, veuillez consulter le code de l'application.

Conclusion

Dans cet article, nous avons fait une présentation de la bibliothèque SMART on FHIR JavaScript Library et montré comment l'utiliser sur deux exemples basés sur le type de ressource FHIR Appointment.

Dans le prochain article, nous allons approfondir les autres fonctionnalités de l'application iris-on-fhir.

0
0 88
Article Guillaume Rongier · Juin 24, 2022 7m read

Dans cette série d'articles en trois parties, il est montré comment vous pouvez utiliser IAM pour ajouter simplement de la sécurité, selon les normes OAuth 2.0, à un service précédemment non authentifié déployé dans IRIS.

Dans la première partie, nous avons fourni des informations sur OAuth 2.0 ainsi que des définitions et des configurations initiales d'IRIS et d'IAM afin de faciliter la compréhension de l'ensemble du processus de sécurisation de vos services.

La deuxième partie discute et montre en détail les étapes nécessaires pour configurer IAM pour valider le jeton d'accès présent dans la demande entrante et transmettre la demande au backend si la validation réussit.

Cette dernière partie de cette série abordera et démontrera les configurations nécessaires pour que IAM génère un jeton d'accès (agissant comme un serveur d'autorisation) et le valide, ainsi que quelques considérations finales importantes.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial d'InterSystems.

Scénario 2 : IAM comme serveur d'autorisation et validateur de jetons d'accès

Dans ce scénario, contrairement au premier scénario, nous allons utiliser un plugin appelé "OAuth 2.0 Authentication".

Afin d'utiliser IAM comme serveur d'autorisation dans ce flux d'informations d'identification du propriétaire des ressources et du mot de passe, le nom d'utilisateur et le mot de passe doivent être authentifiés par l'application cliente. La demande d'obtention du jeton d'accès auprès d'IAM ne doit être effectuée que si l'authentification est réussie.

Commençons par l'ajouter à notre "SampleIRISService". Comme vous pouvez le voir dans la capture d'écran ci-dessous, nous avons différents champs à remplir afin de configurer ce plugin.

Tout d'abord, nous allons copier l'identifiant de notre service "SampleIRISService" dans le champ "service_id" pour activer ce plugin à notre service.

Dans le champ "config.auth_header_name", nous allons spécifier le nom de l'en-tête qui portera le jeton d'autorisation. Dans ce cas, je vais laisser la valeur par défaut comme "authorization".

Le plugin "OAuth 2.0 Authentication" prend en charge les flux OAuth 2.0 Authorization Code Grant, Client Credentials, Implicit Grant ou Resource Owner Password Credentials Grant (respectivement, Attribution de codes d'autorisation, Identifiants client, Attribution implicite et Attribution des informations d'identification du mot de passe du propriétaire de la ressource OAuth 2.0). Comme nous utilisons dans cet article le flux "Resource Owner Password Credentials" (Identifiants du mot de passe du propriétaire de la ressource), nous allons cocher la case "config.enable_password_grant"..

Dans le champ "config.provision_key", saisissez une chaîne à utiliser comme clé de provision. Cette valeur sera utilisée pour demander un jeton d'accès à IAM.

Dans ce cas, j'ai laissé tous les autres champs avec la valeur par défaut. Vous pouvez vérifier la référence complète de chaque champ dans la documentation du plugin disponible ici.

Voici à quoi ressemble la configuration du plugin à la fin :

Une fois le plugin créé, nous devons créer les informations d'identification de notre consommateur "ClientApp".

Pour ce faire, allez dans "Consumers" dans le menu de gauche et cliquez sur "ClientApp". Ensuite, cliquez sur l'onglet "Credentials" et ensuite sur le bouton "New OAuth 2.0 Application".

Sur la page suivante, entrez un nom quelconque pour identifier votre application dans le champ "name" (nom), définissez un identifiant et un secret de client, respectivement, dans les champs "client_id" et "client_secret" et enfin, entrez l'URL dans votre application où les utilisateurs seront envoyés après autorisation dans le champ "redirect_uri". Ensuite, cliquez sur "Create" (créer).

Maintenant, vous êtes prêt à envoyer des demandes.

La première requête que nous devons faire est d'obtenir le jeton d'accès depuis IAM. Le plugin "OAuth 2.0 Authentication" crée automatiquement un point de terminaison en ajoutant le chemin "/oauth2/token" à l'itinéraire déjà créé.

Note: Assurez-vous que vous utilisez le protocole HTTPS et que le port proxy d'IAM prête attention aux requêtes TLS/SSL (le port par défaut est 8443). Il s'agit d'une exigence d'OAuth 2.0.

Par conséquent, dans ce cas, nous devrions faire une demande POST à l'URL :

https://iamhost:8443/event/oauth2/token

Dans le corps de la requête, vous devez inclure le JSON suivant :

{
   "client_id": "clientid",
   "client_secret": "clientsecret",
   "grant_type": "password",
   "provision_key": "provisionkey",
   "authenticated_userid": "1"
}

Comme vous pouvez le constater, ce JSON contient des valeurs définies à la fois lors de la création du plugin "OAuth 2.0 Authentication", telles que "grant_type" et "provision_key", et lors de la création des informations d'identification du Consommateur, telles que "client_id" et "client_secret".

Le paramètre "authenticated_userid" doit également être ajouté par l'application client lorsque le nom d'utilisateur et le mot de passe fournis sont authentifiés avec succès. Sa valeur doit être utilisée pour identifier de manière unique l'utilisateur authentifié.

La demande et sa réponse respective devraient ressembler à ceci :

Avec cela, nous pouvons maintenant faire une requête pour obtenir les données de l'événement en incluant la valeur "access_token" de la réponse ci-dessus comme "Bearer Token" (jeton de porteur) dans une requête GET vers l'URL

https://iamhost:8443/event/1

Si votre jeton d'accès expire, vous pouvez générer un nouveau jeton d'accès en utilisant le jeton de renouvellement que vous avez reçu avec le jeton d'accès expiré en effectuant une requête POST vers le même point de terminaison que celui utilisé pour obtenir un jeton d'accès, avec un corps quelque peu différent :

{
   "client_id": "clientid",
   "client_secret": "clientsecret",
   "grant_type": "refresh_token",
   "refresh_token": "E50m6Yd9xWy6lybgo3DOvu5ktZTjzkwF"
}

La demande et sa réponse respective devraient ressembler à ceci :

Une fonctionnalité intéressante du plugin "OAuth 2.0 Authentication" est la possibilité d'afficher et d'invalider les jetons d'accès.

Pour répertorier les tokens, envoyez une requête GET au point de terminaison suivant de l'API d'administration d'IAM :

https://iamhost:8444/{workspace_name}/oauth2_tokens

où {workspace_name} est le nom de l'espace de travail IAM utilisé. Veillez à saisir les informations d'identification nécessaires pour appeler l'API d'administration d'IAM si vous avez activé RBAC.

Notez que "credential_id" est l'identifiant de l'application OAuth que nous avons créée dans le consommateur ClientApp (dans ce cas, elle s'appelle SampleApp), et "service_id" est l'identifiant de notre "SampleIRISService" auquel ce plugin est appliqué.

Pour invalider un jeton, vous pouvez envoyer une demande DELETE au point de terminaison suivant

https://iamhost:8444/Sample/oauth2_tokens/{token_id}

où {token_id} est l'identifiant du jeton à invalider.

Si nous essayons d'utiliser le jeton invalidé, nous obtenons un message indiquant que le jeton est invalide ou a expiré si nous envoyons une requête GET contenant ce jeton invalidé comme jeton porteur à l'URL :

https://iamhost:8443/event/1

Considérations finales

Dans cet article, nous avons montré comment vous pouvez ajouter l'authentification OAuth 2.0 dans IAM à un service non authentifié déployé dans IRIS. Vous devez tenir compte du fait que le service lui-même continuera à être non authentifié dans IRIS. Par conséquent, si quelqu'un appelle directement le point de terminaison du service IRIS, en contournant la couche IAM, il pourra voir les informations sans aucune authentification. Pour cette raison, il est important d'avoir des règles de sécurité au niveau du réseau pour empêcher les demandes non désirées de contourner la couche IAM.

Vous pouvez en savoir plus sur IAM ici.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial d'InterSystems.

0
0 203
Article Guillaume Rongier · Juin 22, 2022 4m read

Dans cette série d'articles en trois parties, il est montré comment vous pouvez utiliser IAM pour ajouter simplement de la sécurité, selon les normes OAuth 2.0, à un service précédemment non authentifié déployé dans IRIS.

Dans la première partie, nous avons fourni des informations sur OAuth 2.0 ainsi que des définitions et des configurations initiales d'IRIS et d'IAM afin de faciliter la compréhension de l'ensemble du processus de sécurisation de vos services.

Cette partie va maintenant discuter et montrer en détail les étapes nécessaires pour configurer IAM pour valider le jeton d'accès présent dans la demande entrante et transmettre la demande au backend si la validation réussit.

La dernière partie de cette série abordera et démontrera les configurations nécessaires pour que IAM génère un jeton d'accès (agissant comme un serveur d'autorisation) et le valide, ainsi que quelques considérations finales importantes.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial d'InterSystems.

Scénario 1 : IAM comme validateur de jetons d'accès

Dans ce scénario, il sera utilisé un serveur d'autorisation externe qui génère un jeton d'accès au format JWT (JSON Web Token). Ce JWT est signé à l'aide de l'algorithme RS256 et d'une clé privée. Afin de vérifier la signature du JWT, l'autre partie (dans ce cas IAM) doit avoir la clé publique, fournie par le serveur d'autorisation.

Ce JWT généré par le serveur d'autorisation externe comprend également, dans son corps, une déclaration appelée "exp" contenant l'horodatage de la date d'expiration de ce jeton, et une autre déclaration appelée "iss" contenant l'adresse du serveur d'autorisation.

Par conséquent, IAM doit vérifier la signature du JWT avec la clé publique des serveurs d'autorisation et l'horodatage d'expiration contenu dans la déclaration "exp" à l'intérieur du JWT avant de transmettre la demande à IRIS.

Afin de configurer cela dans IAM, commençons par ajouter un plugin appelé "JWT" à notre "SampleIRISService" dans IAM. Pour ce faire, allez sur la page Services dans IAM et copiez l'identifiant du "SampleIRISService", nous allons l'utiliser plus tard.

Ensuite, allez dans Plugins, cliquez sur le bouton "New Plugin", localisez le plugin "JWT" et cliquez sur Enable.

Dans la page suivante, copiez l'identifiant "SampleIRISService" dans le champ "service_id" et cochez la case "exp" dans le paramètre "config.claims_to_verify".


Notez que la valeur du paramètre "config.key_claim_name" est "iss". Nous allons l'utiliser plus tard.

Ensuite, appuyez sur le bouton "Create" (créer).

Cela fait, allez dans la section "Consumers" dans le menu de gauche et cliquez sur notre "ClientApp" précédemment créée. Allez dans l'onglet "Credentials" (identifiants) et cliquez sur le bouton “New JWT Credential” (nouveau Identifiants JWT).

Dans la page suivante, sélectionnez l'algorithme utilisé pour signer le JWT ( ici RS256) et copiez la clé publique dans le champ "rsa_public_key" (il s'agit de la clé publique qui vous a été fournie par le serveur d'autorisation au format PEM).

Dans le champ "key", vous devez insérer le contenu du revendication JWT que vous avez entré dans le champ "config.key_claim_name" lors de l'ajout du plugin JWT. Donc, dans ce cas, je dois insérer le contenu de la revendication iss de mon JWT, qui, dans mon cas, est l'adresse du serveur d'autorisation.

Après cela, cliquez sur le bouton "Créer".

Hint: À des fins de débogage, il existe un outil en ligne permettant de décoder le JWT afin que vous puissiez vérifier les revendications et leurs valeurs et vérifier les signatures en insérant la clé publique. Voici le lien de cet outil en ligne : https://jwt.io/#debugger

Maintenant, avec l'ajout du plugin JWT, il n'est plus possible d'envoyer la requête sans authentification. Comme vous pouvez le voir ci-dessous, une simple demande GET, sans authentification, renvoie à l'URL

http://iamhost:8000/event/1

un message non autorisé avec le code de statut "401 Unauthorized".

Afin d'obtenir les résultats d'IRIS, nous devons ajouter le JWT à la requête.

Par conséquent, nous devons d'abord demander le JWT au serveur d'autorisation. Le serveur d'autorisation personnalisé que nous utilisons ici renvoie un JWT si une demande POST est faite avec quelques paires clé-valeur dans le corps, y compris des informations sur l'utilisateur et le client, à l'URL suivante :

https://authorizationserver:5001/auth

Voici à quoi ressemblent cette requête et sa réponse :

Ensuite, vous pouvez ajouter le JWT obtenu à partir de la réponse ci-dessous dans le header d'autorisation en tant que jeton de porteur Bearer Token et envoyer une requête GET à la même URL utilisée précédemment :

http://iamhost:8000/event/1

Vous pouvez également l'ajouter en tant que paramètre de chaîne de recherche, la clé de la chaîne de recherche étant la valeur spécifiée dans le champ "config.uri_param_names" lors de l'ajout du plugin JWT qui, dans ce cas, est "jwt" :

Enfin, il y a aussi la possibilité d'inclure JWT dans la requête en tant que cookie, si un nom est saisi dans le champ "config.cookie_names".

Passez à la troisième et dernière partie de cette série pour comprendre les configurations nécessaires pour générer un jeton d'accès IAM et le valider, ainsi que quelques considérations finales importantes.

0
0 80
Article Guillaume Rongier · Juin 20, 2022 5m read

Introduction

Aujourd'hui, de nombreuses applications utilisent le cadre d'autorisation ouvert (OAuth) pour accéder aux ressources de toutes sortes de services de manière sûre, fiable et efficace. InterSystems IRIS est déjà compatible avec le cadre OAuth 2.0, en fait, il y a un excellent article dans la communauté concernant OAuth 2.0 et InterSystems IRIS dans le lien suivant ici.

Toutefois, avec l'avènement des outils de gestion des API, certaines organisations l'utilisent comme point unique d'authentification, empêchant les demandes non autorisées d'arriver aux services descendants et découplant les complexités d'autorisation/authentification du service lui-même.

Comme vous le savez peut-être, InterSystems a lancé son outil de gestion des API, appelé InterSystems API Management (IAM), qui est disponible avec la licence IRIS Enterprise (et non IRIS Community Edition). Vous trouverez ici un autre excellent article de la communauté présentant InterSystems API Management.

 Il s'agit de la première partie d'une série d'articles en trois parties qui montrent comment vous pouvez utiliser IAM pour ajouter simplement de la sécurité, selon les normes OAuth 2.0, à un service précédemment non authentifié déployé dans IRIS.

Dans cette première partie, vous trouverez des informations sur OAuth 2.0 ainsi que des définitions et des configurations initiales d'IRIS et d'IAM afin de faciliter la compréhension de l'ensemble du processus de sécurisation de vos services.

Suite à la première partie, cette série d'articles abordera deux scénarios possibles pour sécuriser vos services avec IAM. Dans le premier scénario, IAM validera uniquement le jeton d'accès présent dans la requête entrante et transmettra la requête au backend si la validation réussit. Dans le second scénario, IAM va à la fois générer un jeton d'accès (en agissant comme un serveur d'autorisation) et le valider.

Par conséquent, la deuxième partie abordera et montrera en détail les étapes nécessaires pour configurer le scénario 1, et la troisième partie abordera et démontrera les configurations pour le scénario 2, ainsi que quelques considérations finales.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial InterSystems.

OAuth 2.0 : contexte

Chaque flux d'autorisation OAuth 2.0 se compose essentiellement de 4 parties :

  1. Utilisateur
  2. Client
  3. Serveur d'autorisation
  4. Propriétaire de la ressource

Pour des raisons de simplicité, cet article utilisera le flux OAuth "Resource Owner Password Credentials" (Identifiants du mot de passe du propriétaire de la ressource), mais vous pouvez utiliser n'importe quel flux OAuth dans IAM. De même, cet article ne spécifiera aucune portée.

Note: Vous ne devez utiliser le flux d'informations d'identification du mot de passe du propriétaire des ressources que lorsque l'application cliente est hautement fiable, car elle traite directement les informations d'identification des utilisateurs. Dans la plupart des cas, le client doit être une application de première partie.

En général, le flux "Resource Owner Password Credentials" (Identifiants du mot de passe du propriétaire de la ressource) suit les étapes suivantes :

  1. L'utilisateur saisit ses identifiants (par exemple le nom d'utilisateur et le mot de passe) dans l'application client.
  2. L'application client envoie les identifiants de l'utilisateur ainsi que sa propre identification (identifiant et secret du client, par exemple) au serveur d'autorisation. Le serveur d'autorisation valide les identifiants de l'utilisateur et l'identification du client et renvoie un jeton d'accès.
  3. Le client utilise le jeton pour accéder aux ressources du serveur de ressources.
  4. Le serveur de ressources valide le jeton d'accès reçu avant de renvoyer toute information au client.

Dans cette optique, il existe deux scénarios dans lesquels vous pouvez utiliser IAM pour traiter OAuth 2.0 :

  1. IAM agit comme un validateur, vérifiant le jeton d'accès fourni par l'application cliente, transmettant la demande au serveur de ressources uniquement si le jeton d'accès est valide ; dans ce cas, le jeton d'accès serait généré par un serveur d'autorisation tiers.
  2. IAM agissant à la fois comme un serveur d'autorisation, fournissant un jeton d'accès au client, et comme un validateur de jeton d'accès, vérifiant le jeton d'accès avant de rediriger la demande vers le serveur de ressources.

Définitions d'IRIS et d'IAM

Dans ce post, il sera utilisé une application Web IRIS appelée "/SampleService". Comme vous pouvez le voir sur la capture d'écran ci-dessous, il s'agit d'un service REST non authentifié déployé dans IRIS :

En outre, dans le côté IAM est configuré un service appelé "SampleIRISService" contenant un itinéraire, comme vous pouvez le voir dans la capture d'écran ci-dessous :

En outre, dans IAM est configuré un consommateur appelé "ClientApp", initialement sans aucun justificatif d'identité, pour identifier celui qui appelle l'API dans IAM :

Avec les configurations ci-dessus, IAM transmet chaque requête GET envoyée à l'URL suivante à IRIS :

http://iamhost:8000/event

À ce stade, aucune authentification n'est encore utilisée. Par conséquent, si nous envoyons une simple requête GET, sans authentification, à l'URL

http://iamhost:8000/event/1

nous obtenons la réponse recherchée.

Dans cet article, nous allons utiliser une application appelée "PostMan" pour envoyer des requêtes et vérifier les réponses. Dans la capture d'écran de PostMan ci-dessous, vous pouvez voir une simple requête GET ainsi que sa réponse.

Passez à la deuxième partie de cette série pour comprendre comment configurer IAM pour valider les jetons d'accès présents dans les demandes entrantes.

0
0 89