Raccordement avec un portail métier (SSO)

Objectif de cette note : rappeler à l'éditeur d'un portail métier les standards SSO et plus précisément les impératifs pour se raccorder à un portail Publik. Ce texte pourra être inclus avec profit par les collectivités directement dans leur CCTP afin qu'il s'impose à l'éditeur métier.
Entr'ouvert ne fournit pas de base d'assistance à l'intégration ou à la spécification fonctionnelle d'un SSO. Si souhaité, cette assistance nécessitera un contrat de prestation auprès de la collectivité ou de l'éditeur/intégrateur du portail de l'éditeur métier.

Les fonctionnalités prévus lors d'un raccordement métier seront :

Authentification unique

Publik propose un seul mode de raccordement via le protocole OpenID Connect (OIDC), les spécifications à respecter sont :

Les spécifications désignées DOIVENT être respectées à la lettre, le nommage des attributs ("claim") et des scopes peut, par contre, être adapté.

Des implémentations de référence du protocole OpenID Connect pour différents langages et cadriciels sont disponibles sur https://openid.net/developers/libraries/

Le portail métier et ses éventuels web-services DOIVENT absolument être diffusés via le protocole HTTPS://.

Une authentification réussie fournit au portail un pseudonyme opaque appelé "sub" dans le jargon OpenID Connect, c'est une chaîne UTF-8 qui devra être conservé dans le schéma de donnée du portail et lié au compte du portail métier. La relation entre ce pseudonyme et les comptes du portail métier pourra être : Ce choix dépendra des usages et de la possibilité pour l'éditeur du portail de gérer les parcours de connexion nécessaire avec par exemple : La processus de raccordement à des comptes existants (nommé aussi appairage), ou de création d'un nouveau compte suite à une authentification unique (SSO) réussie, relève de la seule responsabilité du portail métier mais on notera les cas suivants :

Pré-requis

L'intégrateur du portail métier devra fournir à un administrateur de la plateforme Publik les informations suivantes :

Attention : si les URLs de redirection ont des domaines différents et l'UUID n'est pas utilisé comme identifiant, penser à définir une URL de secteur.

L'administrateur de la plateforme Publik transmettra à l'intégrateur du portail métier :

Toutes les opérations de connexion ou déconnexion se font via des appels au fournisseur d'identité de la plateforme Publik de la collectivité, on désignera son URL par IDP_URL.

Description technique non-exhaustive de l'authentification unique

Une authentification unique débutera comme suit :
1. déclenchement de l'authentification sur le portail (appui sur un bouton, appel à une URL particulière, protection de toutes les pages du portail, c'est un point d'implémentation qui relève de l'éditeur du portail métier)

2. redirection du navigateur de l'utilisateur sur l'URL d'autorisation OpenID Connect du fournisseur d'identité de la plateforme Publik:
IDP_URL/idp/oidc/authorize/?client_id=...&...&redirect_uri=...&state=...&...

3. le fournisseur d'identité de la plateforme Publik procède à l'authentification de l'usager, s'il n'est pas déjà authentifié, puis s'il n'a pas encore donné son autorisation lui présente un formulaire lui demandant de confirmer sa volonté de s'authentifier auprès du portail en fournissant un certain nombre d'attributs.

4. le fournisseur d'identité Publik redirige le navigateur de l'utilisateur sur l'URL de retour (ou de callback) déclaré par le portail métier par exemple,

https://portail-metier.collectivite.fr/oidc/callback/?code=xxx&state=yyy

