diff --git a/migrations/Version20220114111659.php b/migrations/Version20220114111659.php
new file mode 100644
index 0000000000000000000000000000000000000000..f55bde648f089f8a8467e556cb140c02b950a309
--- /dev/null
+++ b/migrations/Version20220114111659.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+/**
+ * Auto-generated Migration: Please modify to your needs!
+ */
+final class Version20220114111659 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return '';
+    }
+
+    public function up(Schema $schema): void
+    {
+        // this up() migration is auto-generated, please modify it to your needs
+        $this->addSql('ALTER TABLE capsule ADD password VARCHAR(50) DEFAULT \'\' NOT NULL');
+    }
+
+    public function down(Schema $schema): void
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->addSql('ALTER TABLE capsule DROP password');
+    }
+}
diff --git a/src/Builder/CapsuleBuilder.php b/src/Builder/CapsuleBuilder.php
index ca49a830f33c313706ef5e35c10ecf98e2b427e9..ea2dca1beabf4beff755e34745592edb1aa0faba 100644
--- a/src/Builder/CapsuleBuilder.php
+++ b/src/Builder/CapsuleBuilder.php
@@ -15,6 +15,7 @@ class CapsuleBuilder
     private bool $hasRequiredPreviewLink = false;
     private bool $hasRequiredEditionLink = false;
     private bool $hasRequiredUpdateDate = false;
+    private bool $hasPasswordSet = false;
 
     public function __construct()
     {
@@ -50,11 +51,21 @@ class CapsuleBuilder
         return $this;
     }
 
-    public function withEditionLink(string $edition_link): CapsuleBuilder
+    private function createEditionLink(): void
     {
-        $this->capsule->setEditionLink($edition_link);
+        ContractHelper::requires(
+            $this->hasRequiredPreviewLink,
+            "The call of CapsuleBuilder::withPreviewLink should be " .
+            "called before CapsuleBuilder::createEditionLink"
+        );
+        ContractHelper::requires(
+            $this->hasPasswordSet,
+            "The call of CapsuleBuilder::withPassword should be " .
+            "called before CapsuleBuilder::createEditionLink"
+        );
+        $this->capsule->setEditionLink($this->capsule->getPreviewLink() .
+            "/?p=" . $this->capsule->getPassword());
         $this->hasRequiredEditionLink = true;
-        return $this;
     }
 
     public function withUpdateAuthor(User $update_author): CapsuleBuilder
@@ -70,8 +81,17 @@ class CapsuleBuilder
         return $this;
     }
 
+    public function withPassword(string $password): CapsuleBuilder
+    {
+        $this->capsule->setPassword($password);
+        $this->hasPasswordSet = true;
+
+        return $this;
+    }
+
     public function createCapsule(): Capsule
     {
+        $this->createEditionLink();
         ContractHelper::requires(
             $this->hasRequiredName,
             "The call of CapsuleBuilder::withName should be called before CapsuleBuilder::create"
@@ -96,6 +116,10 @@ class CapsuleBuilder
             $this->hasRequiredUpdateDate,
             "The call of CapsuleBuilder::withUpdateDate should be called before CapsuleBuilder::create"
         );
+        ContractHelper::requires(
+            $this->hasPasswordSet,
+            "The capsule should have its password defined"
+        );
 
         return $this->capsule;
     }
