Implémentation du monitoring dans le plugin OpenID Connect client pour SPIP
Le site oa.dnc.global utilise ce plugin (il est client OIDC, le serpent se mord la queue !). Vous pouvez donc voir une étiquette en haut à gauche de la fenêtre qui traduit l’état du jeton d’accès lié à la connexion courante :
icône | Signification | |
La connexion de l’utilisateur final n’est pas établie avec le serveur OIDC. Notez que l’utilisateur peut s’être connecté à l’application à l’aide de la méthode de connexion classique de SPIP. | ||
L’utilisateur final et l’application sont connectés par OIDC. | ||
Erreur générale, traduit malheureusement de multiples situations :
perte de communication Internet, défaut de configuration du plugin, défaut d’inscription de l’application cliente sur le serveur OAuthSD, inscription de l’application sur un autre serveur, non compatible OAuthSD, login inconnu du serveur OAuthSD (l’utilisateur final n’est pas inscrit sur ce serveur), etc. Le message peut éventuellement être plus explicite : "authentication error", ... |
Le Monitoring permet également de manager la session OIDC et notamment d’effectuer la déconnexion globale (SLO).
En cliquant sur l’icône, des popups apparaissent selon l’état de connexion.
Exemple du code Javascript (avec jQuery) utilisé pour SPIP. Le plugin insère ce code en pied de chaque page.
[SPIP]
- /**
- * Plugin OpenID Connect client pour SPIP
- * OIDC Client Monitoring
- * Interroge le contrôleur OIDC Authorize avec prompt=none pour afficher l'état de connexion.
- * Voir également action_logout() dans oidcclient_options.php.
- * Auteur : B.Degoy DnC
- * Copyright (c) 2019 B.Degoy
- * Licence GPL v3.0
- */
- // OIDC Client Monitoring
- <?php
- include_spip('inc/oidcclient_configuration'); ?>
- $(document).ready(function() {
- // Ajouter l'étiquette si elle n'existe pas
- if($('#oidc').length === 0){
- $('<div id="oidc"> OIDC </div> ')
- .appendTo('nav')
- .css('position','absolute')
- .css('top','12px')
- .css('left','3px')
- .css('color','white')
- .css('padding','3px');
- }
- var login = "<?php echo @$GLOBALS['visiteur_session']['login']; ?>";
- var state = "<?php echo @$GLOBALS['visiteur_session']['state']; ?>";
- if ( login !== "" ) {
- // Si on est logé localement, surveiller qu'on l'est également sur OIDC
- setInterval(function(){
- $.ajax({
- type : "get",
- url : "<?php echo OIDC_AUTHORIZATION_ENDPOINT; ?>",
- data : { 'response_type' : 'code',
- 'client_id' : "<?php echo OIDC_CLIENT_ID; ?>",
- 'user_id' : login,
- 'state' : state,
- 'scope' : 'openid',
- 'prompt' : 'none',
- },
- statusCode : {
- 401 : function(){
- // Non authentifié sur OIDC, déconnecter localement
- var url_logout_public = "<?php echo '?action=logout&logout=local&url=' . $GLOBALS['REQUEST_URI']; ?>";
- window.location.replace(url_logout_public);
- },
- 200 : function (){
- // Signaler la connexion
- $('#oidc').css('background-color', '#8f8');
- $('#oidc').text(' OIDC ');
- },
- },
- error : function(obj,textStatus,errorThrown){
- // Signaler qu'on ne sait pas
- $('#oidc').css('background-color', 'red');
- $('#oidc').text(textStatus + ' ' + errorThrown);
- }
- });
- }, 2000);
- } else {
- // Signaler la déconnexion
- $('#oidc').css('background-color', 'orange');
- $('#oidc').text(' OIDC ');
- }
- });
Implémentation du monitoring dans une extension Wordpress
Le plugin est disponible sur Github.
Le code Javascript est inséré dans un hook appelé par la fonction bootstrap() de l’extension :
[PHP]
- /**
- * OAuthSD project https://oa.dnc.global
- * OAuthSD OIDC plugin for WordPress
- * Insert monitoring code in footer
- * dnc1
- * Author : bdegoy DnC https://degoy.com
- * copyright (c) 2019 B.Degoy DnC
- * Licence GPL v3.0
- */
- function insert_monitoring() {
- // Enqueue some jQuery UIs
- wp_enqueue_script('jquery-ui-dialog'); // from WP core
- // get registered script object for jquery-ui
- global $wp_scripts;
- $ui = $wp_scripts->query('jquery-ui-core');
- // load the Smoothness theme from Google CDN
- $protocol = is_ssl() ? 'https' : 'http';
- $url = "$protocol://ajax.googleapis.com/ajax/libs/jqueryui/{$ui->ver}/themes/smoothness/jquery-ui.min.css";
- wp_enqueue_style('jquery-ui-smoothness', $url, false, null);
- // OIDC Client Monitoring
- $thisuri = $_SERVER['REQUEST_URI'];
- $absolutepath_this_plugin = plugin_dir_path( __FILE__ );
- // Server URLs
- $settings = $this->settings;
- $url_endpoint_login = $settings->endpoint_login;
- $url_endpoint_token = $settings->endpoint_token;
- $url_endpoint_userinfo = $settings->endpoint_userinfo;
- $url_endpoint_logout = $settings->endpoint_end_session;
- $url_server = $parts['scheme'] . '://' . $parts['host'];
- // OIDC user
- $clientID = $settings->client_id;
- // $userID = ???
- // WP user
- $user = get_user_by('id', get_current_user_id());
- $login = $user->user_login;
- $nom_auteur =$user->display_name;
- // for info popup
- $infos =
- '<br/>' . __('oidcclient:serveur_url','openid-connect-generic') . ' : <a href="' . $url_server . '">' . $url_server . '</a>' .
- '<br/>' . __('oidcclient:client_id','openid-connect-generic') . ' : ' . $clientID .
- '<br/>' . __('oidcclient:login_wp','openid-connect-generic') . ' : ' . $login .
- //'<br/>' . __('oidcclient:login_oidc_court','openid-connect-generic') . ' : ' . $userID .
- '<br/>' . __('oidcclient:nom_auteur','openid-connect-generic') . ' : ' . $nom_auteur;
- // labels and messages
- $msg_session_connected_no = __('oidcclient:session_connected_no','openid-connect-generic');
- $msg_session_connected_yes = __('oidcclient:session_connected_yes','openid-connect-generic');
- $msg_session_connected_error = __('oidcclient:session_connected_error','openid-connect-generic');
- $msg_session_open = __('oidcclient:session_open','openid-connect-generic');
- $msg_session_extend = __('oidcclient:session_extend','openid-connect-generic');
- $msg_session_close = __('oidcclient:session_close','openid-connect-generic');
- $msg_session_expires = __('oidcclient:session_expires','openid-connect-generic');
- $lbl_yes = __('oidcclient:item_yes','openid-connect-generic');
- $lbl_no = __('oidcclient:item_no','openid-connect-generic');
- $lbl_t_session_restant = __('oidcclient:t_session_restant','openid-connect-generic');
- $lbl_delai_reponse = __('oidcclient:delai_reponse','openid-connect-generic');
- $lbl_infos_titre = __('oidcclient:lbl_infos_titre','openid-connect-generic');
- // link to OIDC login
- $link_login = $this->client_wrapper->get_authentication_url();
- // link to logout page
- $url_logout = esc_url($url_this_plugin . "/oidc_logout.php?url=" . $_SERVER['REQUEST_URI']);
- echo <<<JSCODE
- <script type="text/javascript">
- (function($) {
- var login = "$login";
- var timeleft = 0;
- var connected = 0;
- var connectionMsg = '';
- var interval = null;
- var pollperiod = 60000;
- var tagappendto = '#content';
- var tagtop = '120px';
- var tagleft = '16px';
- var responseDelay = 'Unk';
- $(document).on('ready',function(){
- // Add OIDC labels
- if($('#oidc').length === 0){
- $('<div id="oidc"><span id="oidctag"> OIDC </span><span id="oidcinfo"> ? </span></div>')
- .appendTo(tagappendto);
- //
- $('#oidc')
- .css('position','absolute')
- .css('top',tagtop)
- .css('left',tagleft);
- //
- $('#oidctag')
- .css('color','white')
- .css('padding','3px')
- .css('z-index','10000')
- .on('click', function(){
- switch (connected) {
- case 0 :
- connectionMsg = "$msg_session_connected_no";
- SessionOpenDialog(connectionMsg);
- break;
- case 1 :
- connectionMsg = "$msg_session_connected_yes";
- SessionCloseDialog(connectionMsg);
- break;
- default :
- case -1 :
- connectionMsg = "$msg_session_connected_error";
- break;
- };
- });
- //
- $('#oidcinfo')
- .css('color','white')
- .css('padding','3px')
- .css('z-index','10001')
- .css('background-color','#09f')
- .on('click', function(){
- $('<div></div>').appendTo('body')
- .html('<div><h6>$infos<br/>$lbl_t_session_restant : ' + timeleft + ' s<br/>$lbl_delai_reponse : ' + responseDelay + ' ms</h6></div>')
- .dialog({
- modal: true, title: "$lbl_infos_titre", zIndex: 10000, autoOpen: true,
- width: 'auto', resizable: false,
- close: function (event, ui) {
- $(this).remove();
- interval = setInterval(pollOidc,pollperiod);
- }
- });
- }
- );
- }
- // If user is logged locally, verify the OIDC session is valid.
- if ( login !== "" ) {
- pollOidc();
- interval = setInterval(pollOidc,pollperiod);
- } else {
- connected = 0;
- // Show not OIDC connected.
- $('#oidctag').css('background-color', 'orange');
- $('#oidctag').text(' OIDC ');
- }
- function SessionCloseDialog(message) { //[dnc28d]
- clearInterval(interval);
- $('<div></div>').appendTo('body')
- .html('<div><h6>'+message+'?</h6></div>')
- .dialog({
- modal: true, title: "$msg_session_close", zIndex: 10000, autoOpen: true,
- width: 'auto', resizable: false,
- buttons: [
- {
- text: "$lbl_yes",
- click: function () {
- // Close the OIDC session.
- window.location.replace("$url_logout");
- $(this).dialog("close");
- }
- },{
- text: "$lbl_no",
- click: function () {
- $(this).dialog("close");
- interval = setInterval(pollOidc,pollperiod);
- }
- }
- ],
- close: function (event, ui) {
- $(this).remove();
- interval = setInterval(pollOidc,pollperiod);
- }
- });
- };
- function SessionOpenDialog(message) { //[dnc28d]
- clearInterval(interval);
- $('<div></div>').appendTo('body')
- .html('<div><h6>'+message+'?</h6></div>')
- .dialog({
- modal: true, title: "$msg_session_open", zIndex: 10000, autoOpen: true,
- width: 'auto', resizable: false,
- buttons: [
- {
- text: "$lbl_yes",
- click: function () {
- // Se connecter
- window.location.replace("$link_login");
- $(this).dialog("close");
- }
- },{
- text: "$lbl_no",
- click: function () {
- $(this).dialog("close");
- interval = setInterval(pollOidc,pollperiod);
- }
- }
- ],
- close: function (event, ui) {
- $(this).remove();
- interval = setInterval(pollOidc,pollperiod);
- }
- });
- };
- function ExtendDialog(message) { //[dnc28d]
- if ( !$("#extenddialog").size() ) { //[dnc28f]
- clearInterval(interval);
- $('<div id="extendeddialog"></div>').appendTo('body')
- .html('<div><h6>'+message+'?</h6></div>')
- .dialog({
- modal: true, title: "$msg_session_extend", zIndex: 10000, autoOpen: true,
- width: 'auto', resizable: false,
- buttons: [
- {
- text: "$lbl_yes",
- click: function () {
- // Extend session
- $.ajax({
- type : "get",
- url : "$url_endpoint_login",
- data : { 'response_type' : 'code',
- 'client_id' : "$clientID",
- 'user_id' : login,
- 'state' : "$state",
- 'scope' : 'openid sli',
- }
- });
- $(this).dialog("close");
- interval = setInterval(pollOidc,pollperiod);
- }
- },{
- text: "$lbl_no",
- click: function () {
- $(this).dialog("close");
- interval = setInterval(pollOidc,pollperiod);
- },
- }
- ],
- close: function (event, ui) {
- $(this).remove();
- interval = setInterval(pollOidc,pollperiod);
- },
- });
- }
- };
- // Test OIDC connection.
- function pollOidc(){
- connected = -1;
- var d = new Date();
- var timeStart = d.getTime();
- var timeStop = 0;
- $.ajax({
- type : "get",
- url : "$url_endpoint_login",
- data : { 'response_type' : 'code',
- 'client_id' : "$clientID",
- 'user_id' : login,
- 'state' : "$state",
- 'scope' : 'openid',
- 'prompt' : 'none',
- },
- statusCode : {
- 401 : function(){
- connected = 0;
- var d = new Date();
- timeStop = d.getTime();
- // Not (or no longer) connected on OIDC, disconnect locally
- window.location.replace("$url_logout" +"&logout=local");
- },
- 200 : function ( data, textStatus, jqXHR){
- connected = 1;
- var d = new Date();
- timeStop = d.getTime();
- // Show OIDC connected
- $('#oidctag').css('background-color', '#8f8');
- $('#oidctag').text(' OIDC ');
- timeleft = data['timeleft'];
- if ( timeleft < 600 ) { //[dnc28d]
- // Approaching OIDC session end.
- clearInterval(interval);
- ExtendDialog("$msg_session_expires");
- interval = setInterval(pollOidc,pollperiod);
- }
- },
- },
- error : function(obj,textStatus,errorThrown){
- connected = -1;
- // Show error (OIDC state is unknown)
- $('#oidctag').css('background-color', 'red');
- $('#oidctag').text(textStatus + ' ' + errorThrown);
- },
- complete : function ( data, textStatus, jqXHR){
- if ( timeStop && timeStart ) {
- responseDelay = timeStop - timeStart;
- } else {
- responseDelay = 'Unk';
- }
- },
- });
- }
- });
- })( jQuery );
- </script>
- JSCODE
- ;
- } //function
Notons qu’il faut insérer un bloc div en bas de page, ce qui est fait au moyen d’une action dans la fonction bootstrap en même temps que le hook de la fonction précédente :
[PHP]
- //OIDC Monitoring
- wp_enqueue_script("jquery");