5. le portail métier à la réception de cette requête doit :
5.1. éventuellement utiliser le paramètre state pour retrouver un état conservé (URL de retour sur le portail, identifiant métier de la personne demandé préalablement, jeton transmis par mail ou SMS permettant l'appairage, etc...) en session
5.2. appeler le web-service token (IDP_URL/ipd/oidc/token/) du fournisseur d'identité en s'authentifiant avec son client_id et son client_secret (fourni lui aussi par l'administrateur de la plateforme Publik) permettant d'échanger code contre un access_token ; l'access token est un jeton qui permettra d'appeler le web-service fournissant les informations sur l'utilisateur. Le web-service token fournit aussi le sub ou identifiant unique de l'utilisateur, c'est cet identifiant qui sert de clé à la liaison entre Publik et le portail-métier. Enfin, le web-service token fournit deux valeurs iss (identifiant de l'émetteur) et sid (identifiant de la session) qui doivent être enregistrés dans la session créée sur le portail métier, en vue d'assurer la mécanique de déconnexion (voir plus bas).

5.3. appeler le web-service user-info (IDP_URL/idp/oidc/user_info/) pour obtenir les attributs de l'utilisateur qui lui sont autorisés.

5.4. déterminer si le sub est connu

Description technique non-exhaustive de la déconnexion unique

La déconnexion pourra avoir lieu :

SLO initié par Publik (Frontchannel Logout)

Voir http://openid.net/specs/openid-connect-frontchannel-1_0.html#RPLogout

La plateforme Publik procédera à une re-direction sur l'URL frontchannel_logout_uri via une iframe invisible, le portail métier devra procéder à la déconnexion de la session en cours sur toute requête à cette URL et faire en sorte qu'elle ne puisse jamais être mise en cache par le navigateur.

Deux paramètres sont envoyés dans la query-string de l'URL frontchannel_logout_uri : iss et sid. Ce sont ceux qui ont été reçus lors de l'appel au web-service token au début de la création de la session (voir plus haut). Ces deux paramètres permettent de retrouver la session en jeu sur le portail métier, et de la détruire afin d'assurer la déconnexion.

Note : il convient de régler les entêtes de sécurité de l'URL pour que celle-ci soit utilisable dans une iframe. Notamment il ne faut pas renvoyer d'entête de restriction X-Frame-Options, ni de limitation via Content-Security-Policy.

SLO inité par le portail métier (RP initiated Logout)

Voir https://openid.net/specs/openid-connect-rpinitiated-1_0.html

Le portail-métier devra rediriger le navigateur de l'utilisateur sur l'URL IDP_URL/idp/oidc/logout/, il pourra passer une URL de retour via le paramètre post_logout_redirect_uri. Cette URL devra être préalablement déclarée auprès de l'administrateur Publik.

Remontée d'information

Publik propose un point d'entrée unique pour la gestion de la relation usager, à ce titre il est important que Publik puisse centraliser toutes les informations importantes des portails métiers tiers. Pour cela nous proposons la possibilité d'appeler des web-services portés par les portails métiers en vue d'afficher des informations dans les pages du portail citoyen de Publik.

Pré-requis

Affichage de demandes en cours dans le portail-métier

Publik étant spécialisé dans la mise en place de télé-services, il y a un formalisme particulier à adopter pour faire remonter des demandes dans le portail Publik.

Ce téléservice devra répondre sur un GET et prendre en entrée le sub comme paramètre de l'URL (le chemin de l'URL n'est pas imposé). La réponse devra avoir la forme exacte suivante :

GET /api/demandes/?sub=xxx

{
  "err": 0,
  "data": [
     {
        "datetime": "2018-03-04 12:34:32",
        "name": "Demande de carte de stationnement",
        "status": "En attente d'information",
        "form_number": "1234",
        "form_status_is_endpoint": false,
        "url": "https://portail-metier/demandes/1234/",
        "draft": false
     }
  ]
}
Champ Type Obligatoire Description
datetime string, la date au format ISO8601 YYYY-MM-DD HH:MM:SS Oui la date de création de la demande
name string Oui le nom du type de demande
form_number string Oui l'identifiant de la demande (numéro ou autre)
url string Oui lien profond vers la demande, si une URL par demande n'est pas disponible le portail métier peut se contenter de renvoyer l'URL d'une page affichant toutes les demandes en cours
status string Oui le statut actuel de la demande, "Nouvelle", "En cours", "En attente d'information", à définir par le portail mais la chaîne doit être présentable directement à l'usager, ce ne doit pas être un code
form_status_is_endpoint booléen Non vrai si le statut de la demande indique qu'elle est terminée
draft booléen Non vrai si la demande est un brouillon

Affichage des factures en cours venant du portail-métier

Publik contient nativement un système de remontée et paiement de factures, pour permettre une intégration des factures exposées par un portail métier tiers, il y a là aussi un formalisme particulier à respecter.

Le portail métier DOIT fournir un web-services porté par une URL de base que nous nommerons BASE_URL, de la forme BASE_URL/invoices/, le dernier élément du chemin est obligatoire.

Ce téléservice devra répondre sur un GET et prendre en entrée le sub comme paramètre de l'URL (le chemin de l'URL n'est pas imposé). La réponse devra avoir la forme exacte suivante :

GET /api/invoices/?sub=xxx

{
   "err": 0,
   "data": [
              {
            "id": "939456",
            "label": "restauration août 2015",
            "amount": "37.26",
            "total_amount": "37.26",
            "created": "2015-08-01",
            "pay_limit_date": "2015-09-29",
            "paid": false,
            "no_online_payment_reason": "litigation",
            "payment_url": "https://portail-metier/factures/934395/pay/",
            "pdf_url": "https//portail-metier/factures/934395/pdf/F20180192.pdf",
             ... (autres informations si le logiciel backend en donne) 
        },
   ]
}
Champ Type Obligatoire Description
id string, libre Oui identifiant interne au portail métier de la facture, uniquement pour debug
amount string, décimal Oui montant du reste à payer, nombre décimal formaté avec un point décimal et non une virgule décimale (à l'anglaise)
total_amount string, décimal Oui montant total de la facture, format identique à amount
created string, date ISO Oui date de création de la facture, format ISO8601 YYYY-MM-DD
pay_limit_date string, date ISO Oui date limite de paiement de la facture, date exlue (i.e. à partir de cette date le paiement n'est plus possible), format ISO8601 YYYY-MM-DD
payment_url string, URL Non l'URL pour payer la facture si celle-ci est payable en ligne
pdf_url string, URL Non l'URL vers le PDF de la facture si celle-ci est téléchargeable
non_online_payment_reason sttring, enum Non si payment_url est absent, la raison éventuelle de la non-possibilité de paiement en ligne (contestation, prélèvement, délai dépassé), voir plus loin les valeurs possibles
Les valeurs actuellement possibles pour no_online_payement_reason sont :
Valeur Description
litigation la facture pose un problème
autobilling la facture est payée par prélèvement automatique
past_due_date il n'est plus possible de payer cette facture en ligne car un délai est dépassé

Remontée d'autres informations1

Pour tout autre type d'information nous imposons le formalisme générique suivant, en plus des pré-requis donnés plus haut : Ce web-service retournera une description du formatage attendu pour ces donnés selon le formalisme suivant :
Type Description
block un bloc composé d'autres éléments, permet de grouper
text un paragraphe, peut contenir un texte simple, pré-formaté ou formaté en HTML, en utilisant uniquement les balises autorisés dans un noeud <p> du HTML (balises inline, <em/>, <i/>, <b/>), ainsi qu'un lien d'édition (pictogramme stylo dans le coin haut-droit du contenu)
table un tableau, contenant des lignes qui contiennent soit des entête header soit des cellules de contenu text
Tous les types acceptent les attributs suivants :

Exemple de présentation d'un profil famille venant d'un portail famille :

{
  "err": 0,
  "data": {
     "type": "block",
     "label": "Ma famille",
     "edit_url": "https://portail-famille/ma-famille/edit/",
     "content": [
         {
            "type": "text",
            "id": "adresse",
            "label": "Adresse",
            "pre": true,
            "content": "1 rue du calvaire\nXX100 MAVILLE" 
         },
         {
            "type": "text",
            "id": "parent1",
            "class": "parent",
            "label": "Premier parent",
            "html": true,
            "content": "Jean-Michel <b>DUPOND</b>, né le 12 décembre 1964 à Marseille",
         },
         {
            "type": "text",
            "id": "parent2",
            "class": "parent",
            "label": "Second parent",
            "html": true,
            "content": "Régine <b>DUPOND</b>, né MARTIN le 12 décembre 1964 à Lyon" 
         }
         {
            "type": "block",
            "label": "Enfants",
            "content": [
               {
                  "type": "text",
                  "content": "Kévin DUPOND, 5 ans, né le 22 mars 2013",
               }
            ]
         }
      ]
   }
}

Le but de ce formalisme est de laisser à la fois un peu de liberté au portail métier sur les contenus et aussi la liberté pour Publik d'appliquer des feuilles de style aux contenus.

Coté Publik, ces contenus seront présentés via des cellules JSON (cellule associant un web-service JSON avec un template).

1 technologie équivalente https://github.com/portabletext/portabletext

Dépôt d'une demande

Voir https://doc-publik.entrouvert.com/dev/echanges-logiciel-de-demandes-metier/ en sachant que l'information « sub » peut être envoyée dans la demande si elle doit être reliée à un compte dans le logiciel cible.