diff --git a/src/Builder/UserBuilder.php b/src/Builder/UserBuilder.php
index 639effabb6c42cc710a71aa33c7baf270c5fc7f4..12b29b7559821d3ce4d6c79aa3c701c368523d9c 100644
--- a/src/Builder/UserBuilder.php
+++ b/src/Builder/UserBuilder.php
@@ -54,6 +54,10 @@ class UserBuilder
 
     public function withPassword(string $password): UserBuilder
     {
+        ContractHelper::requires(
+            $this->hasRequiredSalt,
+            "The call of UserBuilder::withSalt should be called before UserBuilder::withPassword"
+        );
         $this->user->setPassword($this->password_hasher->hashPassword($this->user, $password));
         $this->hasRequiredPassword = true;
         return $this;
diff --git a/src/Controller/CapsuleController.php b/src/Controller/CapsuleController.php
index fc19bcc0f147acd5e04fce69f7f5dc93ecf86cab..6591914ff9bba923e51b64ae4eb89baef4237393 100644
--- a/src/Controller/CapsuleController.php
+++ b/src/Controller/CapsuleController.php
@@ -3,6 +3,7 @@
 namespace App\Controller;
 
 use App\Entity\User;
+use App\Helper\StringHelper;
 use App\Repository\CapsuleRepository;
 use App\Builder\CapsuleBuilder;
 use App\Form\CreateCapsuleFormType;
@@ -51,8 +52,8 @@ class CapsuleController extends AbstractController
             $new_date_time = new \DateTime();
             $capsule_name = $form->get('name')->getData();
             $video_url =  htmlspecialchars($form->get('video_url')->getData());
+            $password = StringHelper::generateRandomHashedString();
             $preview_link = Uuid::v4();
-            $edition_link = $preview_link . '/?p=edit';
 
             $entityManager = $this->getDoctrine()->getManager();
             $capsule_builder = new CapsuleBuilder();
@@ -61,8 +62,8 @@ class CapsuleController extends AbstractController
                 ->withCreationAuthor($current_user)
                 ->withCreationDate($new_date_time)
                 ->withPreviewLink($preview_link)
-                ->withEditionLink($edition_link)
                 ->withUpdateDate($new_date_time)
+                ->withPassword($password)
                 ->createCapsule();
 
             $entityManager->persist($capsule);
diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php
index 051935a01aa2f22fe6a20f1135dd82cbde11f696..3e089828a1f124c1c4e7e8fb1dc89ca6ed188744 100644
--- a/src/Controller/ProjectController.php
+++ b/src/Controller/ProjectController.php
@@ -7,6 +7,7 @@ use App\Exception\ZipArchiveNotOpeningException;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 use Symfony\Component\Config\Util\Exception\XmlParsingException;
 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
+use Symfony\Component\HttpFoundation\File\Exception\FileException;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Routing\Annotation\Route;
 use Symfony\Contracts\Translation\TranslatorInterface;
@@ -46,6 +47,8 @@ class ProjectController extends AbstractController
 
         $this->addProjectVideoUrlInXMLProjectFile($capsule_directory, $video_url);
 
+        $this->createOrUpdatePasswordFile($capsule_directory, $capsule->getPassword());
+
         $this->addFlash(
             'capsule_created_success',
             $translator->trans(
@@ -92,4 +95,10 @@ class ProjectController extends AbstractController
             throw new XmlParsingException('Video URL could not be written in XML project file');
         }
     }
+
+    private function createOrUpdatePasswordFile(string $capsule_directory, string $password): void
+    {
+        $project_password_file = $capsule_directory . "/file/projectPassword.txt";
+        file_put_contents($project_password_file, $password);
+    }
 }
diff --git a/src/DataFixtures/CapsuleFixtures.php b/src/DataFixtures/CapsuleFixtures.php
index 56b6ec4891a0062c27d6354b9f1de1b2a174a43f..0f2cb8ddbdd7365f38723aa15bf672d67087c422 100644
--- a/src/DataFixtures/CapsuleFixtures.php
+++ b/src/DataFixtures/CapsuleFixtures.php
@@ -38,13 +38,14 @@ class CapsuleFixtures extends Fixture implements DependentFixtureInterface
                 $new_date_time
             ) {
                 $uuid = Uuid::v4();
+                $password = sha1(random_bytes(100));
                 $builder
                     ->withName("Pomme")
                     ->withCreationAuthor($verified_user1)
                     ->withCreationDate($new_date_time)
                     ->withUpdateDate($new_date_time)
                     ->withPreviewLink($uuid)
-                    ->withEditionLink($uuid . '/?p=edit');
+                    ->withPassword($password);
             }
         );
 
@@ -54,13 +55,14 @@ class CapsuleFixtures extends Fixture implements DependentFixtureInterface
                 $new_date_time
             ) {
                 $uuid = Uuid::v4();
+                $password = sha1(random_bytes(100));
                 $builder
                     ->withName("Adele")
                     ->withCreationAuthor($verified_user2)
                     ->withCreationDate($new_date_time)
                     ->withUpdateDate($new_date_time)
                     ->withPreviewLink($uuid)
-                    ->withEditionLink($uuid . '/?p=edit');
+                    ->withPassword($password);
             }
         );
 
