diff --git a/FEATURES/68179 b/FEATURES/68179
new file mode 100644
index 0000000000000000000000000000000000000000..95f056be45db4e4fc5833a3de806cf24ea93cccc
--- /dev/null
+++ b/FEATURES/68179
@@ -0,0 +1,10 @@
+        '68179' =>
+            ['Label' => $this->_('[Contractuel] Connecteur : Storyplayr contactuel'),
+             'Desc' => '',
+             'Image' => '',
+             'Video' => '',
+             'Category' => '',
+             'Right' => function($feature_description, $user) {return true;},
+             'Wiki' => '',
+             'Test' => '',
+             'Date' => '2018-03-23'],
\ No newline at end of file
diff --git a/VERSIONS_WIP/68179 b/VERSIONS_WIP/68179
new file mode 100644
index 0000000000000000000000000000000000000000..b413c4b37b6c2d26b0efe28be6427e25d96dfa5a
--- /dev/null
+++ b/VERSIONS_WIP/68179
@@ -0,0 +1 @@
+ - ticket #68179 : [Contractuel] Connecteur : Storyplayr contactuel
\ No newline at end of file
diff --git a/application/modules/admin/controllers/IndexController.php b/application/modules/admin/controllers/IndexController.php
index 19ea63e21fc1eae6a88d13885fe30d43535ec0af..c1e165ed32375d357bb7817c89ae62caa798aeb4 100644
--- a/application/modules/admin/controllers/IndexController.php
+++ b/application/modules/admin/controllers/IndexController.php
@@ -51,18 +51,9 @@ class Admin_IndexController extends ZendAfi_Controller_Action {
 
 
   public function adminvarAction() {
-    $existing_variables = Class_AdminVar::findAllBy(['order' => 'CLEF']);
-    $existing_clefs = [];
-    foreach ($existing_variables as $var)
-      $existing_clefs[] = $var->getId();
-
-    // creer les variables manquantes
-    foreach (Class_AdminVar::getKnownVarsKeys() as $name)
-      if (!in_array($name, $existing_clefs))
-        $existing_variables[] = Class_AdminVar::set($name, Class_AdminVar::getValueOrDefault($name));
-
+    Class_AdminVar::init();
     $this->view->titre = $this->_('Gestion des variables');
-    $this->view->vars = Class_AdminVar::filterByUserRole($existing_variables);
+    $this->view->vars = Class_AdminVar::filterByUserRole(Class_AdminVar::findAllBy(['order' => 'CLEF']));
   }
 
 
diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php
index 60796c91e62b51a482601ffdf202dbac7190c0e7..eba089f45b0593a8330535f9a8a7258cb2ac7133 100644
--- a/library/Class/AdminVar.php
+++ b/library/Class/AdminVar.php
@@ -26,6 +26,25 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
   /** @var array */
   protected $all_vars;
 
+  protected $_inited = false;
+
+  public function init() {
+    if ($this->_inited)
+      return $this;
+
+    $keys = (new Storm_Model_Collection(Class_AdminVar::findAllBy(['order' => 'CLEF'])))
+      ->collect('clef')
+      ->getArrayCopy();
+
+    foreach (Class_AdminVar::getKnownVarsKeys() as $key)
+      if (!in_array($key, $keys))
+        Class_AdminVar::set($key, Class_AdminVar::getValueOrDefault($key));
+
+    $this->_inited = true;
+
+    return $this;
+  }
+
 
   /**
    * @param string $name
@@ -949,6 +968,7 @@ class Class_AdminVar extends Storm_Model_Abstract {
 
   protected $_fixed_id = true;
 
+
   public function getValeur() {
     return $this->_get('valeur');
   }
diff --git a/library/Class/DigitalResource/Config.php b/library/Class/DigitalResource/Config.php
index 085771f4cf6c99d79c15bcac1d4e51ed9402f8b1..0b2139bc2fc24ef6329c1026ec821335f2f807e0 100644
--- a/library/Class/DigitalResource/Config.php
+++ b/library/Class/DigitalResource/Config.php
@@ -86,6 +86,7 @@ class Class_DigitalResource_Config extends Class_Entity {
 
 
   public function getAdminVarsInstances() {
+    Class_AdminVar::init();
     $vars = [];
     foreach($this->getAdminVars() as $key => $meta)
       $vars [] = $this->getDigitalResource()->getAdminVarInstance($key);
diff --git a/library/ZendAfi/View/Helper/DigitalResource/Dashboard.php b/library/ZendAfi/View/Helper/DigitalResource/Dashboard.php
index da5d8f85ca40d2cae00556d1ba5d8ad2f347e207..ea27273ff02dfe671d9a635d41e05b118761128e 100644
--- a/library/ZendAfi/View/Helper/DigitalResource/Dashboard.php
+++ b/library/ZendAfi/View/Helper/DigitalResource/Dashboard.php
@@ -101,9 +101,13 @@ class ZendAfi_View_Helper_DigitalResource_Dashboard extends ZendAfi_View_Helper_
                                                                 'label' => $this->_('Modifier "%s"', $model->getClef())]]);
                      });
 
-    return
-      $this->_tag('h3', $this->_('Paramétrage'))
-      . $this->view->renderTable($description, $this->_config->getAdminVarsInstances(), ['sorter' => true]);
+    $html = ($table = $this->view->renderTable($description,
+                                               $this->_config->getAdminVarsInstances(),
+                                               ['sorter' => true]))
+      ? $table
+      : $this->_tag('p', $this->_('Veuillez vérifier le fichier config.php de la ressource pour pouvoir gérer le paramétrage'), ['class' => 'error']);
+
+    return $this->_tag('h3', $this->_('Paramétrage')) . $html;
   }
 
 
diff --git a/library/ZendAfi/View/Helper/RenderTable.php b/library/ZendAfi/View/Helper/RenderTable.php
index e5693da8dea3649bf9197ea1b37f2823035374fa..653c1efdd4f40ed13fbe5685da0a60b705a21cba 100644
--- a/library/ZendAfi/View/Helper/RenderTable.php
+++ b/library/ZendAfi/View/Helper/RenderTable.php
@@ -30,6 +30,9 @@ class ZendAfi_View_Helper_RenderTable extends ZendAfi_View_Helper_BaseHelper {
     if(!$grouped_models)
       return '';
 
+    if(!array_filter($grouped_models))
+      return '';
+
     $grouped_models = (is_array($grouped_models) || is_a($grouped_models, 'ArrayObject'))
       ? new Class_TableDescription_Models($grouped_models)
       : $grouped_models;
diff --git a/library/digital_resources/StoryPlayR/Config.php b/library/digital_resources/StoryPlayR/Config.php
new file mode 100644
index 0000000000000000000000000000000000000000..975654cef0102639a12f79d2e29be8959e5c599c
--- /dev/null
+++ b/library/digital_resources/StoryPlayR/Config.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class StoryPlayR_Config extends Class_DigitalResource_Config {
+  public function getConfig() {
+    return ['Introduction' => $this->_('Plusieurs centaines d\'albums jeunesse et livres audio !'),
+            'AdminVars' => ['SSO_URL' => Class_AdminVar_Meta::newDefault($this->_('URL SSO de la plateforme StoryPlay*r'))
+                            ->bePrivate()],
+            'PermissionLabel' => $this->_('Bibliothèque numérique: accéder aux albums StoryPlay*r'),
+            'SsoAction' => true,
+            'Harvesting' => true,
+
+            'HelpLink' => 'http://wiki.bokeh-library-portal.org/index.php/StoryPlayR',
+            'Url' => 'https://www.storyplayr.com/',
+            'Icon' => 'https://www.storyplayr.com/images/v2/logo.png',
+
+            'MenuLabel' => $this->_('Lien vers StoryPlay*r'),
+            'ModuleMenu' => $this->withNameSpace('ModuleMenu'),
+            'NotAllowedMessage' => $this->_('Vous devez être abonné pour accéder à cette ressource.'),
+    ];
+  }
+
+
+  public function getSsoUrl($user) {
+    return $this->getAdminVar('SSO_URL');
+  }
+
+
+  public function isEnabled() {
+    return '' != $this->getAdminVar('SSO_URL');
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/digital_resources/StoryPlayR/controllers/IndexController.php b/library/digital_resources/StoryPlayR/controllers/IndexController.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3f247ae5dfd44f8cbfff2fa6171dc75447d9d7a
--- /dev/null
+++ b/library/digital_resources/StoryPlayR/controllers/IndexController.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+class StoryPlayR_Plugin_IndexController extends Class_DigitalResource_Controller {}
\ No newline at end of file
diff --git a/library/digital_resources/StoryPlayR/tests/StoryPlayRTest.php b/library/digital_resources/StoryPlayR/tests/StoryPlayRTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..80eb4ba44024126cc05716d1d5065759cc87d02c
--- /dev/null
+++ b/library/digital_resources/StoryPlayR/tests/StoryPlayRTest.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class StoryPlayRSsoTest extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
+
+  public function setUp() {
+    parent::setUp();
+
+    Class_AdminVar::set('StoryPlayR_SSO_URL', 'https://www.storyplayr.com/');
+
+    $group = $this->fixture('Class_UserGroup',
+                            ['id' => 1]);
+
+    $user = $this->fixture('Class_Users',
+                           ['id' => 1,
+                            'login' => 'Tom',
+                            'password' => 'pwd'])
+                 ->setUserGroups([$group]);
+
+    $this->fixture('Class_Permission',
+                   ['id' => 1,
+                    'code' => 'StoryPlayR'])
+         ->permitTo($group,  new Class_Entity());
+
+    ZendAfi_Auth::getInstance()->logUser($user);
+    $this->dispatch('/opac/modules/story-play-r', true);
+  }
+
+
+  /** @test */
+  public function shouldRedirectToStoryPlayer() {
+    $this->assertXPathContentContains('//script' , 'document.location.href="https://www.storyplayr.com/";', $this->_response->getBody());
+  }
+}
+
+
+
+
+class StoryPlayRDashboardTest extends Admin_AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/StoryPlayR_Plugin', true);
+  }
+
+
+  /** @test */
+  public function shouldDisplayActivated() {
+    $this->assertXPathContentContains('//button', 'Désactivé');
+  }
+
+
+  /** @test */
+  public function ssoUrlShoudlBeDisplay() {
+    $this->assertXPathContentContains('//table', 'StoryPlayR_SSO_URL');
+  }
+}
\ No newline at end of file