-
Notifications
You must be signed in to change notification settings - Fork 697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor scrypt hashing and source app session mgmt pt 2/3 #5694
Refactor scrypt hashing and source app session mgmt pt 2/3 #5694
Conversation
acbf43f
to
3083589
Compare
@classmethod | ||
def log_user_in(cls, user: SourceUser, user_passphrase: "DicewarePassphrase") -> None: | ||
# Save the passphrase in the user's session cookie | ||
session[cls._KEY_IN_SESSION_COOKIE] = user_passphrase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This follows the same logic as the current code base, which is to put the user's passphrase in their session cookie (which is encrypted). I don't know if this is useful or not, but we could replace the passphrase in the cookie with a randomly-generated session ID.
3083589
to
e320129
Compare
d87ae38
to
ce9cbbe
Compare
# ignore_static here because `crypto_util.hash_codename` is scrypt | ||
# (very time consuming), and we don't need to waste time running if | ||
# we're just serving a static resource that won't need to access | ||
# these common values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer needed since I removed the "time consuming" scrypt call from the code that handles incoming requests.
del session['logged_in'] | ||
del session['codename'] | ||
return redirect(url_for('main.index')) | ||
g.loc = app.storage.path(g.filesystem_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the authentication and session logic in this file is now handled by the SessionManager, which is called when the @login_required
decorator is used in the Flask routes. This ensures that all authentication / session management logic happens in a single code location, thereby reducing complexity.
except UserNotLoggedIn: | ||
return redirect(url_for("main.login")) | ||
|
||
return f(*args, **kwargs, logged_in_source=logged_in_source) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The decorator directly passes the source user to the Flask route/code (to make the "data flow" more obvious/simple), so using flask.g or session (and checking that they are in the right "state") is no longer needed.
ce9cbbe
to
01675a4
Compare
logged_in_source = SessionManager.get_logged_in_user() | ||
|
||
except (UserSessionExpired, UserHasBeenDeleted): | ||
return clear_session_and_redirect_to_logged_out_page(session) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add compatibility layer for session management to reduce size of changes Make passphrase as the session cookie more obvious Cleanup test_source fixture and explicitely pass a db_session Clarify name Consolidate logout behavior Run black formatting Add tests for SessionManager Fix tests securedrop/requirements/python3/securedrop-app-code-requirements.in securedrop/requirements/python3/securedrop-app-code-requirements.txt
01675a4
to
7762ec2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running it on staging for a few days, no issues shown.
- verified Session expiry banner on the source index page #5716 is fixed
- verified Logged-out user is shown "You were logged out due to inactivity" and redirected to index page #5741 is fixed
- On g https://flask.palletsprojects.com/en/1.1.x/design/#thread-locals
Include tests, and also updates the apparmor
entries. Merging this now and then moving to the last PR in this set.
Awesome! |
We may have to revert this. While reviewing #5695 I noticed that sometimes using a second or third source at the same time is causing logout due to inactivity. And a a few times after updating to this session manager code, I can see that the source interface is not showing the source passphrase on the top. |
I can look into this. |
Thanks @nabla-c0d3 - if you wanna chat about it (even just for rubber-duck mode) folks are around on SD Gitter: https://gitter.im/freedomofpress/securedrop |
Thanks! It was the morning for me so I only got to this just now. Some thoughts/questions:
That's all I have for now... let me know your thoughts @kushaldas @zenmonkeykstop . Thanks! |
For the first issue, I managed to get the "logged out due to inactivity" error intermittently (about half the time) in a staging env by:
This isn't precisely what Kushal saw, though, and I haven't found a way to consistently replicate that yet. (Also as STRs go, it is as the kids say, kinda sus) Production (and staging) instances use Apache and mod_wsgi, and 2 processes are being spawned, so it's possible different requests will be served by different child processes. It might be better to back that change out as you mentioned. We could look at alternatives for subsequent releases. (The application uses Redis to cache GPG fingerprints already, but I think more work/research would be required before using it for full-on session management.) For the second issue (no passphrase on /lookup) - my understanding is that the scenario Kushal is describing is the passphrase not showing up on /lookup on first login. I haven't managed to replicate this yet though, and it could just be a misunderstanding, so focusing on the first issue seems like the best idea for now. |
I went through the steps you described a few times but I haven't been able to reproduce the logout errors/bugs. My environment might be different. Is your staging environment the same as running Regardless, I've updated the next PR at #5695 to remove the local cache, so that the whole session information is stored in the session cookie, like it was previously. This should get rid of these errors; I've tried it in my dev environment and it seemed to work fine. |
Hey @nabla-c0d3 - we have 3 types of environments, each with their own foibles:
Thanks for the updates (and for the knock-on updates to pr number 3 :) )! We'll take a pass through ASAP. |
Status
Ready.
Description of Changes
This PR follows #5692 .
pyotp
with equivalent functionality incryptography
#5613).