Repository: freedomofpress/securedrop

Issue:
Only show source codename on first session
# Feature request

## Description

A source is shown their codename on the `/lookup` page to help them remember it on their first session. This hint should not be shown again after the source logs out. The reason being is in the future, we maybe remove the actual codename from the cookie to prevent it from being used to login indefinitely (either by encrypting it or using some uuid that maps to the codename per session). If we show this on subsequent logins, an attack could steal the cookie, not learn the codename, but login see the codename, and then login again indefinitely.

Plus, is a source has logged in successfully, they definitely know their codename, and there is little (nothing?) to be gained by showing it again.


Discussion:
Adding hackathon, and some notes. This could be done simply by adding a single field to the session cookie that is only added on account creation and not login. The templates could check for that either as a standalone variable or in `g`.
Taking a look.

Might be nice to stop storing the codename from the session too.

Resolving patch:
diff --git a/securedrop/source_app/main.py b/securedrop/source_app/main.py
--- a/securedrop/source_app/main.py
+++ b/securedrop/source_app/main.py
@@ -38,6 +38,7 @@ def generate():
 
         codename = generate_unique_codename()
         session['codename'] = codename
+        session['new_user'] = True
         return render_template('generate.html', codename=codename)
 
     @view.route('/create', methods=['POST'])
@@ -91,6 +92,7 @@ def lookup():
             codename=g.codename,
             replies=replies,
             flagged=g.source.flagged,
+            new_user=session.get('new_user', None),
             haskey=crypto_util.getkey(
                 g.filesystem_id))
 


Test patch:
diff --git a/securedrop/tests/functional/source_navigation_steps.py b/securedrop/tests/functional/source_navigation_steps.py
--- a/securedrop/tests/functional/source_navigation_steps.py
+++ b/securedrop/tests/functional/source_navigation_steps.py
@@ -54,6 +54,9 @@ def _source_shows_codename(self):
         assert not content.is_displayed()
         self.driver.find_element_by_id('codename-hint-show').click()
         assert content.is_displayed()
+        content_content = self.driver.find_element_by_css_selector(
+                '#codename-hint-content p')
+        assert content_content.text == self.source_name
 
     def _source_hides_codename(self):
         content = self.driver.find_element_by_id('codename-hint-content')
@@ -61,6 +64,10 @@ def _source_hides_codename(self):
         self.driver.find_element_by_id('codename-hint-hide').click()
         assert not content.is_displayed()
 
+    def _source_sees_no_codename(self):
+        codename = self.driver.find_elements_by_css_selector('.code-reminder')
+        assert len(codename) == 0
+
     @screenshots
     def _source_chooses_to_login(self):
         self.driver.find_element_by_id('login-button').click()
@@ -90,6 +97,10 @@ def _source_proceeds_to_login(self):
 
         assert ("SecureDrop | Protecting Journalists and Sources" ==
                 self.driver.title)
+        # Check that we've logged in
+
+        replies = self.driver.find_elements_by_id("replies")
+        assert len(replies) == 1
 
     def _source_enters_codename_in_login_form(self):
         codename_input = self.driver.find_element_by_id(
diff --git a/securedrop/tests/functional/test_source.py b/securedrop/tests/functional/test_source.py
--- a/securedrop/tests/functional/test_source.py
+++ b/securedrop/tests/functional/test_source.py
@@ -12,3 +12,8 @@ def test_lookup_codename_hint(self):
         self._source_continues_to_submit_page()
         self._source_shows_codename()
         self._source_hides_codename()
+        self._source_logs_out()
+        self._source_visits_source_homepage()
+        self._source_chooses_to_login()
+        self._source_proceeds_to_login()
+        self._source_sees_no_codename()