Intégrer Pro Santé Connect dans une application : OIDC, e-CPS, scopes et homologation
Guide pratique pour raccorder un logiciel à Pro Santé Connect : parcours Datapass et bac à sable, flux code d'autorisation, scopes et claims, durées de vie des jetons, déconnexion, mTLS et Espace de Confiance.
Ala Ben Aicha

Réponse directe
Pro Santé Connect (PSC) est le fournisseur d'identité OpenID Connect de l'ANS pour les professionnels des secteurs sanitaire, médico-social et social. Votre application est un client OIDC confidentiel : elle redirige vers la mire PSC (carte CPx, application e-CPS, clé FIDO2 ou délégation), échange le code côté serveur avec scope=openid scope_all et acr_values=eidas1, puis identifie l'utilisateur par SubjectNameID. Le raccordement passe par une demande Datapass, un passage obligatoire en bac à sable (BAS), puis une demande de production depuis l'Espace Authentifié du portail industriels.
Pro Santé Connect en deux minutes
PSC est un service gratuit développé et maintenu par l'ANS, bâti sur Keycloak. D'après la page produit Pro Santé Connect, son implémentation est obligatoire depuis le 1er janvier 2023 pour les services numériques en santé dits « sensibles » au sens de la PGSSI-S. L'Annuaire Santé, alimenté par le RPPS, est la source des identités.
Quatre moyens d'identification électronique (MIE) apparaissent aujourd'hui dans la mire et dans le claim authMode des jetons :
| MIE | Valeur authMode |
Remarque |
|---|---|---|
| Application e-CPS | MOBILE |
Seul MIE pouvant atteindre le niveau « Certifié » |
| Carte CPS / CPx | CARD |
Lecteur PC/SC ; sous macOS, CPS-Gestion est requis hors Firefox |
| Clé de sécurité FIDO2 | WEBAUTHN |
Niveau Standard |
| Délégation à un FI tiers | IDENTITY_BROKER |
Ouverture partielle, parcours dédié |
L'ANS déconseille explicitement de filtrer les accès sur authMode : il décrit le moyen utilisé, pas le niveau de garantie.
Environnements et endpoints
La documentation technique PSC publie deux environnements. Le bac à sable sert aux tests avec des identités fictives ; la production utilise le domaine historique esw.
| Endpoint | Bac à sable (BAS) | Production |
|---|---|---|
| Discovery | https://auth.bas.psc.esante.gouv.fr/auth/realms/esante-wallet/.well-known/wallet-openid-configuration |
https://auth.esw.esante.gouv.fr/auth/realms/esante-wallet/.well-known/wallet-openid-configuration |
| Authorization | https://wallet.bas.psc.esante.gouv.fr/auth |
https://wallet.esw.esante.gouv.fr/auth |
| Token, UserInfo, Logout | sous /auth/realms/esante-wallet/protocol/openid-connect/ |
idem sur auth.esw.esante.gouv.fr |
Premier piège : le document de découverte s'appelle wallet-openid-configuration. Une bibliothèque qui ajoute automatiquement /.well-known/openid-configuration à l'issuer obtient bien un document Keycloak valide, mais son authorization_endpoint pointe vers Keycloak et non vers la mire wallet. Passez l'URL de découverte complète.
Le parcours de raccordement
Le parcours standard vers l'Espace Communautaire suit ces étapes, avec les délais moyens annoncés par l'ANS :
- Créer le compte du responsable technique sur iSC, le fournisseur d'identité de l'ANS pour les industriels (environ 2 semaines).
- Déposer une demande Datapass d'accès à l'API Pro Santé Connect, une demande par service raccordé (environ 2 semaines). C'est le numéro de demande, et non le numéro d'habilitation, qui est attendu ensuite.
- Activer l'Espace Authentifié et soumettre la demande de création en BAS depuis la rubrique « Mon raccordement à Pro Santé Connect ».
- Obtenir un MIE de test : carte CPx de test via la démarche F414 si vous avez un lecteur, ou identité de test générée dans EDiT avec l'application e-CPS de test.
- Tester, puis soumettre la demande de production.
Le référentiel PSC impose un test réussi sur le BAS avant toute production (EXI PSC 12) et l'accès de l'ANS à votre service de test (EXI PSC 13). La version 1.8.4 du référentiel est en vigueur ; la version 2.0, qui ajoute l'Espace de Confiance, est publiée à titre informatif. Les établissements qui achètent une solution déjà validée par PSC peuvent passer par le « raccordement direct » et sauter le BAS.
Le flux code d'autorisation, paramètre par paramètre
PSC attend un client confidentiel : le client ID et le secret restent côté serveur (exigence 22), CORS n'est pas autorisé et la mire ne s'affiche pas dans une iframe. Un client lourd doit ouvrir un navigateur externe (EXI PSC 25 et 26).
| Paramètre | Valeur | Source |
|---|---|---|
response_type |
code |
Obligatoire |
scope |
openid scope_all |
EXI PSC 17 |
acr_values |
eidas1 |
EXI PSC 16, obligatoire |
state, nonce |
Aléatoires, vérifiés au retour | Recommandés |
prompt, max_age |
login pour forcer la ré-authentification |
Optionnels |
use_camp, authentication_mode |
Préremplissage de la mire (fonction CAMP, juin 2026) | Optionnels |
Au retour, PSC ajoute code, state et iss à l'URL de callback. L'appel au token endpoint s'authentifie soit par client_secret_post, soit par tls_client_auth avec un certificat ORG AUTH_CLI de l'IGC-Santé dont le CN contient le client ID. Le mTLS est disponible en production depuis le 18 février 2025 ; il est conseillé sur l'Espace Communautaire et obligatoire pour l'Espace de Confiance.
Sur PKCE : le document de découverte annonce S256, mais le tableau de paramètres de l'ANS ne le mentionne pas. Traitez-le comme une défense en profondeur et vérifiez-le sur le BAS avant de l'activer en production.
Exemple minimal avec openid-client
Exemple Node.js avec openid-client v6. Les valeurs sont des placeholders ; l'URL de callback doit être identique, octet pour octet, à celle déclarée lors de la création du service.
import * as client from 'openid-client';
const PSC_DISCOVERY = new URL(
'https://auth.bas.psc.esante.gouv.fr/auth/realms/esante-wallet/.well-known/wallet-openid-configuration'
);
const REDIRECT_URI = 'https://app.example.test/auth/psc/callback';
const config = await client.discovery(
PSC_DISCOVERY,
process.env.PSC_CLIENT_ID,
undefined,
client.ClientSecretPost(process.env.PSC_CLIENT_SECRET)
);
// Step 1: build the redirect to the PSC login page
export async function startLogin(session) {
session.codeVerifier = client.randomPKCECodeVerifier();
session.state = client.randomState();
session.nonce = client.randomNonce();
return client.buildAuthorizationUrl(config, {
redirect_uri: REDIRECT_URI,
scope: 'openid scope_all',
acr_values: 'eidas1',
state: session.state,
nonce: session.nonce,
code_challenge: await client.calculatePKCECodeChallenge(session.codeVerifier),
code_challenge_method: 'S256'
});
}
// Step 2: exchange the code server-side and read UserInfo
export async function handleCallback(session, currentUrl) {
const tokens = await client.authorizationCodeGrant(config, currentUrl, {
pkceCodeVerifier: session.codeVerifier,
expectedState: session.state,
expectedNonce: session.nonce
});
const idClaims = tokens.claims();
const userinfo = await client.fetchUserInfo(config, tokens.access_token, idClaims.sub);
return {
nationalId: userinfo.SubjectNameID,
authLevel: userinfo.auth_level,
idToken: tokens.id_token,
refreshToken: tokens.refresh_token
};
}
Derrière un reverse proxy, reconstruisez currentUrl à partir de l'URL publique : la bibliothèque en dérive le redirect_uri envoyé au token endpoint.
Ce que contiennent les jetons
Le scope choisi détermine les claims du UserInfo. Le référentiel exige scope_all, qui renvoie l'ensemble.
| Scope | Claims UserInfo |
|---|---|
openid |
sub |
profile |
codeCivilite, given_name, family_name |
rpps |
SubjectRefPro, SubjectNameID |
scope_all |
Tout le UserInfo, dont otherIds et auth_level |
Trois évolutions de 2026 changent la façon de modéliser l'utilisateur :
- Depuis le 19 mars 2026 en production,
subest un UUID technique. L'ancien format qui concaténait l'identifiant national a disparu, et un service qui indexait ses comptes sursubse retrouve avec des doublons. - Le claim
PSISubjectNameIDporte l'identifiant Pro Santé Identité, vide tant que l'utilisateur ne l'a pas activé. - Depuis le 16 avril 2026,
SubjectNameIDcontient le RPPS lorsqu'il existe pour une authentification e-CPS, etauth_levelvaut « 1 » (Standard) ou « 2 » (Certifié).
La règle reste celle d'EXI PSC 18 : clé de compte et traçabilité sur SubjectNameID, rapprochement par le RPPS via otherIds si l'utilisateur possède encore des identifiants ADELI ou locaux. La page UserInfo détaille SubjectRefPro, qui liste les exercices et activités issus de l'Annuaire Santé. Exemple synthétique, tronqué :
{
"sub": "00000000-0000-4000-8000-000000000000",
"SubjectNameID": "899999999999",
"PSISubjectNameID": "",
"auth_level": "1",
"given_name": "JANE",
"family_name": "DOE",
"otherIds": [
{ "identifiant": "899999999999", "origine": "RPPS", "qualite": 1 }
],
"SubjectRefPro": { "exercices": [{ "codeProfession": "10", "activities": [] }] }
}
PSC ne propose pas de sélection d'activité. Si votre logiciel doit savoir dans quelle structure le praticien exerce, construisez l'écran de choix à partir des activities.
Durées de vie, rafraîchissement et déconnexion
| Élément | BAS et production |
|---|---|
| Authorization code | 1 minute |
| Access token | 2 minutes |
| Refresh token | 30 minutes, glissantes |
| Session PSC maximale | 4 heures |
Un access token de deux minutes surprend souvent. EXI PSC 11 demande de rafraîchir uniquement quand l'utilisateur est actif ; l'ANS suggère de le faire au changement de page ou de rubrique. Sans activité, la session PSC expire au bout de 30 minutes.
La déconnexion est un GET vers le logout endpoint avec id_token_hint et, en option, post_logout_redirect_uri. Elle termine la session PSC sur tous les services et appareils de l'utilisateur. Le document de découverte affiche backchannel_logout_supported, mais la documentation précise que PSC ne pousse ni front-channel ni back-channel logout : pour savoir si une session vit encore, introspectez ou rafraîchissez. Le référentiel impose aussi une déconnexion automatique de votre service après inactivité, sans fermer la session PSC (EXI PSC 32).
Espace de Confiance et API Pro Santé Connectées
L'Espace Communautaire couvre l'authentification. L'Espace de Confiance va plus loin : le jeton PSC sert à appeler des services socles (DMP, ordonnance numérique et INSi dans un premier temps) via des API Pro Santé Connectées, en passant par un proxy e-Santé qui réalise l'échange de jeton auprès du serveur d'autorisation. Le mTLS y est obligatoire, les tests d'intrusion sont définis par profil de logiciel et l'accès aux environnements partenaires du CNDA exige une authentification BAS réussie et un rapport validé de l'outil de conformité du proxy. L'ANS publie un exemple de proxy e-Santé sur GitHub.
Pour le Ségur vague 2, l'habilitation EDC fait partie du parcours de référencement. L'ANS a fixé le dépôt du dossier de preuves (jalon 2) au 23 mai 2026 pour RIS et DRIMbox et au 22 juillet 2026 pour les LGC ; une preuve alternative issue du guichet EDC sur Convergence était acceptée, d'après l'actualité ANS sur l'habilitation EDC. Si votre logiciel lit l'INS, l'article sur FR Core, INS et CI-SIS explique où l'INSi s'insère.
Pièges fréquents
| Piège | Symptôme | Correction |
|---|---|---|
Découverte standard au lieu de wallet-openid-configuration |
Mire Keycloak brute, parcours e-CPS absent | Configurer l'URL de découverte complète |
Comptes indexés sur sub |
Doublons après mars 2026 | Clé sur SubjectNameID, rapprochement RPPS |
acr_values omis |
Erreur à l'autorisation ou non-conformité | Toujours envoyer eidas1 ; eidas2 n'est pas encore servi |
Contrôle d'accès sur authMode |
Refus arbitraires selon le MIE | Utiliser auth_level avec discernement, plus les attributs de SubjectRefPro |
| Refresh en tâche de fond | Session PSC prolongée sans utilisateur | Rafraîchir sur action utilisateur seulement |
| Client PAR activé par défaut | Échec de l'autorisation | PAR est annoncé mais pas activé ; le désactiver |
Apache mod_auth_openidc |
otherIds absent des en-têtes |
OIDCPassUserInfoAs json |
Checklist avant la demande de production
- Client ID et secret (ou certificat ORG AUTH_CLI) stockés uniquement côté serveur.
- Scopes,
acr_values,stateetnonceenvoyés et vérifiés. - Comptes clés sur
SubjectNameID, fusion autour du RPPS si d'autres modes de connexion existent (EXI PSC 19). - Refresh piloté par l'activité, déconnexion PSC et déconnexion locale sur inactivité.
- Données de test uniquement sur le BAS (EXI PSC 37), hébergement HDS si le service traite des données de santé (EXI PSC 06, voir l'article sur l'hébergement HDS).
- Tests réalisés avec une carte de test et une e-CPS de test, outils de PSC Tools à portée de main.
Le jeton PSC sert aussi d'authentification sur l'API LPS de la messagerie sécurisée : l'article sur l'intégration MSSanté montre comment. Côté FHIR, le lancement d'une application dans le contexte d'un DPI relève d'un autre protocole, décrit dans SMART on FHIR.
Si vous devez cadrer un raccordement PSC ou une candidature à l'Espace de Confiance, je propose un accompagnement en développement HealthTech.