diff --git a/VERSIONS_STABLE/hotline_#18075_fix__private_profil_and_rewrite_url b/VERSIONS_STABLE/hotline_#18075_fix__private_profil_and_rewrite_url
new file mode 100644
index 0000000000000000000000000000000000000000..599c7213861e954f230491a523f61e4f1532801d
--- /dev/null
+++ b/VERSIONS_STABLE/hotline_#18075_fix__private_profil_and_rewrite_url
@@ -0,0 +1 @@
+ - ticket: #18075: les profils sont privés par héritage. L'accès à un profil privé via sa réécriture d'url fonctionne correctement.
\ No newline at end of file
diff --git a/library/Class/Profil.php b/library/Class/Profil.php
index 455e54be7d7c9cadad62d3767903672dc04734aa..54189d465716c1e3048293dc259f66db7f85fce6 100644
--- a/library/Class/Profil.php
+++ b/library/Class/Profil.php
@@ -1213,7 +1213,22 @@ class Class_Profil extends Storm_Model_Abstract {
 	 * @return bool
 	 */
 	public function isPublic() {
-		return (int)$this->getAccessLevel() === -1;
+		$access_level = (int)$this->getAccessLevel();
+		if($this->hasParentProfil() && $access_level === -1)
+			return $this->getParentProfil()->isPublic();
+		return $access_level === -1;
+	}
+
+
+	public function getAccessLevel() {
+		if($access_level = parent::getAccessLevel())
+			return $access_level;
+
+		if(!$parent_profil = $this->getParentProfil())
+			return $access_level;
+
+		return $parent_profil->getAccessLevel();
+
 	}
 
 
diff --git a/library/ZendAfi/Controller/Plugin/DefineURLs.php b/library/ZendAfi/Controller/Plugin/DefineURLs.php
index 3dacd872909e2840d3a573927c57b1970414e17d..4d3f5a579ccfb22af2fdb40c74f5d8e9c3624f83 100644
--- a/library/ZendAfi/Controller/Plugin/DefineURLs.php
+++ b/library/ZendAfi/Controller/Plugin/DefineURLs.php
@@ -16,7 +16,7 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 //////////////////////////////////////////////////////////////////////////////////////////
 // OPAC3 :	Activation du profil et du skin
@@ -33,7 +33,7 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
 		$module = $this->getModuleNameForProfilAndRequest($profil, $request);
 		$profil->setSkin($request->getParam('skin',$profil->getSkin()));
 		$this->setUpSkin($module, $profil);
-		
+
 
 		if ($module=="admin")
 			$this->setUpBibZoneFilters($request);
@@ -46,29 +46,26 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
 
 
 	public function findProfilTelephoneId() {
-		if (!$profil = Class_Profil::getLoader()->findFirstBy(array('BROWSER' => 'telephone'))) 
+		if (!$profil = Class_Profil::getLoader()->findFirstBy(array('BROWSER' => 'telephone')))
 			return 0;
 		return $profil->getId();
 	}
 
-	
-	public function selectProfilFromRequest($request) {
-		$requested_module = $request->getModuleName();
 
-		// Initialisation du profil
-		$id_profil = ($requested_module === 'admin') ? 0 : (int)$request->getParam('id_profil');
-		
-		if ($id_profil <= 0 && ($this->_session->id_profil) && ($requested_module !== 'telephone'))
+	protected function selectProfilFromRequest($request) {
+		$id_profil = $this->getIdProfilFromRequest($request);
+
+		if ($id_profil <= 0 && ($this->_session->id_profil) && ($request->getModuleName() !== 'telephone'))
 				$id_profil = intval($this->_session->id_profil);
-		
+
 		if ($id_profil <= 0 && $this->shouldSelectTelephone($request))
 				$id_profil = $this->findProfilTelephoneId();
 
 		if ($id_profil <= 0)
 			$id_profil = 1;
-			
-		if (!$profil = Class_Profil::getLoader()->find($id_profil))
-			$profil = Class_Profil::getLoader()->findFirstBy(array('order' => 'id_profil'));
+
+		if (!$profil = Class_Profil::find($id_profil))
+			$profil = Class_Profil::findFirstBy(['order' => 'id_profil']);
 
 		$this->_session->id_profil = $profil->getId();
 
@@ -76,30 +73,41 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
 	}
 
 
-	public function memorizeLastProfil() {
+	protected function getIdProfilFromRequest($request) {
+		if($request->getModuleName() === 'admin')
+			return 0;
+
+		if (!$profil = Class_Profil::findFirstBy(['rewrite_url' => $request->getControllerName()]))
+			return (int)$request->getParam('id_profil', 0);
+
+		return $profil->getId();
+	}
+
+
+	protected function memorizeLastProfil() {
 		$this->_session->previous_id_profil = isset($this->_session->id_profil) ? $this->_session->id_profil : 1;
 		return $this;
 	}
 
 
-	public function getModuleNameForProfilAndRequest($profil, $request) {
+	protected function getModuleNameForProfilAndRequest($profil, $request) {
 		$module = $requested_module = $request->getModuleName();
 		if (('telephone' == $profil->getBrowser()) &&  ($requested_module != 'admin'))
 			$module = 'telephone';
 
 		if ($requested_module == 'telephone' && $profil->getBrowser() == 'opac')
 			$module = 'opac';
-			
+
 		/**
 		 * Si l'ouverture du profil nécessite un niveau d'accès et que
 		 * le niveau requis est trop faible, on redirige sur la page de login
-		 */		
+		 */
 		if (!$profil->isPublic()) {
 			$auth = ZendAfi_Auth::getInstance();
 			if (!$auth->hasIdentity() or	$auth->getIdentity()->ROLE_LEVEL < $profil->getAccessLevel()) {
-        if ($module != 'admin' && !$auth->hasIdentity()) {
+        if ($module != 'admin') {
           $redirect = '?redirect=' . urlencode('/index/index/id_profil/' . $profil->getId());
-          $this->getResponse()->setRedirect(BASE_URL . '/auth/login/id_profil/1' . $redirect);
+          return $this->getResponse()->setRedirect(BASE_URL . '/auth/login/id_profil/1' . $redirect);
         }
 				$request->setControllerName('auth');
 				$request->setActionName('login');
@@ -111,7 +119,7 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
 	}
 
 
-	public function setUpSkin($module, $profil) {
+	protected function setUpSkin($module, $profil) {
 		$skindir = $profil->getPathTheme();
 		$url_skin = BASE_URL . $skindir;
 
@@ -119,10 +127,10 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
 	}
 
 
-	public function setUpBibZoneFilters($request) {
+	protected function setUpBibZoneFilters($request) {
 		if (!array_key_exists('admin', $_SESSION))
-			$_SESSION["admin"] = array("filtre_localisation" => array("id_zone" => 'ALL',
-																																"id_bib" => 'ALL'));
+			$_SESSION['admin'] = ['filtre_localisation' => ['id_zone' => 'ALL',
+																											'id_bib' => 'ALL']];
 			$session=$_SESSION["admin"]["filtre_localisation"];
 
 
diff --git a/tests/application/modules/opac/controllers/IndexControllerTest.php b/tests/application/modules/opac/controllers/IndexControllerTest.php
index 9f90a1fe56347097a9f35b7348128dd94f59196e..84f56aab41f3fd4e8043a54b1b9dd7c862593b81 100644
--- a/tests/application/modules/opac/controllers/IndexControllerTest.php
+++ b/tests/application/modules/opac/controllers/IndexControllerTest.php
@@ -232,4 +232,40 @@ class IndexControllerSitemapTest extends AbstractControllerTestCase {
 
 }
 
-?>
\ No newline at end of file
+
+
+class IndexControllerRewriteUrlTest extends AbstractControllerTestCase {
+	public function setUp() {
+		parent::setUp();
+
+		ZendAfi_Auth::getInstance()->logUser($this->fixture('Class_Users',
+																												['id' => 1,
+																												 'login' => 'guest',
+																												 'password' => 'guest',
+																												 'role_level' => ZendAfi_Acl_AdminControllerRoles::INVITE]));
+		$this->fixture('Class_Profil', ['id' => 345,
+																		'libelle' => 'Zork - Main',
+																		'parent_id' => null,
+																		'rewrite_url' => 'zork',
+																		'access_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]);
+
+		$this->fixture('Class_Profil', ['id' => 879,
+																		'libelle' => 'Zork - Child',
+																		'parent_id' => 345,
+																		'rewrite_url' => 'zork-child']);
+	}
+
+
+	/** @test */
+	public function privateProfilShouldRedirectToLogin() {
+		$this->dispatch('/zork', true);
+		$this->assertContains('/auth/login/id_profil/1?redirect=%2Findex%2Findex%2Fid_profil%2F345', $this->_response->getHeaders()[0]['value']);
+	}
+
+
+	/** @test */
+	public function publicProfilWithPrivateParentProfilShouldRedirectToLogin() {
+		$this->dispatch('/zork-child', true);
+		$this->assertContains('/auth/login/id_profil/1?redirect=%2Findex%2Findex%2Fid_profil%2F879', $this->_response->getHeaders()[0]['value']);
+	}
+}
\ No newline at end of file