diff --git a/src/Entity/Capsule.php b/src/Entity/Capsule.php
index ef40356cb52556d41817803303b43d49a046f3cd..3b4a39d34504ce6550bee9852cb9c451d13c6d4b 100644
--- a/src/Entity/Capsule.php
+++ b/src/Entity/Capsule.php
@@ -70,6 +70,13 @@ class Capsule
      */
     private string $edition_link;
 
+    /**
+     * @var string the capsule edit password access
+     *
+     * @ORM\Column (name="password", type="string", length=50, nullable=false, options={"default":""})
+     */
+    private string $password;
+
     public function getId(): int
     {
         return $this->id;
@@ -155,4 +162,14 @@ class Capsule
     {
         $this->updated_date = $update_date;
     }
+
+    public function getPassword(): string
+    {
+        return $this->password;
+    }
+
+    public function setPassword(string $password): void
+    {
+        $this->password = $password;
+    }
 }
diff --git a/src/Helper/StringHelper.php b/src/Helper/StringHelper.php
new file mode 100644
index 0000000000000000000000000000000000000000..741c4b84bb14d94b471d081622462c3e1389d207
--- /dev/null
+++ b/src/Helper/StringHelper.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Helper;
+
+class StringHelper
+{
+    public static function generateRandomHashedString(): string
+    {
+        return strtoupper(sha1(random_bytes(100)));
+    }
+}
diff --git a/tests/functional/ProjectControllerTest.php b/tests/functional/ProjectControllerTest.php
index 0935ff7d8ce2025635d1ffe7f51f3a9164801c5f..8687740c2ca4321febcc4f93b38d65e5ac6b2753 100644
--- a/tests/functional/ProjectControllerTest.php
+++ b/tests/functional/ProjectControllerTest.php
@@ -87,6 +87,11 @@ class ProjectControllerTest extends WebTestCase
         return $this->getCapsuleDirPath($capsule_directory) . '/file/project.xml';
     }
 
+    private function getPasswordFilePath(string $capsule_directory): string
+    {
+        return $this->getCapsuleDirPath($capsule_directory) . '/file/projectPassword.txt';
+    }
+
     public function testProjectDirectoryWithCorrespondingXMLFileIsCreatedWhenCapsuleCreationIsSuccessful(): void
     {
         $video_url = "https://TestUrl";
@@ -129,4 +134,45 @@ class ProjectControllerTest extends WebTestCase
         $this->assertEquals($video_url, $video_url_in_xml_file);
         $this->assertSame(self::CAPSULE_NAME, $capsule_name_in_db);
     }
+
+    public function testProjectDirectoryWithCorrespondingPasswordFileIsCreatedWhenCapsuleCreationIsSuccessful(): void
+    {
+        $video_url = "https://TestUrl";
+        $this->form['create_capsule_form[name]'] = self::CAPSULE_NAME;
+        $this->form['create_capsule_form[video_url]'] = $video_url;
+
+        $this->client->submit($this->form);
+
+        $this->assertResponseRedirects(
+            '/my_capsules',
+            302,
+            'Once the capsule is created, the user should be redirected to its capsules lists'
+        );
+
+        $this->client->followRedirect();
+        $this->assertResponseIsSuccessful('/my_capsules');
+
+        $capsule_repository = $this->object_manager->getRepository(Capsule::class);
+        $capsule_in_db = $capsule_repository->findOneBy(['name' => self::CAPSULE_NAME]);
+
+        if (! $capsule_in_db instanceof Capsule) {
+            throw new \Exception("Capsule does not exist.");
+        }
+
+        $capsule_name_in_db = $capsule_in_db->getName();
+        $capsule_directory = $capsule_in_db->getPreviewLink();
+
+        $this->assertDirectoryExists($capsule_directory);
+        $this->assertDirectoryIsReadable($capsule_directory);
+
+        $password_file_path = $this->getPasswordFilePath($capsule_directory);
+        $password = file_get_contents($password_file_path, true);
+
+        $this->assertTrue(false !== $password, "The projectPassword.txt should be readable");
+        $this->assertSame(
+            $capsule_in_db->getPassword(),
+            $password,
+            "The password should be saved in projectPassword.txt file"
+        );
+    }
 }