-
Notifications
You must be signed in to change notification settings - Fork 687
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
Logout to revoke tokens #4349
Logout to revoke tokens #4349
Conversation
51480b8
to
1582036
Compare
securedrop/alembic/versions/e9fa666b089a_added_revoked_tokens_table.py
Outdated
Show resolved
Hide resolved
1582036
to
b2d91ce
Compare
Regarding the ever-increasing size of the blacklisted token table (cc @emkll @heartsucker), what about the following:
Thoughts? |
Actually we can skip step 1 and just try to validate the tokens as part of the function described in step 2, since expired tokens won't validate. |
I've implemented my suggestions above (since we are so close to the 0.13.0 cutoff, I didn't want to merge this without the cleanup of expired and revoked API tokens implemented). To facilitate testing from other people who are less familiar with the app code, I added more detailed steps to test in the PR description above, which I have followed to verify this functionality works as expected. If someone could inspect/approve my last four commits and comment here if they look good, then we can merge - I 👍 @heartsucker's changes (not explicitly approving this PR to prevent accidental merge of unreviewed code in my commits). |
I ran through the test plan, and it worked as expected. Took me a minute to realize I needed to make a request after restarting the server (steps 9 and 10) to get the expired revoked token purged, because before_first_request, but that got me wondering if Flask has a better place for housekeeping like this, like maybe record_once? Seems like it would be better to get this done without delaying any user request, though it's unlikely to take too long. Also, it's not clear to me from the Flask docs what happens when a function registered either way throws an exception -- do we need to be sure that doesn't happen? |
Agreed - and good idea re: |
I was afraid of something like that with |
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.
@redshiftzero's changes look good.
One follow up we may want to note is that an NTP based attack right at server/application boot could change the server time so that the token no longer validates so it is cleared from the table, but a second NTP update could reset the server to the actual time allowing an attacker to use the token. However, if the attacker managed to capture a token, we likely have much larger problems than this. I still think this should be documented for completeness.
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.
Looks good to me, both functionally and diff review.
Regarding @heartsucker 's point on ntp-based attacks, definitely worth tracking, but the risk is even lesser due to Tor bootstrapping and authenticated tor hidden services being sensitive to clock skew
Status
Ready for review
Description of Changes
Fixes #3933
Added a
/logout
endpoint to the API. Added arevoked_tokens
DB table.Test Plan
(edited by @redshiftzero)
Preconditions
TOKEN_EXPIRATION_MINS
insecuredrop/journalist_app/api.py
to a smaller value, like 5 minutes or so../manage.py run
withbash
insecuredrop/bin/run
(this is so we can re-run the dev server manually to check the token cleanup works as expected with all the dev env setup insecuredrop/bin/run
)Testing
make -C securedrop dev
./manage.py run
Confirm that you see a single row in this database and that it contains your token expired.
Provided it has been less than 5 minutes since you created that token restart the server and run once more with
./manage.py run
.Confirm that you can still not use this token (this confirms it was not removed from the database incorrectly):
Wait until 5 minutes have passed from when you first created this token (since we set 5 minutes as the expiration time) and restart the server one last time.
Confirm that the token is now gone from the revoked_tokens table in the database following the same steps as above:
(and for good measure if you like you can also verify that you still cannot use the token because it’s expired).
Deployment
Nothing special. Backwards compatible API change.
Checklist
If you made changes to the server application code:
make ci-lint
) and tests (make -C securedrop test
) pass in the development container